From be1ae792de797017f999b16cbea393451cced4fd Mon Sep 17 00:00:00 2001 From: Alexis Jacomy Date: Tue, 12 Mar 2024 14:06:29 +0100 Subject: [PATCH] [edge-curve] Drafts @sigma/edge-curve package This commit drafts the new edge-curve renderer, based on previous work by @Yomguithereal, in his sigma-experiments. It compiles, but it does not work as intended yet. TODO: - Fix missing part of the curve - Add custom canvas label renderer that follows the curvature --- package-lock.json | 13 +- package.json | 3 +- packages/edge-curve/.gitignore | 2 + packages/edge-curve/.npmignore | 4 + packages/edge-curve/package.json | 49 + packages/edge-curve/src/index.ts | 84 + packages/edge-curve/src/shader-frag.ts | 47 + packages/edge-curve/src/shader-vert.ts | 87 + .../src/stories/AllFeatures.stories.ts | 40 + packages/edge-curve/src/stories/data.json | 2808 +++++++++++++++++ packages/edge-curve/src/stories/stage.css | 4 + packages/edge-curve/tsconfig.json | 26 + packages/node-image/package.json | 2 +- packages/sigma/src/index-bundle.ts | 5 +- packages/website/docs/advanced/renderers.md | 1 + tsconfig.json | 3 +- 16 files changed, 3172 insertions(+), 6 deletions(-) create mode 100644 packages/edge-curve/.gitignore create mode 100644 packages/edge-curve/.npmignore create mode 100644 packages/edge-curve/package.json create mode 100644 packages/edge-curve/src/index.ts create mode 100644 packages/edge-curve/src/shader-frag.ts create mode 100644 packages/edge-curve/src/shader-vert.ts create mode 100644 packages/edge-curve/src/stories/AllFeatures.stories.ts create mode 100644 packages/edge-curve/src/stories/data.json create mode 100644 packages/edge-curve/src/stories/stage.css create mode 100644 packages/edge-curve/tsconfig.json diff --git a/package-lock.json b/package-lock.json index b59d7218f..b0604b590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6067,6 +6067,10 @@ "resolved": "packages/demo", "link": true }, + "node_modules/@sigma/edge-curve": { + "resolved": "packages/edge-curve", + "link": true + }, "node_modules/@sigma/node-image": { "resolved": "packages/node-image", "link": true @@ -34895,12 +34899,19 @@ "node": ">=10" } }, + "packages/edge-curve": { + "version": "3.0.0-beta.1", + "license": "MIT", + "peerDependencies": { + "sigma": ">=3.0.0-beta.10" + } + }, "packages/node-image": { "name": "@sigma/node-image", "version": "3.0.0-beta.5", "license": "MIT", "peerDependencies": { - "sigma": ">=3.0.0-beta.6" + "sigma": ">=3.0.0-beta.10" } }, "packages/sigma": { diff --git a/package.json b/package.json index 3efb85c4d..e4869d0c7 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "preconstruct": { "packages": [ "packages/sigma", - "packages/node-image" + "packages/node-image", + "packages/edge-curve" ] } } diff --git a/packages/edge-curve/.gitignore b/packages/edge-curve/.gitignore new file mode 100644 index 000000000..f06235c46 --- /dev/null +++ b/packages/edge-curve/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/packages/edge-curve/.npmignore b/packages/edge-curve/.npmignore new file mode 100644 index 000000000..0e9d6d53f --- /dev/null +++ b/packages/edge-curve/.npmignore @@ -0,0 +1,4 @@ +.gitignore +node_modules +src +tsconfig.json diff --git a/packages/edge-curve/package.json b/packages/edge-curve/package.json new file mode 100644 index 000000000..7dbc69eae --- /dev/null +++ b/packages/edge-curve/package.json @@ -0,0 +1,49 @@ +{ + "name": "@sigma/edge-curve", + "version": "3.0.0-beta.1", + "description": "An edge program that renders edges as curves for sigma.js", + "main": "dist/sigma-edge-curve.cjs.js", + "module": "dist/sigma-edge-curve.esm.js", + "types": "dist/sigma-edge-curve.cjs.d.ts", + "files": [ + "/dist" + ], + "sideEffects": false, + "homepage": "https://www.sigmajs.org", + "bugs": "http://github.com/jacomyal/sigma.js/issues", + "repository": { + "type": "git", + "url": "http://github.com/jacomyal/sigma.js.git" + }, + "keywords": [ + "graph", + "graphology", + "sigma" + ], + "contributors": [ + { + "name": "Guillaume Plique", + "url": "http://github.com/Yomguithereal" + }, + { + "name": "Alexis Jacomy", + "url": "http://github.com/jacomyal" + } + ], + "license": "MIT", + "preconstruct": { + "entrypoints": [ + "index.ts" + ] + }, + "peerDependencies": { + "sigma": ">=3.0.0-beta.10" + }, + "exports": { + ".": { + "module": "./dist/sigma-edge-curve.esm.js", + "import": "./dist/sigma-edge-curve.cjs.mjs", + "default": "./dist/sigma-edge-curve.cjs.js" + } + } +} diff --git a/packages/edge-curve/src/index.ts b/packages/edge-curve/src/index.ts new file mode 100644 index 000000000..67b2cc5e5 --- /dev/null +++ b/packages/edge-curve/src/index.ts @@ -0,0 +1,84 @@ +import { Attributes } from "graphology-types"; +import { EdgeProgram, ProgramInfo } from "sigma/rendering"; +import { EdgeDisplayData, NodeDisplayData, RenderParams } from "sigma/types"; +import { floatColor } from "sigma/utils"; + +import FRAGMENT_SHADER_SOURCE from "./shader-frag"; +import VERTEX_SHADER_SOURCE from "./shader-vert"; + +const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; + +const UNIFORMS = ["u_matrix", "u_sizeRatio", "u_dimensions", "u_pixelRatio"] as const; + +const DEFAULT_EDGE_CURVATURE = 0.25; + +export default class EdgeCurveProgram< + N extends Attributes = Attributes, + E extends Attributes = Attributes, + G extends Attributes = Attributes, +> extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> { + getDefinition() { + return { + VERTICES: 4, + VERTEX_SHADER_SOURCE, + FRAGMENT_SHADER_SOURCE, + METHOD: WebGLRenderingContext.TRIANGLES, + UNIFORMS, + ATTRIBUTES: [ + { name: "a_source", size: 2, type: FLOAT }, + { name: "a_target", size: 2, type: FLOAT }, + { name: "a_thickness", size: 1, type: FLOAT }, + { name: "a_curvature", size: 1, type: FLOAT }, + { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, + { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ], + CONSTANT_ATTRIBUTES: [ + { name: "a_current", size: 1, type: FLOAT }, // TODO: could optimize to bool + { name: "a_direction", size: 1, type: FLOAT }, // TODO: could optimize to byte + ], + CONSTANT_DATA: [ + [0, 1], + [0, -1], + [1, 1], + [1, -1], + ], + }; + } + + processVisibleItem( + edgeIndex: number, + startIndex: number, + sourceData: NodeDisplayData, + targetData: NodeDisplayData, + data: EdgeDisplayData & { curvature?: number }, + ) { + const thickness = data.size || 1; + const x1 = sourceData.x; + const y1 = sourceData.y; + const x2 = targetData.x; + const y2 = targetData.y; + const color = floatColor(data.color); + const curvature = typeof data.curvature === "number" ? data.curvature : DEFAULT_EDGE_CURVATURE; + + const array = this.array; + + // First point + array[startIndex++] = x1; + array[startIndex++] = y1; + array[startIndex++] = x2; + array[startIndex++] = y2; + array[startIndex++] = thickness; + array[startIndex++] = curvature; + array[startIndex++] = color; + array[startIndex++] = edgeIndex; + } + + setUniforms(params: RenderParams, { gl, uniformLocations }: ProgramInfo): void { + const { u_matrix, u_pixelRatio, u_sizeRatio, u_dimensions } = uniformLocations; + + gl.uniformMatrix3fv(u_matrix, false, params.matrix); + gl.uniform1f(u_pixelRatio, params.pixelRatio); + gl.uniform1f(u_sizeRatio, params.sizeRatio); + gl.uniform2f(u_dimensions, params.width * params.pixelRatio, params.height * params.pixelRatio); + } +} diff --git a/packages/edge-curve/src/shader-frag.ts b/packages/edge-curve/src/shader-frag.ts new file mode 100644 index 000000000..f5dcd848e --- /dev/null +++ b/packages/edge-curve/src/shader-frag.ts @@ -0,0 +1,47 @@ +// language=GLSL +const SHADER_SOURCE = /*glsl*/ ` +precision mediump float; + +varying vec4 v_color; +varying float v_thickness; +varying vec2 v_cpA; +varying vec2 v_cpB; +varying vec2 v_cpC; + +float det(vec2 a, vec2 b) { + return a.x * b.y - b.x * a.y; +} + +vec2 get_distance_vector(vec2 b0, vec2 b1, vec2 b2) { + float a = det(b0, b2), b = 2.0 * det(b1, b0), d = 2.0 * det(b2, b1); + float f = b * d - a * a; + vec2 d21 = b2 - b1, d10 = b1 - b0, d20 = b2 - b0; + vec2 gf = 2.0 * (b * d21 + d * d10 + a * d20); + gf = vec2(gf.y, -gf.x); + vec2 pp = -f * gf / dot(gf, gf); + vec2 d0p = b0 - pp; + float ap = det(d0p, d20), bp = 2.0 * det(d10, d0p); + float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0); + return mix(mix(b0, b1, t), mix(b1, b2, t), t); +} + +float distToQuadraticBezierCurve(vec2 p, vec2 b0, vec2 b1, vec2 b2) { + return length(get_distance_vector(b0 - p, b1 - p, b2 - p)); +} + +const float epsilon = 0.7; +const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0); + +void main(void) { + float dist = distToQuadraticBezierCurve(gl_FragCoord.xy, v_cpA, v_cpB, v_cpC); + + if (dist < v_thickness + epsilon) { + float inCurve = 1.0 - smoothstep(v_thickness - epsilon, v_thickness + epsilon, dist); + gl_FragColor = inCurve * vec4(v_color.rgb * v_color.a, v_color.a); + } else { + gl_FragColor = transparent; + } +} +`; + +export default SHADER_SOURCE; diff --git a/packages/edge-curve/src/shader-vert.ts b/packages/edge-curve/src/shader-vert.ts new file mode 100644 index 000000000..59bdc2762 --- /dev/null +++ b/packages/edge-curve/src/shader-vert.ts @@ -0,0 +1,87 @@ +// language=GLSL +const VERTEX_SHADER_SOURCE = /*glsl*/ ` +attribute vec4 a_color; +attribute float a_direction; +attribute float a_thickness; +attribute vec2 a_source; +attribute vec2 a_target; +attribute float a_current; +attribute float a_curvature; + +uniform mat3 u_matrix; +uniform float u_sizeRatio; +uniform float u_pixelRatio; +uniform vec2 u_dimensions; + +varying vec4 v_color; +varying float v_thickness; +varying vec2 v_cpA; +varying vec2 v_cpB; +varying vec2 v_cpC; + +const float bias = 255.0 / 254.0; +const float epsilon = 0.7; +const float minThickness = 0.3; + +vec2 clipspaceToViewport(vec2 pos, vec2 dimensions) { + return vec2( + (pos.x + 1.0) * dimensions.x / 2.0, + (pos.y + 1.0) * dimensions.y / 2.0 + ); +} + +vec2 viewportToClipspace(vec2 pos, vec2 dimensions) { + return vec2( + pos.x / dimensions.x * 2.0 - 1.0, + pos.y / dimensions.y * 2.0 - 1.0 + ); +} + +void main() { + // Selecting the correct position + // Branchless "position = a_source if a_current == 1.0 else a_target" + vec2 position = a_source * max(0.0, a_current) + a_target * max(0.0, 1.0 - a_current); + position = (u_matrix * vec3(position, 1)).xy; + + vec2 source = (u_matrix * vec3(a_source, 1)).xy; + vec2 target = (u_matrix * vec3(a_target, 1)).xy; + + vec2 viewportPosition = clipspaceToViewport(position, u_dimensions); + vec2 viewportSource = clipspaceToViewport(source, u_dimensions); + vec2 viewportTarget = clipspaceToViewport(target, u_dimensions); + + vec2 delta = viewportTarget.xy - viewportSource.xy; + float len = length(delta); + vec2 normal = vec2(-delta.y, delta.x) * a_direction; + vec2 unitNormal = normal / len; + float boundingBoxThickness = len * a_curvature; + float curveThickness = max(minThickness, a_thickness / 2.0 / u_sizeRatio * u_pixelRatio); + + v_thickness = curveThickness; + + v_cpA = viewportSource; + v_cpB = 0.5 * (viewportSource + viewportTarget) + unitNormal * a_direction * boundingBoxThickness; + v_cpC = viewportTarget; + + vec2 viewportOffsetPosition = ( + viewportPosition + + unitNormal * (boundingBoxThickness / 2.0 + curveThickness + epsilon) * + max(0.0, a_direction) // NOTE: cutting the bounding box in half to avoid overdraw + ); + + position = viewportToClipspace(viewportOffsetPosition, u_dimensions); + gl_Position = vec4(position, 0, 1); + + #ifdef PICKING_MODE + // For picking mode, we use the ID as the color: + v_color = a_id; + #else + // For normal mode, we use the color: + v_color = a_color; + #endif + + v_color.a *= bias; +} +`; + +export default VERTEX_SHADER_SOURCE; diff --git a/packages/edge-curve/src/stories/AllFeatures.stories.ts b/packages/edge-curve/src/stories/AllFeatures.stories.ts new file mode 100644 index 000000000..cd347bbcb --- /dev/null +++ b/packages/edge-curve/src/stories/AllFeatures.stories.ts @@ -0,0 +1,40 @@ +import { Meta, StoryObj } from "@storybook/html"; +import Graph from "graphology"; +import Sigma from "sigma"; + +import EdgeCurveProgram from "../index.ts"; +import data from "./data.json"; +import "./stage.css"; + +const createPictogramsStage = () => { + const stage = document.createElement("div"); + stage.classList.add("stage"); + + const graph = new Graph(); + graph.import(data); + + new Sigma(graph, stage, { + allowInvalidContainer: true, + defaultEdgeType: "curve", + edgeProgramClasses: { + curve: EdgeCurveProgram, + }, + }); + + return stage; +}; + +const meta: Meta = { + title: "edge-curve", + render: () => createPictogramsStage(), + parameters: { + layout: "fullscreen", + }, +}; + +export default meta; +type Story = StoryObj; + +export const ComparisonExample: Story = { + name: "All features at once", +}; diff --git a/packages/edge-curve/src/stories/data.json b/packages/edge-curve/src/stories/data.json new file mode 100644 index 000000000..0a8e7ba79 --- /dev/null +++ b/packages/edge-curve/src/stories/data.json @@ -0,0 +1,2808 @@ +{ + "nodes": [ + { + "key": "0.0", + "attributes": { + "x": 268.72385, + "y": 91.18155, + "size": 22.714287, + "label": "Myriel", + "color": "#D8482D" + } + }, + { + "key": "1.0", + "attributes": { + "x": 296.39902, + "y": 57.118374, + "size": 15, + "label": "Napoleon", + "color": "#B30000" + } + }, + { + "key": "2.0", + "attributes": { + "x": 248.45229, + "y": 52.22656, + "size": 16.714285, + "label": "MlleBaptistine", + "color": "#BB100A" + } + }, + { + "key": "3.0", + "attributes": { + "x": 224.83313, + "y": 98.01885, + "size": 16.714285, + "label": "MmeMagloire", + "color": "#BB100A" + } + }, + { + "key": "4.0", + "attributes": { + "x": 270.9098, + "y": 149.2961, + "size": 15, + "label": "CountessDeLo", + "color": "#B30000" + } + }, + { + "key": "5.0", + "attributes": { + "x": 318.6509, + "y": 85.41602, + "size": 15, + "label": "Geborand", + "color": "#B30000" + } + }, + { + "key": "6.0", + "attributes": { + "x": 330.3126, + "y": 117.94921, + "size": 15, + "label": "Champtercier", + "color": "#B30000" + } + }, + { + "key": "7.0", + "attributes": { + "x": 310.513, + "y": 155.66956, + "size": 15, + "label": "Cravatte", + "color": "#B30000" + } + }, + { + "key": "8.0", + "attributes": { + "x": 295.74683, + "y": 124.78035, + "size": 15, + "label": "Count", + "color": "#B30000" + } + }, + { + "key": "9.0", + "attributes": { + "x": 241.03372, + "y": 131.8897, + "size": 15, + "label": "OldMan", + "color": "#B30000" + } + }, + { + "key": "10.0", + "attributes": { + "x": -55.532795, + "y": -246.75798, + "size": 15, + "label": "Labarre", + "color": "#B30000" + } + }, + { + "key": "11.0", + "attributes": { + "x": -8.81755, + "y": -60.480377, + "size": 45, + "label": "Valjean", + "color": "#FEF0D9" + } + }, + { + "key": "12.0", + "attributes": { + "x": 116.85369, + "y": -100.77216, + "size": 15.857142, + "label": "Marguerite", + "color": "#B70805" + } + }, + { + "key": "13.0", + "attributes": { + "x": 78.10812, + "y": -16.99423, + "size": 15, + "label": "MmeDeR", + "color": "#B30000" + } + }, + { + "key": "14.0", + "attributes": { + "x": 47.669666, + "y": -96.23158, + "size": 15, + "label": "Isabeau", + "color": "#B30000" + } + }, + { + "key": "15.0", + "attributes": { + "x": 20.945133, + "y": -118.35298, + "size": 15, + "label": "Gervais", + "color": "#B30000" + } + }, + { + "key": "16.0", + "attributes": { + "x": 232.50653, + "y": -165.75543, + "size": 21.857143, + "label": "Tholomyes", + "color": "#D44028" + } + }, + { + "key": "17.0", + "attributes": { + "x": 322.50223, + "y": -210.94756, + "size": 20.142857, + "label": "Listolier", + "color": "#CC301E" + } + }, + { + "key": "18.0", + "attributes": { + "x": 322.0389, + "y": -162.5361, + "size": 20.142857, + "label": "Fameuil", + "color": "#CC301E" + } + }, + { + "key": "19.0", + "attributes": { + "x": 282.84045, + "y": -234.37758, + "size": 20.142857, + "label": "Blacheville", + "color": "#CC301E" + } + }, + { + "key": "20.0", + "attributes": { + "x": 282.14212, + "y": -141.3707, + "size": 20.142857, + "label": "Favourite", + "color": "#CC301E" + } + }, + { + "key": "21.0", + "attributes": { + "x": 279.24896, + "y": -186.69917, + "size": 20.142857, + "label": "Dahlia", + "color": "#CC301E" + } + }, + { + "key": "22.0", + "attributes": { + "x": 240.49136, + "y": -212.45226, + "size": 20.142857, + "label": "Zephine", + "color": "#CC301E" + } + }, + { + "key": "23.0", + "attributes": { + "x": 185.86234, + "y": -128.47615, + "size": 27, + "label": "Fantine", + "color": "#ED7047" + } + }, + { + "key": "24.0", + "attributes": { + "x": -15.730793, + "y": 46.37429, + "size": 23.57143, + "label": "MmeThenardier", + "color": "#DC5032" + } + }, + { + "key": "25.0", + "attributes": { + "x": 3.6068764, + "y": 98.60965, + "size": 27.857143, + "label": "Thenardier", + "color": "#F1784C" + } + }, + { + "key": "26.0", + "attributes": { + "x": -69.92912, + "y": -15.777599, + "size": 23.57143, + "label": "Cosette", + "color": "#DC5032" + } + }, + { + "key": "27.0", + "attributes": { + "x": 54.198936, + "y": 49.115128, + "size": 28.714287, + "label": "Javert", + "color": "#F58051" + } + }, + { + "key": "28.0", + "attributes": { + "x": 58.138313, + "y": -56.714897, + "size": 17.571428, + "label": "Fauchelevent", + "color": "#BF180F" + } + }, + { + "key": "29.0", + "attributes": { + "x": 97.39532, + "y": -157.35661, + "size": 21, + "label": "Bamatabois", + "color": "#D03823" + } + }, + { + "key": "30.0", + "attributes": { + "x": 157.66608, + "y": -88.86034, + "size": 15.857142, + "label": "Perpetue", + "color": "#B70805" + } + }, + { + "key": "31.0", + "attributes": { + "x": 130.24326, + "y": -62.113045, + "size": 17.571428, + "label": "Simplice", + "color": "#BF180F" + } + }, + { + "key": "32.0", + "attributes": { + "x": -31.725157, + "y": -124.8531, + "size": 15, + "label": "Scaufflaire", + "color": "#B30000" + } + }, + { + "key": "33.0", + "attributes": { + "x": 45.4282, + "y": -2.6807823, + "size": 15.857142, + "label": "Woman1", + "color": "#B70805" + } + }, + { + "key": "34.0", + "attributes": { + "x": -2.146402, + "y": -152.7878, + "size": 19.285715, + "label": "Judge", + "color": "#C72819" + } + }, + { + "key": "35.0", + "attributes": { + "x": 54.183117, + "y": -142.10239, + "size": 19.285715, + "label": "Champmathieu", + "color": "#C72819" + } + }, + { + "key": "36.0", + "attributes": { + "x": -21.096437, + "y": -192.47128, + "size": 19.285715, + "label": "Brevet", + "color": "#C72819" + } + }, + { + "key": "37.0", + "attributes": { + "x": 56.919018, + "y": -184.99847, + "size": 19.285715, + "label": "Chenildieu", + "color": "#C72819" + } + }, + { + "key": "38.0", + "attributes": { + "x": 21.456747, + "y": -211.19899, + "size": 19.285715, + "label": "Cochepaille", + "color": "#C72819" + } + }, + { + "key": "39.0", + "attributes": { + "x": -69.42261, + "y": 66.22773, + "size": 16.714285, + "label": "Pontmercy", + "color": "#BB100A" + } + }, + { + "key": "40.0", + "attributes": { + "x": 52.13746, + "y": 97.863976, + "size": 15, + "label": "Boulatruelle", + "color": "#B30000" + } + }, + { + "key": "41.0", + "attributes": { + "x": -84.15585, + "y": 140.50175, + "size": 23.57143, + "label": "Eponine", + "color": "#DC5032" + } + }, + { + "key": "42.0", + "attributes": { + "x": -47.696083, + "y": 112.90357, + "size": 16.714285, + "label": "Anzelma", + "color": "#BB100A" + } + }, + { + "key": "43.0", + "attributes": { + "x": 10.037987, + "y": 7.8234367, + "size": 16.714285, + "label": "Woman2", + "color": "#BB100A" + } + }, + { + "key": "44.0", + "attributes": { + "x": 82.99555, + "y": -87.651726, + "size": 15.857142, + "label": "MotherInnocent", + "color": "#B70805" + } + }, + { + "key": "45.0", + "attributes": { + "x": 94.93769, + "y": -47.799778, + "size": 15, + "label": "Gribier", + "color": "#B30000" + } + }, + { + "key": "46.0", + "attributes": { + "x": -293.23438, + "y": -146.10257, + "size": 15, + "label": "Jondrette", + "color": "#B30000" + } + }, + { + "key": "47.0", + "attributes": { + "x": -294.94247, + "y": -108.07895, + "size": 15.857142, + "label": "MmeBurgon", + "color": "#B70805" + } + }, + { + "key": "48.0", + "attributes": { + "x": -215.57619, + "y": 34.40003, + "size": 33, + "label": "Gavroche", + "color": "#FCA072" + } + }, + { + "key": "49.0", + "attributes": { + "x": -119.18742, + "y": -17.39732, + "size": 20.142857, + "label": "Gillenormand", + "color": "#CC301E" + } + }, + { + "key": "50.0", + "attributes": { + "x": -57.473045, + "y": 29.63873, + "size": 15.857142, + "label": "Magnon", + "color": "#B70805" + } + }, + { + "key": "51.0", + "attributes": { + "x": -93.255005, + "y": -60.657784, + "size": 20.142857, + "label": "MlleGillenormand", + "color": "#CC301E" + } + }, + { + "key": "52.0", + "attributes": { + "x": -93.764046, + "y": 22.565668, + "size": 15.857142, + "label": "MmePontmercy", + "color": "#B70805" + } + }, + { + "key": "53.0", + "attributes": { + "x": -132.14008, + "y": -66.85538, + "size": 15, + "label": "MlleVaubois", + "color": "#B30000" + } + }, + { + "key": "54.0", + "attributes": { + "x": -95.75337, + "y": -102.71505, + "size": 17.571428, + "label": "LtGillenormand", + "color": "#BF180F" + } + }, + { + "key": "55.0", + "attributes": { + "x": -142.15263, + "y": 36.388676, + "size": 30.428574, + "label": "Marius", + "color": "#FC8F5C" + } + }, + { + "key": "56.0", + "attributes": { + "x": -160.2533, + "y": -24.29684, + "size": 15.857142, + "label": "BaronessT", + "color": "#B70805" + } + }, + { + "key": "57.0", + "attributes": { + "x": -267.16248, + "y": 196.98003, + "size": 23.57143, + "label": "Mabeuf", + "color": "#DC5032" + } + }, + { + "key": "58.0", + "attributes": { + "x": -190.88988, + "y": 96.44671, + "size": 27, + "label": "Enjolras", + "color": "#ED7047" + } + }, + { + "key": "59.0", + "attributes": { + "x": -222.5417, + "y": 144.66484, + "size": 23.57143, + "label": "Combeferre", + "color": "#DC5032" + } + }, + { + "key": "60.0", + "attributes": { + "x": -325.61102, + "y": 166.71417, + "size": 21.857143, + "label": "Prouvaire", + "color": "#D44028" + } + }, + { + "key": "61.0", + "attributes": { + "x": -276.3468, + "y": 145.79153, + "size": 23.57143, + "label": "Feuilly", + "color": "#DC5032" + } + }, + { + "key": "62.0", + "attributes": { + "x": -251.45561, + "y": 97.83937, + "size": 25.285713, + "label": "Courfeyrac", + "color": "#E5603D" + } + }, + { + "key": "63.0", + "attributes": { + "x": -318.40936, + "y": 114.202415, + "size": 24.428572, + "label": "Bahorel", + "color": "#E05837" + } + }, + { + "key": "64.0", + "attributes": { + "x": -278.9682, + "y": 45.932438, + "size": 25.285713, + "label": "Bossuet", + "color": "#E5603D" + } + }, + { + "key": "65.0", + "attributes": { + "x": -333.04984, + "y": 62.438156, + "size": 24.428572, + "label": "Joly", + "color": "#E05837" + } + }, + { + "key": "66.0", + "attributes": { + "x": -370.2446, + "y": 101.73884, + "size": 22.714287, + "label": "Grantaire", + "color": "#D8482D" + } + }, + { + "key": "67.0", + "attributes": { + "x": -253.54378, + "y": 237.9443, + "size": 15, + "label": "MotherPlutarch", + "color": "#B30000" + } + }, + { + "key": "68.0", + "attributes": { + "x": -16.550194, + "y": 152.69055, + "size": 22.714287, + "label": "Gueulemer", + "color": "#D8482D" + } + }, + { + "key": "69.0", + "attributes": { + "x": 35.653145, + "y": 144.49445, + "size": 22.714287, + "label": "Babet", + "color": "#D8482D" + } + }, + { + "key": "70.0", + "attributes": { + "x": 58.97649, + "y": 188.46011, + "size": 22.714287, + "label": "Claquesous", + "color": "#D8482D" + } + }, + { + "key": "71.0", + "attributes": { + "x": -2.9325058, + "y": 200.66508, + "size": 21.857143, + "label": "Montparnasse", + "color": "#D44028" + } + }, + { + "key": "72.0", + "attributes": { + "x": -30.056648, + "y": 3.5053203, + "size": 16.714285, + "label": "Toussaint", + "color": "#BB100A" + } + }, + { + "key": "73.0", + "attributes": { + "x": -244.859, + "y": -11.3161335, + "size": 15.857142, + "label": "Child1", + "color": "#B70805" + } + }, + { + "key": "74.0", + "attributes": { + "x": -280.33203, + "y": -1.466383, + "size": 15.857142, + "label": "Child2", + "color": "#B70805" + } + }, + { + "key": "75.0", + "attributes": { + "x": -56.819256, + "y": 182.0544, + "size": 20.142857, + "label": "Brujon", + "color": "#CC301E" + } + }, + { + "key": "76.0", + "attributes": { + "x": -382.06223, + "y": 47.045475, + "size": 20.142857, + "label": "MmeHucheloup", + "color": "#CC301E" + } + } + ], + "edges": [ + { + "key": "0", + "source": "1.0", + "target": "0.0", + "attributes": { + "size": 1 + } + }, + { + "key": "1", + "source": "2.0", + "target": "0.0", + "attributes": { + "size": 8 + } + }, + { + "key": "2", + "source": "3.0", + "target": "0.0", + "attributes": { + "size": 10 + } + }, + { + "key": "3", + "source": "3.0", + "target": "2.0", + "attributes": { + "size": 6 + } + }, + { + "key": "4", + "source": "4.0", + "target": "0.0", + "attributes": { + "size": 1 + } + }, + { + "key": "5", + "source": "5.0", + "target": "0.0", + "attributes": { + "size": 1 + } + }, + { + "key": "6", + "source": "6.0", + "target": "0.0", + "attributes": { + "size": 1 + } + }, + { + "key": "7", + "source": "7.0", + "target": "0.0", + "attributes": { + "size": 1 + } + }, + { + "key": "8", + "source": "8.0", + "target": "0.0", + "attributes": { + "size": 2 + } + }, + { + "key": "9", + "source": "9.0", + "target": "0.0", + "attributes": { + "size": 1 + } + }, + { + "key": "13", + "source": "11.0", + "target": "0.0", + "attributes": { + "size": 5 + } + }, + { + "key": "12", + "source": "11.0", + "target": "2.0", + "attributes": { + "size": 3 + } + }, + { + "key": "11", + "source": "11.0", + "target": "3.0", + "attributes": { + "size": 3 + } + }, + { + "key": "10", + "source": "11.0", + "target": "10.0", + "attributes": { + "size": 1 + } + }, + { + "key": "14", + "source": "12.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "15", + "source": "13.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "16", + "source": "14.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "17", + "source": "15.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "18", + "source": "17.0", + "target": "16.0", + "attributes": { + "size": 4 + } + }, + { + "key": "19", + "source": "18.0", + "target": "16.0", + "attributes": { + "size": 4 + } + }, + { + "key": "20", + "source": "18.0", + "target": "17.0", + "attributes": { + "size": 4 + } + }, + { + "key": "21", + "source": "19.0", + "target": "16.0", + "attributes": { + "size": 4 + } + }, + { + "key": "22", + "source": "19.0", + "target": "17.0", + "attributes": { + "size": 4 + } + }, + { + "key": "23", + "source": "19.0", + "target": "18.0", + "attributes": { + "size": 4 + } + }, + { + "key": "24", + "source": "20.0", + "target": "16.0", + "attributes": { + "size": 3 + } + }, + { + "key": "25", + "source": "20.0", + "target": "17.0", + "attributes": { + "size": 3 + } + }, + { + "key": "26", + "source": "20.0", + "target": "18.0", + "attributes": { + "size": 3 + } + }, + { + "key": "27", + "source": "20.0", + "target": "19.0", + "attributes": { + "size": 4 + } + }, + { + "key": "28", + "source": "21.0", + "target": "16.0", + "attributes": { + "size": 3 + } + }, + { + "key": "29", + "source": "21.0", + "target": "17.0", + "attributes": { + "size": 3 + } + }, + { + "key": "30", + "source": "21.0", + "target": "18.0", + "attributes": { + "size": 3 + } + }, + { + "key": "31", + "source": "21.0", + "target": "19.0", + "attributes": { + "size": 3 + } + }, + { + "key": "32", + "source": "21.0", + "target": "20.0", + "attributes": { + "size": 5 + } + }, + { + "key": "33", + "source": "22.0", + "target": "16.0", + "attributes": { + "size": 3 + } + }, + { + "key": "34", + "source": "22.0", + "target": "17.0", + "attributes": { + "size": 3 + } + }, + { + "key": "35", + "source": "22.0", + "target": "18.0", + "attributes": { + "size": 3 + } + }, + { + "key": "36", + "source": "22.0", + "target": "19.0", + "attributes": { + "size": 3 + } + }, + { + "key": "37", + "source": "22.0", + "target": "20.0", + "attributes": { + "size": 4 + } + }, + { + "key": "38", + "source": "22.0", + "target": "21.0", + "attributes": { + "size": 4 + } + }, + { + "key": "47", + "source": "23.0", + "target": "11.0", + "attributes": { + "size": 9 + } + }, + { + "key": "46", + "source": "23.0", + "target": "12.0", + "attributes": { + "size": 2 + } + }, + { + "key": "39", + "source": "23.0", + "target": "16.0", + "attributes": { + "size": 3 + } + }, + { + "key": "40", + "source": "23.0", + "target": "17.0", + "attributes": { + "size": 3 + } + }, + { + "key": "41", + "source": "23.0", + "target": "18.0", + "attributes": { + "size": 3 + } + }, + { + "key": "42", + "source": "23.0", + "target": "19.0", + "attributes": { + "size": 3 + } + }, + { + "key": "43", + "source": "23.0", + "target": "20.0", + "attributes": { + "size": 4 + } + }, + { + "key": "44", + "source": "23.0", + "target": "21.0", + "attributes": { + "size": 4 + } + }, + { + "key": "45", + "source": "23.0", + "target": "22.0", + "attributes": { + "size": 4 + } + }, + { + "key": "49", + "source": "24.0", + "target": "11.0", + "attributes": { + "size": 7 + } + }, + { + "key": "48", + "source": "24.0", + "target": "23.0", + "attributes": { + "size": 2 + } + }, + { + "key": "52", + "source": "25.0", + "target": "11.0", + "attributes": { + "size": 12 + } + }, + { + "key": "51", + "source": "25.0", + "target": "23.0", + "attributes": { + "size": 1 + } + }, + { + "key": "50", + "source": "25.0", + "target": "24.0", + "attributes": { + "size": 13 + } + }, + { + "key": "54", + "source": "26.0", + "target": "11.0", + "attributes": { + "size": 31 + } + }, + { + "key": "55", + "source": "26.0", + "target": "16.0", + "attributes": { + "size": 1 + } + }, + { + "key": "53", + "source": "26.0", + "target": "24.0", + "attributes": { + "size": 4 + } + }, + { + "key": "56", + "source": "26.0", + "target": "25.0", + "attributes": { + "size": 1 + } + }, + { + "key": "57", + "source": "27.0", + "target": "11.0", + "attributes": { + "size": 17 + } + }, + { + "key": "58", + "source": "27.0", + "target": "23.0", + "attributes": { + "size": 5 + } + }, + { + "key": "60", + "source": "27.0", + "target": "24.0", + "attributes": { + "size": 1 + } + }, + { + "key": "59", + "source": "27.0", + "target": "25.0", + "attributes": { + "size": 5 + } + }, + { + "key": "61", + "source": "27.0", + "target": "26.0", + "attributes": { + "size": 1 + } + }, + { + "key": "62", + "source": "28.0", + "target": "11.0", + "attributes": { + "size": 8 + } + }, + { + "key": "63", + "source": "28.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "66", + "source": "29.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "64", + "source": "29.0", + "target": "23.0", + "attributes": { + "size": 1 + } + }, + { + "key": "65", + "source": "29.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "67", + "source": "30.0", + "target": "23.0", + "attributes": { + "size": 1 + } + }, + { + "key": "69", + "source": "31.0", + "target": "11.0", + "attributes": { + "size": 3 + } + }, + { + "key": "70", + "source": "31.0", + "target": "23.0", + "attributes": { + "size": 2 + } + }, + { + "key": "71", + "source": "31.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "68", + "source": "31.0", + "target": "30.0", + "attributes": { + "size": 2 + } + }, + { + "key": "72", + "source": "32.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "73", + "source": "33.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "74", + "source": "33.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "75", + "source": "34.0", + "target": "11.0", + "attributes": { + "size": 3 + } + }, + { + "key": "76", + "source": "34.0", + "target": "29.0", + "attributes": { + "size": 2 + } + }, + { + "key": "77", + "source": "35.0", + "target": "11.0", + "attributes": { + "size": 3 + } + }, + { + "key": "79", + "source": "35.0", + "target": "29.0", + "attributes": { + "size": 2 + } + }, + { + "key": "78", + "source": "35.0", + "target": "34.0", + "attributes": { + "size": 3 + } + }, + { + "key": "82", + "source": "36.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "83", + "source": "36.0", + "target": "29.0", + "attributes": { + "size": 1 + } + }, + { + "key": "80", + "source": "36.0", + "target": "34.0", + "attributes": { + "size": 2 + } + }, + { + "key": "81", + "source": "36.0", + "target": "35.0", + "attributes": { + "size": 2 + } + }, + { + "key": "87", + "source": "37.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "88", + "source": "37.0", + "target": "29.0", + "attributes": { + "size": 1 + } + }, + { + "key": "84", + "source": "37.0", + "target": "34.0", + "attributes": { + "size": 2 + } + }, + { + "key": "85", + "source": "37.0", + "target": "35.0", + "attributes": { + "size": 2 + } + }, + { + "key": "86", + "source": "37.0", + "target": "36.0", + "attributes": { + "size": 2 + } + }, + { + "key": "93", + "source": "38.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "94", + "source": "38.0", + "target": "29.0", + "attributes": { + "size": 1 + } + }, + { + "key": "89", + "source": "38.0", + "target": "34.0", + "attributes": { + "size": 2 + } + }, + { + "key": "90", + "source": "38.0", + "target": "35.0", + "attributes": { + "size": 2 + } + }, + { + "key": "91", + "source": "38.0", + "target": "36.0", + "attributes": { + "size": 2 + } + }, + { + "key": "92", + "source": "38.0", + "target": "37.0", + "attributes": { + "size": 2 + } + }, + { + "key": "95", + "source": "39.0", + "target": "25.0", + "attributes": { + "size": 1 + } + }, + { + "key": "96", + "source": "40.0", + "target": "25.0", + "attributes": { + "size": 1 + } + }, + { + "key": "97", + "source": "41.0", + "target": "24.0", + "attributes": { + "size": 2 + } + }, + { + "key": "98", + "source": "41.0", + "target": "25.0", + "attributes": { + "size": 3 + } + }, + { + "key": "101", + "source": "42.0", + "target": "24.0", + "attributes": { + "size": 1 + } + }, + { + "key": "100", + "source": "42.0", + "target": "25.0", + "attributes": { + "size": 2 + } + }, + { + "key": "99", + "source": "42.0", + "target": "41.0", + "attributes": { + "size": 2 + } + }, + { + "key": "102", + "source": "43.0", + "target": "11.0", + "attributes": { + "size": 3 + } + }, + { + "key": "103", + "source": "43.0", + "target": "26.0", + "attributes": { + "size": 1 + } + }, + { + "key": "104", + "source": "43.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "106", + "source": "44.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "105", + "source": "44.0", + "target": "28.0", + "attributes": { + "size": 3 + } + }, + { + "key": "107", + "source": "45.0", + "target": "28.0", + "attributes": { + "size": 2 + } + }, + { + "key": "108", + "source": "47.0", + "target": "46.0", + "attributes": { + "size": 1 + } + }, + { + "key": "112", + "source": "48.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "110", + "source": "48.0", + "target": "25.0", + "attributes": { + "size": 1 + } + }, + { + "key": "111", + "source": "48.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "109", + "source": "48.0", + "target": "47.0", + "attributes": { + "size": 2 + } + }, + { + "key": "114", + "source": "49.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "113", + "source": "49.0", + "target": "26.0", + "attributes": { + "size": 3 + } + }, + { + "key": "116", + "source": "50.0", + "target": "24.0", + "attributes": { + "size": 1 + } + }, + { + "key": "115", + "source": "50.0", + "target": "49.0", + "attributes": { + "size": 1 + } + }, + { + "key": "119", + "source": "51.0", + "target": "11.0", + "attributes": { + "size": 2 + } + }, + { + "key": "118", + "source": "51.0", + "target": "26.0", + "attributes": { + "size": 2 + } + }, + { + "key": "117", + "source": "51.0", + "target": "49.0", + "attributes": { + "size": 9 + } + }, + { + "key": "121", + "source": "52.0", + "target": "39.0", + "attributes": { + "size": 1 + } + }, + { + "key": "120", + "source": "52.0", + "target": "51.0", + "attributes": { + "size": 1 + } + }, + { + "key": "122", + "source": "53.0", + "target": "51.0", + "attributes": { + "size": 1 + } + }, + { + "key": "125", + "source": "54.0", + "target": "26.0", + "attributes": { + "size": 1 + } + }, + { + "key": "124", + "source": "54.0", + "target": "49.0", + "attributes": { + "size": 1 + } + }, + { + "key": "123", + "source": "54.0", + "target": "51.0", + "attributes": { + "size": 2 + } + }, + { + "key": "131", + "source": "55.0", + "target": "11.0", + "attributes": { + "size": 19 + } + }, + { + "key": "132", + "source": "55.0", + "target": "16.0", + "attributes": { + "size": 1 + } + }, + { + "key": "133", + "source": "55.0", + "target": "25.0", + "attributes": { + "size": 2 + } + }, + { + "key": "130", + "source": "55.0", + "target": "26.0", + "attributes": { + "size": 21 + } + }, + { + "key": "128", + "source": "55.0", + "target": "39.0", + "attributes": { + "size": 1 + } + }, + { + "key": "134", + "source": "55.0", + "target": "41.0", + "attributes": { + "size": 5 + } + }, + { + "key": "135", + "source": "55.0", + "target": "48.0", + "attributes": { + "size": 4 + } + }, + { + "key": "127", + "source": "55.0", + "target": "49.0", + "attributes": { + "size": 12 + } + }, + { + "key": "126", + "source": "55.0", + "target": "51.0", + "attributes": { + "size": 6 + } + }, + { + "key": "129", + "source": "55.0", + "target": "54.0", + "attributes": { + "size": 1 + } + }, + { + "key": "136", + "source": "56.0", + "target": "49.0", + "attributes": { + "size": 1 + } + }, + { + "key": "137", + "source": "56.0", + "target": "55.0", + "attributes": { + "size": 1 + } + }, + { + "key": "139", + "source": "57.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "140", + "source": "57.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "138", + "source": "57.0", + "target": "55.0", + "attributes": { + "size": 1 + } + }, + { + "key": "145", + "source": "58.0", + "target": "11.0", + "attributes": { + "size": 4 + } + }, + { + "key": "143", + "source": "58.0", + "target": "27.0", + "attributes": { + "size": 6 + } + }, + { + "key": "142", + "source": "58.0", + "target": "48.0", + "attributes": { + "size": 7 + } + }, + { + "key": "141", + "source": "58.0", + "target": "55.0", + "attributes": { + "size": 7 + } + }, + { + "key": "144", + "source": "58.0", + "target": "57.0", + "attributes": { + "size": 1 + } + }, + { + "key": "148", + "source": "59.0", + "target": "48.0", + "attributes": { + "size": 6 + } + }, + { + "key": "147", + "source": "59.0", + "target": "55.0", + "attributes": { + "size": 5 + } + }, + { + "key": "149", + "source": "59.0", + "target": "57.0", + "attributes": { + "size": 2 + } + }, + { + "key": "146", + "source": "59.0", + "target": "58.0", + "attributes": { + "size": 15 + } + }, + { + "key": "150", + "source": "60.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "151", + "source": "60.0", + "target": "58.0", + "attributes": { + "size": 4 + } + }, + { + "key": "152", + "source": "60.0", + "target": "59.0", + "attributes": { + "size": 2 + } + }, + { + "key": "153", + "source": "61.0", + "target": "48.0", + "attributes": { + "size": 2 + } + }, + { + "key": "158", + "source": "61.0", + "target": "55.0", + "attributes": { + "size": 1 + } + }, + { + "key": "157", + "source": "61.0", + "target": "57.0", + "attributes": { + "size": 1 + } + }, + { + "key": "154", + "source": "61.0", + "target": "58.0", + "attributes": { + "size": 6 + } + }, + { + "key": "156", + "source": "61.0", + "target": "59.0", + "attributes": { + "size": 5 + } + }, + { + "key": "155", + "source": "61.0", + "target": "60.0", + "attributes": { + "size": 2 + } + }, + { + "key": "164", + "source": "62.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "162", + "source": "62.0", + "target": "48.0", + "attributes": { + "size": 7 + } + }, + { + "key": "159", + "source": "62.0", + "target": "55.0", + "attributes": { + "size": 9 + } + }, + { + "key": "163", + "source": "62.0", + "target": "57.0", + "attributes": { + "size": 2 + } + }, + { + "key": "160", + "source": "62.0", + "target": "58.0", + "attributes": { + "size": 17 + } + }, + { + "key": "161", + "source": "62.0", + "target": "59.0", + "attributes": { + "size": 13 + } + }, + { + "key": "166", + "source": "62.0", + "target": "60.0", + "attributes": { + "size": 3 + } + }, + { + "key": "165", + "source": "62.0", + "target": "61.0", + "attributes": { + "size": 6 + } + }, + { + "key": "168", + "source": "63.0", + "target": "48.0", + "attributes": { + "size": 5 + } + }, + { + "key": "174", + "source": "63.0", + "target": "55.0", + "attributes": { + "size": 1 + } + }, + { + "key": "170", + "source": "63.0", + "target": "57.0", + "attributes": { + "size": 2 + } + }, + { + "key": "171", + "source": "63.0", + "target": "58.0", + "attributes": { + "size": 4 + } + }, + { + "key": "167", + "source": "63.0", + "target": "59.0", + "attributes": { + "size": 5 + } + }, + { + "key": "173", + "source": "63.0", + "target": "60.0", + "attributes": { + "size": 2 + } + }, + { + "key": "172", + "source": "63.0", + "target": "61.0", + "attributes": { + "size": 3 + } + }, + { + "key": "169", + "source": "63.0", + "target": "62.0", + "attributes": { + "size": 6 + } + }, + { + "key": "184", + "source": "64.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "177", + "source": "64.0", + "target": "48.0", + "attributes": { + "size": 5 + } + }, + { + "key": "175", + "source": "64.0", + "target": "55.0", + "attributes": { + "size": 5 + } + }, + { + "key": "183", + "source": "64.0", + "target": "57.0", + "attributes": { + "size": 1 + } + }, + { + "key": "179", + "source": "64.0", + "target": "58.0", + "attributes": { + "size": 10 + } + }, + { + "key": "182", + "source": "64.0", + "target": "59.0", + "attributes": { + "size": 9 + } + }, + { + "key": "181", + "source": "64.0", + "target": "60.0", + "attributes": { + "size": 2 + } + }, + { + "key": "180", + "source": "64.0", + "target": "61.0", + "attributes": { + "size": 6 + } + }, + { + "key": "176", + "source": "64.0", + "target": "62.0", + "attributes": { + "size": 12 + } + }, + { + "key": "178", + "source": "64.0", + "target": "63.0", + "attributes": { + "size": 4 + } + }, + { + "key": "187", + "source": "65.0", + "target": "48.0", + "attributes": { + "size": 3 + } + }, + { + "key": "194", + "source": "65.0", + "target": "55.0", + "attributes": { + "size": 2 + } + }, + { + "key": "193", + "source": "65.0", + "target": "57.0", + "attributes": { + "size": 1 + } + }, + { + "key": "189", + "source": "65.0", + "target": "58.0", + "attributes": { + "size": 5 + } + }, + { + "key": "192", + "source": "65.0", + "target": "59.0", + "attributes": { + "size": 5 + } + }, + { + "key": "191", + "source": "65.0", + "target": "60.0", + "attributes": { + "size": 2 + } + }, + { + "key": "190", + "source": "65.0", + "target": "61.0", + "attributes": { + "size": 5 + } + }, + { + "key": "188", + "source": "65.0", + "target": "62.0", + "attributes": { + "size": 5 + } + }, + { + "key": "185", + "source": "65.0", + "target": "63.0", + "attributes": { + "size": 5 + } + }, + { + "key": "186", + "source": "65.0", + "target": "64.0", + "attributes": { + "size": 7 + } + }, + { + "key": "200", + "source": "66.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "196", + "source": "66.0", + "target": "58.0", + "attributes": { + "size": 3 + } + }, + { + "key": "197", + "source": "66.0", + "target": "59.0", + "attributes": { + "size": 1 + } + }, + { + "key": "203", + "source": "66.0", + "target": "60.0", + "attributes": { + "size": 1 + } + }, + { + "key": "202", + "source": "66.0", + "target": "61.0", + "attributes": { + "size": 1 + } + }, + { + "key": "198", + "source": "66.0", + "target": "62.0", + "attributes": { + "size": 2 + } + }, + { + "key": "201", + "source": "66.0", + "target": "63.0", + "attributes": { + "size": 1 + } + }, + { + "key": "195", + "source": "66.0", + "target": "64.0", + "attributes": { + "size": 3 + } + }, + { + "key": "199", + "source": "66.0", + "target": "65.0", + "attributes": { + "size": 2 + } + }, + { + "key": "204", + "source": "67.0", + "target": "57.0", + "attributes": { + "size": 3 + } + }, + { + "key": "206", + "source": "68.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "207", + "source": "68.0", + "target": "24.0", + "attributes": { + "size": 1 + } + }, + { + "key": "205", + "source": "68.0", + "target": "25.0", + "attributes": { + "size": 5 + } + }, + { + "key": "208", + "source": "68.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "210", + "source": "68.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "209", + "source": "68.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "213", + "source": "69.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "214", + "source": "69.0", + "target": "24.0", + "attributes": { + "size": 1 + } + }, + { + "key": "211", + "source": "69.0", + "target": "25.0", + "attributes": { + "size": 6 + } + }, + { + "key": "215", + "source": "69.0", + "target": "27.0", + "attributes": { + "size": 2 + } + }, + { + "key": "217", + "source": "69.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "216", + "source": "69.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "212", + "source": "69.0", + "target": "68.0", + "attributes": { + "size": 6 + } + }, + { + "key": "221", + "source": "70.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "222", + "source": "70.0", + "target": "24.0", + "attributes": { + "size": 1 + } + }, + { + "key": "218", + "source": "70.0", + "target": "25.0", + "attributes": { + "size": 4 + } + }, + { + "key": "223", + "source": "70.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "224", + "source": "70.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "225", + "source": "70.0", + "target": "58.0", + "attributes": { + "size": 1 + } + }, + { + "key": "220", + "source": "70.0", + "target": "68.0", + "attributes": { + "size": 4 + } + }, + { + "key": "219", + "source": "70.0", + "target": "69.0", + "attributes": { + "size": 4 + } + }, + { + "key": "230", + "source": "71.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "233", + "source": "71.0", + "target": "25.0", + "attributes": { + "size": 1 + } + }, + { + "key": "226", + "source": "71.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "232", + "source": "71.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "231", + "source": "71.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "228", + "source": "71.0", + "target": "68.0", + "attributes": { + "size": 2 + } + }, + { + "key": "227", + "source": "71.0", + "target": "69.0", + "attributes": { + "size": 2 + } + }, + { + "key": "229", + "source": "71.0", + "target": "70.0", + "attributes": { + "size": 2 + } + }, + { + "key": "236", + "source": "72.0", + "target": "11.0", + "attributes": { + "size": 1 + } + }, + { + "key": "234", + "source": "72.0", + "target": "26.0", + "attributes": { + "size": 2 + } + }, + { + "key": "235", + "source": "72.0", + "target": "27.0", + "attributes": { + "size": 1 + } + }, + { + "key": "237", + "source": "73.0", + "target": "48.0", + "attributes": { + "size": 2 + } + }, + { + "key": "238", + "source": "74.0", + "target": "48.0", + "attributes": { + "size": 2 + } + }, + { + "key": "239", + "source": "74.0", + "target": "73.0", + "attributes": { + "size": 3 + } + }, + { + "key": "242", + "source": "75.0", + "target": "25.0", + "attributes": { + "size": 3 + } + }, + { + "key": "244", + "source": "75.0", + "target": "41.0", + "attributes": { + "size": 1 + } + }, + { + "key": "243", + "source": "75.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "241", + "source": "75.0", + "target": "68.0", + "attributes": { + "size": 3 + } + }, + { + "key": "240", + "source": "75.0", + "target": "69.0", + "attributes": { + "size": 3 + } + }, + { + "key": "245", + "source": "75.0", + "target": "70.0", + "attributes": { + "size": 1 + } + }, + { + "key": "246", + "source": "75.0", + "target": "71.0", + "attributes": { + "size": 1 + } + }, + { + "key": "252", + "source": "76.0", + "target": "48.0", + "attributes": { + "size": 1 + } + }, + { + "key": "253", + "source": "76.0", + "target": "58.0", + "attributes": { + "size": 1 + } + }, + { + "key": "251", + "source": "76.0", + "target": "62.0", + "attributes": { + "size": 1 + } + }, + { + "key": "250", + "source": "76.0", + "target": "63.0", + "attributes": { + "size": 1 + } + }, + { + "key": "247", + "source": "76.0", + "target": "64.0", + "attributes": { + "size": 1 + } + }, + { + "key": "248", + "source": "76.0", + "target": "65.0", + "attributes": { + "size": 1 + } + }, + { + "key": "249", + "source": "76.0", + "target": "66.0", + "attributes": { + "size": 1 + } + } + ] +} diff --git a/packages/edge-curve/src/stories/stage.css b/packages/edge-curve/src/stories/stage.css new file mode 100644 index 000000000..488e3696c --- /dev/null +++ b/packages/edge-curve/src/stories/stage.css @@ -0,0 +1,4 @@ +.stage { + width: 100vw; + height: 100vh; +} diff --git a/packages/edge-curve/tsconfig.json b/packages/edge-curve/tsconfig.json new file mode 100644 index 000000000..aedd11da7 --- /dev/null +++ b/packages/edge-curve/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target": "ESNext", // Specifies the JavaScript version to target when transpiling code. + "useDefineForClassFields": true, // Enables the use of 'define' for class fields. + "lib": ["ES2020", "DOM", "DOM.Iterable"], // Specifies the libraries available for the code. + "module": "ESNext", // Defines the module system to use for code generation. + "skipLibCheck": true, // Skips type checking of declaration files. + + /* Bundler mode */ + "moduleResolution": "node", // Specifies how modules are resolved when bundling. + "allowSyntheticDefaultImports": true, + "allowImportingTsExtensions": true, // Allows importing TypeScript files with extensions. + "resolveJsonModule": true, // Enables importing JSON modules. + "isolatedModules": true, // Ensures each file is treated as a separate module. + "noEmit": true, // Prevents TypeScript from emitting output files. + + /* Linting */ + "strict": true, // Enables strict type checking. + "noUnusedLocals": true, // Flags unused local variables. + "noUnusedParameters": true, // Flags unused function parameters. + "noFallthroughCasesInSwitch": true, // Requires handling all cases in a switch statement. + "declaration": true // Generates declaration files for TypeScript. + }, + "include": ["src"], // Specifies the directory to include when searching for TypeScript files. + "exclude": ["src/**/__docs__", "src/**/__test__"] +} diff --git a/packages/node-image/package.json b/packages/node-image/package.json index a440062cc..8b8ec1431 100644 --- a/packages/node-image/package.json +++ b/packages/node-image/package.json @@ -37,7 +37,7 @@ ] }, "peerDependencies": { - "sigma": ">=3.0.0-beta.6" + "sigma": ">=3.0.0-beta.10" }, "exports": { ".": { diff --git a/packages/sigma/src/index-bundle.ts b/packages/sigma/src/index-bundle.ts index 0cea4e988..623e1b1d4 100644 --- a/packages/sigma/src/index-bundle.ts +++ b/packages/sigma/src/index-bundle.ts @@ -7,7 +7,8 @@ * useful classes as static properties. * @module */ -import { NodeImageProgram } from "@sigma/node-image"; +import EdgeCurveProgram from "@sigma/edge-curve"; +import { createNodeImageProgram } from "@sigma/node-image"; import * as rendering from "./rendering"; import * as utils from "./utils"; @@ -20,7 +21,7 @@ class Sigma extends SigmaClass { static MouseCaptor = MouseCaptor; static Sigma = SigmaClass; - static rendering = { ...rendering, NodeImageProgram }; + static rendering = { ...rendering, createNodeImageProgram, EdgeCurveProgram }; static utils = utils; } diff --git a/packages/website/docs/advanced/renderers.md b/packages/website/docs/advanced/renderers.md index 76bad738f..ce3e01eb0 100644 --- a/packages/website/docs/advanced/renderers.md +++ b/packages/website/docs/advanced/renderers.md @@ -67,3 +67,4 @@ For a deeper understanding and practical examples, developers are encouraged to Some more programs are also exposed, but as they carry more complexity, they are published as additional packages. - [**`@sigma/node-image`**](https://www.npmjs.com/package/@sigma/node-image): This package exposes a factory to create a program that operates similarly to `node.circle`, but filling the circles with images using a texture atlas. +- [**`@sigma/edge-curve`**](https://www.npmjs.com/package/@sigma/edge-curve): This package exposes an edge renderer that draw edges as curves. diff --git a/tsconfig.json b/tsconfig.json index 5bc86fb07..876b01f21 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,8 @@ { "path": "./packages/test" }, { "path": "./packages/storybook" }, { "path": "./packages/sigma" }, - { "path": "./packages/node-image" } + { "path": "./packages/node-image" }, + { "path": "./packages/edge-curve" } ], "watchOptions": { "excludeDirectories": ["**/node_modules"]