plebeiangraphlibrary 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -830,21 +830,21 @@ var $0a378558e9c2f574$var$__awaiter = undefined && undefined.__awaiter || functi
830
830
  return $0a378558e9c2f574$var$__awaiter(this, void 0, void 0, function*() {
831
831
  const adj = Graph.get_adjacency();
832
832
  const exploredFromMap = new Map();
833
- const explored = [];
834
- const stack = [];
835
- // queue the first node
836
- stack.push(node);
833
+ const explored = new Set([
834
+ node
835
+ ]);
836
+ const queue = [
837
+ node
838
+ ];
837
839
  exploredFromMap.set(node, -1);
838
- // search through the whole graph
839
- while(stack.length > 0){
840
- const currentNode = stack.pop();
841
- // add this current node to the explored list
842
- explored.push(currentNode);
840
+ while(queue.length > 0){
841
+ const currentNode = queue.shift();
843
842
  const neighbours = adj.get(currentNode);
844
843
  for(let i = 0; i < neighbours.length; i++){
845
844
  const neighbour = neighbours[i];
846
- if (!explored.includes(neighbour)) {
847
- stack.push(neighbour);
845
+ if (!explored.has(neighbour)) {
846
+ explored.add(neighbour);
847
+ queue.push(neighbour);
848
848
  exploredFromMap.set(neighbour, currentNode);
849
849
  }
850
850
  }
@@ -865,20 +865,17 @@ var $0a378558e9c2f574$var$__awaiter = undefined && undefined.__awaiter || functi
865
865
  return $0a378558e9c2f574$var$__awaiter(this, void 0, void 0, function*() {
866
866
  const adj = Graph.get_adjacency();
867
867
  const Dmap = new Map();
868
- // get the explored from map
869
868
  const exploredFromMap = yield $0a378558e9c2f574$var$BFSSearch(Graph, Node);
870
- // then for each element in the map go through
871
- // contact trace where that element came from
872
869
  for (const n of adj.keys()){
870
+ if (!exploredFromMap.has(n)) continue; // unreachable (disconnected)
873
871
  let i = 0;
874
872
  let exploredFrom = exploredFromMap.get(n);
875
- while(exploredFrom != -1){
873
+ while(exploredFrom !== undefined && exploredFrom !== -1){
876
874
  exploredFrom = exploredFromMap.get(exploredFrom);
877
875
  i += 1;
878
876
  }
879
877
  Dmap.set(n, i);
880
878
  }
881
- // now return this map
882
879
  return Dmap;
883
880
  });
884
881
  }
@@ -894,12 +891,27 @@ var $0a378558e9c2f574$var$__awaiter = undefined && undefined.__awaiter || functi
894
891
  * @returns returns an object with a start, end - the two points of a graph and the diameter of the graph
895
892
  */ function $0a378558e9c2f574$var$GraphDiameter(Graph) {
896
893
  return $0a378558e9c2f574$var$__awaiter(this, void 0, void 0, function*() {
897
- // find the diameter of the graph
898
- // start Dijkstra from some random node
899
- let seed = Math.floor(Math.random() * Graph.nodes.size);
894
+ const nodeIds = [
895
+ ...Graph.nodes.keys()
896
+ ];
897
+ if (nodeIds.length === 0) return {
898
+ start: 0,
899
+ end: 0,
900
+ distance: 0
901
+ };
902
+ if (nodeIds.length === 1) return {
903
+ start: nodeIds[0],
904
+ end: nodeIds[0],
905
+ distance: 0
906
+ };
907
+ const adj = Graph.get_adjacency();
908
+ const withNeighbors = nodeIds.filter((id)=>{
909
+ var _a, _b;
910
+ return ((_b = (_a = adj.get(id)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
911
+ });
912
+ const pickFrom = withNeighbors.length > 0 ? withNeighbors : nodeIds;
913
+ let seed = pickFrom[Math.floor(Math.random() * pickFrom.length)];
900
914
  let Dstart = yield $0a378558e9c2f574$var$Dijkstra(Graph, seed);
901
- // iterate through all the values and then get
902
- // the value that is the highest amongst the others
903
915
  let currentDistance = -1;
904
916
  for (const n of Dstart.keys()){
905
917
  const dval = Dstart.get(n);
@@ -908,10 +920,8 @@ var $0a378558e9c2f574$var$__awaiter = undefined && undefined.__awaiter || functi
908
920
  currentDistance = dval;
909
921
  }
910
922
  }
911
- // then search from there to the furthest point again
912
923
  const newStart = seed;
913
924
  Dstart = yield $0a378558e9c2f574$var$Dijkstra(Graph, seed);
914
- // repeat the thing
915
925
  currentDistance = -1;
916
926
  for (const n of Dstart.keys()){
917
927
  const dval = Dstart.get(n);
@@ -920,12 +930,11 @@ var $0a378558e9c2f574$var$__awaiter = undefined && undefined.__awaiter || functi
920
930
  currentDistance = dval;
921
931
  }
922
932
  }
923
- const returnObj = {
933
+ return {
924
934
  start: newStart,
925
935
  end: seed,
926
936
  distance: currentDistance
927
937
  };
928
- return returnObj;
929
938
  });
930
939
  }
931
940
  // Select a subrgaph
@@ -1057,17 +1066,10 @@ var $b0efdff792a30fe0$var$__awaiter = undefined && undefined.__awaiter || functi
1057
1066
  return $b0efdff792a30fe0$var$__awaiter(this, void 0, void 0, function*() {
1058
1067
  // I'm constructing a Graph here so some of the stuff doesnt matter
1059
1068
  this.edges.forEach((edge)=>{
1060
- // get the start point
1061
1069
  const start = edge.start;
1062
1070
  const end = edge.end;
1063
- // set the node property
1064
- if (this.nodes.get(start)) {
1065
- const relevantSNode = this.nodes.get(start);
1066
- relevantSNode.neighbours.push(end);
1067
- } else if (this.nodes.get(end)) {
1068
- const relevantENode = this.nodes.get(end);
1069
- relevantENode.neighbours.push(start);
1070
- }
1071
+ if (this.nodes.get(start)) this.nodes.get(start).neighbours.push(end);
1072
+ if (this.nodes.get(end)) this.nodes.get(end).neighbours.push(start);
1071
1073
  });
1072
1074
  // then for each node then get the unique neighbours
1073
1075
  for (const key of this.nodes.keys()){
@@ -1097,11 +1099,12 @@ var $b0efdff792a30fe0$var$__awaiter = undefined && undefined.__awaiter || functi
1097
1099
  * @param data - data associated with the edge
1098
1100
  */ add_edge(start, end, data) {
1099
1101
  const newEdge = new (0, $5v7Uc.default)(start, end, data);
1100
- // this is a new edge that we add to the edges
1101
1102
  this.edges.set(this.edges.size, newEdge);
1102
- // also add this to the node neighbours
1103
- const relevantNode = this.nodes.get(start);
1104
- relevantNode.neighbours.push(end);
1103
+ // keep adjacency consistent for undirected graph (both directions)
1104
+ const startNode = this.nodes.get(start);
1105
+ const endNode = this.nodes.get(end);
1106
+ if (startNode) startNode.neighbours.push(end);
1107
+ if (endNode) endNode.neighbours.push(start);
1105
1108
  }
1106
1109
  // get an adjacency list reprentation of the graph
1107
1110
  // this onlu has the indices and not the actual data
@@ -1211,6 +1214,8 @@ $parcel$export(module.exports, "default", () => $c4d4feb6deac3a62$export$2e2bcd8
1211
1214
 
1212
1215
  var $I1Jpx = parcelRequire("I1Jpx");
1213
1216
 
1217
+ var $49USC = parcelRequire("49USC");
1218
+
1214
1219
  var $1xDj5 = parcelRequire("1xDj5");
1215
1220
 
1216
1221
  var $84wto = parcelRequire("84wto");
@@ -1352,6 +1357,27 @@ var __awaiter = undefined && undefined.__awaiter || function(thisArg11, _argumen
1352
1357
  const emap11 = Graph11.get_edge_map();
1353
1358
  return DrawThinEdgesFromEdgeMap(emap11, bounds11, color11);
1354
1359
  }
1360
+ /**
1361
+ * Draw a single thick line through an ordered list of node IDs (e.g. a path).
1362
+ * Uses graph positions; line width in pixels (pass thickness >= 1 for pixel width).
1363
+ *
1364
+ * @param Graph - Graph with position map
1365
+ * @param bounds - Scale factor for positions
1366
+ * @param pathNodeIds - Ordered node IDs (start to end)
1367
+ * @param color - Hex color for the path line
1368
+ * @param thickness - Line width in pixels (e.g. 5 for a thick path)
1369
+ */ function DrawThickPathFromNodeIds(Graph11, bounds11, pathNodeIds11, color11 = 0xffffff, thickness11 = 5) {
1370
+ const pmap11 = Graph11.get_position_map();
1371
+ const pathPoints11 = pathNodeIds11.map((id11)=>pmap11.get(id11)).filter((p11)=>p11 != null);
1372
+ if (pathPoints11.length < 2) return new $I1Jpx.Group();
1373
+ const pathLine11 = new (0, $49USC.default)(pathPoints11);
1374
+ return (0, $1xDj5.createThickEdgesGroup)(new Map([
1375
+ [
1376
+ 0,
1377
+ pathLine11
1378
+ ]
1379
+ ]), bounds11, color11, thickness11);
1380
+ }
1355
1381
  // function to draw edges from edge map
1356
1382
  /**
1357
1383
  *
@@ -1539,44 +1565,75 @@ var __awaiter = undefined && undefined.__awaiter || function(thisArg11, _argumen
1539
1565
  return lineGroup11;
1540
1566
  }
1541
1567
  /**
1568
+ * Set vertex colors by node ID. Uses the geometry's "label" attribute (node ID per vertex) to map node IDs to vertex indices; if "label" is missing, indexArray is treated as vertex indices.
1542
1569
  *
1543
- * Change all the vertex colors based on some array of properties
1544
- *
1545
- * @param vertices - ThreeJS Points object, be sure to pass in the points object and not the group that the points belong too
1546
- * @param indexArray - The array of the indices of all the nodes whose values that have to be changed
1547
- * @param color - The color that they have to be changed too
1570
+ * @param vertices - THREE.Points with customColor (and optionally label) attribute, or a Group whose first child is that Points object
1571
+ * @param indexArray - Node IDs to color, or vertex indices if geometry has no label attribute
1572
+ * @param color - Hex color to apply
1548
1573
  */ function ChangeTheVertexColours(vertices11, indexArray11, color11) {
1549
- let Attrib11 = vertices11.geometry.attributes;
1550
- let k11 = 0;
1551
- const col11 = new $I1Jpx.Color(color11);
1552
- indexArray11.forEach((node11)=>{
1553
- k11 = node11 * 3; // @ts-ignore
1554
- Attrib11.customColor.array[k11] = col11.r; // @ts-ignore
1555
- Attrib11.customColor.array[k11 + 1] = col11.g; // @ts-ignore
1556
- Attrib11.customColor.array[k11 + 2] = col11.b;
1557
- });
1558
- Attrib11.customColor.needsUpdate = true;
1574
+ try {
1575
+ const points11 = vertices11 instanceof $I1Jpx.Group ? vertices11.children[0] : vertices11;
1576
+ const geom11 = points11 === null || points11 === void 0 ? void 0 : points11.geometry;
1577
+ if (!(geom11 === null || geom11 === void 0 ? void 0 : geom11.attributes)) return;
1578
+ const customColor11 = geom11.attributes.customColor;
1579
+ const arr11 = customColor11 === null || customColor11 === void 0 ? void 0 : customColor11.array;
1580
+ if (!arr11 || arr11.length === 0) return;
1581
+ const col11 = new $I1Jpx.Color(color11);
1582
+ const labelAttr11 = geom11.attributes.label;
1583
+ const labels11 = labelAttr11 === null || labelAttr11 === void 0 ? void 0 : labelAttr11.array;
1584
+ if (labels11 && labels11.length > 0) // Map node IDs to vertex indices via label attribute
1585
+ indexArray11.forEach((nodeId11)=>{
1586
+ for(let i11 = 0; i11 < labels11.length; i11++)if (labels11[i11] === nodeId11) {
1587
+ const k11 = i11 * 3;
1588
+ if (k11 + 2 < arr11.length) {
1589
+ arr11[k11] = col11.r;
1590
+ arr11[k11 + 1] = col11.g;
1591
+ arr11[k11 + 2] = col11.b;
1592
+ }
1593
+ break;
1594
+ }
1595
+ });
1596
+ else // No label: treat indexArray as vertex indices
1597
+ indexArray11.forEach((node11)=>{
1598
+ const k11 = node11 * 3;
1599
+ if (k11 + 2 < arr11.length) {
1600
+ arr11[k11] = col11.r;
1601
+ arr11[k11 + 1] = col11.g;
1602
+ arr11[k11 + 2] = col11.b;
1603
+ }
1604
+ });
1605
+ if (customColor11) customColor11.needsUpdate = true;
1606
+ } catch (_a11) {
1607
+ // Points object or customColor may be missing; skip coloring
1608
+ }
1559
1609
  }
1560
1610
  /**
1561
- *
1562
- * This resets all the colors to white
1563
- *
1564
- * @param vertices - ThreeJS Points object, be sure to pass in the points object and not the group that the points belong too
1611
+ * Reset all vertex colors to white.
1612
+ * @param vertices - THREE.Points with customColor attribute, or a Group whose first child is that Points object
1565
1613
  */ function ResetVertexColors(vertices11) {
1566
- let Attrib11 = vertices11.geometry.attributes;
1567
- let k11 = 0;
1568
- for(let i11 = 0; i11 < Attrib11.customColor.count; i11++){
1569
- k11 = i11 * 3; // @ts-ignore
1570
- Attrib11.customColor.array[k11] = 255; // @ts-ignore
1571
- Attrib11.customColor.array[k11 + 1] = 255; // @ts-ignore
1572
- Attrib11.customColor.array[k11 + 2] = 255;
1614
+ var _a11, _b11, _c11;
1615
+ try {
1616
+ const points11 = vertices11 instanceof $I1Jpx.Group ? vertices11.children[0] : vertices11;
1617
+ const customColor11 = (_b11 = (_a11 = points11 === null || points11 === void 0 ? void 0 : points11.geometry) === null || _a11 === void 0 ? void 0 : _a11.attributes) === null || _b11 === void 0 ? void 0 : _b11.customColor;
1618
+ const arr11 = customColor11 === null || customColor11 === void 0 ? void 0 : customColor11.array;
1619
+ if (!arr11 || arr11.length === 0) return;
1620
+ const count11 = (_c11 = customColor11 === null || customColor11 === void 0 ? void 0 : customColor11.count) !== null && _c11 !== void 0 ? _c11 : Math.floor(arr11.length / 3);
1621
+ for(let i11 = 0; i11 < count11; i11++){
1622
+ const k11 = i11 * 3;
1623
+ arr11[k11] = 1;
1624
+ arr11[k11 + 1] = 1;
1625
+ arr11[k11 + 2] = 1;
1626
+ }
1627
+ if (customColor11) customColor11.needsUpdate = true;
1628
+ } catch (_d11) {
1629
+ // skip if wrong object or missing attribute
1573
1630
  }
1574
- Attrib11.customColor.needsUpdate = true;
1575
1631
  }
1576
1632
  var $c4d4feb6deac3a62$export$2e2bcd8739ae039 = {
1577
1633
  DrawTHREEGraphVertices: DrawTHREEGraphVertices,
1578
1634
  DrawTHREEGraphEdgesThick: DrawTHREEGraphEdgesThick,
1579
1635
  DrawTHREEGraphEdgesThin: DrawTHREEGraphEdgesThin,
1636
+ DrawThickPathFromNodeIds: DrawThickPathFromNodeIds,
1580
1637
  AddBoxBasedImaging: AddBoxBasedImaging,
1581
1638
  AddInModularityBasedPointGroups: AddInModularityBasedPointGroups,
1582
1639
  DrawThinEdgesFromEdgeMap: DrawThinEdgesFromEdgeMap,