plotboilerplate 1.29.0 → 1.31.0

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.
Files changed (80) hide show
  1. package/README.md +26 -13
  2. package/dist/index.esm.js +310 -57
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.esm.min.js +1 -1
  5. package/dist/index.esm.min.js.map +1 -1
  6. package/dist/plotboilerplate.browser.min.js +1 -1
  7. package/dist/plotboilerplate.browser.min.js.map +1 -1
  8. package/dist/plotboilerplate.js +266 -36
  9. package/dist/plotboilerplate.min.js +1 -1
  10. package/package.json +1 -1
  11. package/src/cjs/Circle.d.ts +17 -1
  12. package/src/cjs/Circle.js +21 -1
  13. package/src/cjs/Circle.js.map +1 -1
  14. package/src/cjs/CubicBezierCurve.d.ts +34 -3
  15. package/src/cjs/CubicBezierCurve.js +79 -12
  16. package/src/cjs/CubicBezierCurve.js.map +1 -1
  17. package/src/cjs/Line.d.ts +46 -1
  18. package/src/cjs/Line.js +80 -1
  19. package/src/cjs/Line.js.map +1 -1
  20. package/src/cjs/Polygon.d.ts +18 -4
  21. package/src/cjs/Polygon.js +56 -18
  22. package/src/cjs/Polygon.js.map +1 -1
  23. package/src/cjs/VertTuple.d.ts +24 -2
  24. package/src/cjs/VertTuple.js +28 -2
  25. package/src/cjs/VertTuple.js.map +1 -1
  26. package/src/cjs/Vertex.d.ts +2 -2
  27. package/src/cjs/Vertex.js +2 -2
  28. package/src/cjs/utils/algorithms/delaunay2voronoi.d.ts +2 -1
  29. package/src/cjs/utils/algorithms/delaunay2voronoi.js +8 -10
  30. package/src/cjs/utils/algorithms/delaunay2voronoi.js.map +1 -1
  31. package/src/cjs/utils/datastructures/PointSet.d.ts +63 -0
  32. package/src/cjs/utils/datastructures/PointSet.js +126 -0
  33. package/src/cjs/utils/datastructures/PointSet.js.map +1 -0
  34. package/src/cjs/utils/datastructures/VoronoiCell.d.ts +19 -2
  35. package/src/cjs/utils/datastructures/VoronoiCell.js +39 -12
  36. package/src/cjs/utils/datastructures/VoronoiCell.js.map +1 -1
  37. package/src/cjs/utils/renderers/VoronoiRenderer.d.ts +99 -0
  38. package/src/cjs/utils/renderers/VoronoiRenderer.js +147 -0
  39. package/src/cjs/utils/renderers/VoronoiRenderer.js.map +1 -0
  40. package/src/esm/Circle.d.ts +17 -1
  41. package/src/esm/Circle.js +21 -1
  42. package/src/esm/Circle.js.map +1 -1
  43. package/src/esm/CubicBezierCurve.d.ts +34 -3
  44. package/src/esm/CubicBezierCurve.js +79 -12
  45. package/src/esm/CubicBezierCurve.js.map +1 -1
  46. package/src/esm/Line.d.ts +46 -1
  47. package/src/esm/Line.js +80 -1
  48. package/src/esm/Line.js.map +1 -1
  49. package/src/esm/Polygon.d.ts +18 -4
  50. package/src/esm/Polygon.js +56 -18
  51. package/src/esm/Polygon.js.map +1 -1
  52. package/src/esm/VertTuple.d.ts +24 -2
  53. package/src/esm/VertTuple.js +28 -2
  54. package/src/esm/VertTuple.js.map +1 -1
  55. package/src/esm/Vertex.d.ts +2 -2
  56. package/src/esm/Vertex.js +2 -2
  57. package/src/esm/utils/algorithms/delaunay2voronoi.d.ts +2 -1
  58. package/src/esm/utils/algorithms/delaunay2voronoi.js +8 -10
  59. package/src/esm/utils/algorithms/delaunay2voronoi.js.map +1 -1
  60. package/src/esm/utils/datastructures/PointSet.d.ts +63 -0
  61. package/src/esm/utils/datastructures/PointSet.js +115 -0
  62. package/src/esm/utils/datastructures/PointSet.js.map +1 -0
  63. package/src/esm/utils/datastructures/VoronoiCell.d.ts +19 -2
  64. package/src/esm/utils/datastructures/VoronoiCell.js +39 -12
  65. package/src/esm/utils/datastructures/VoronoiCell.js.map +1 -1
  66. package/src/esm/utils/renderers/VoronoiRenderer.d.ts +99 -0
  67. package/src/esm/utils/renderers/VoronoiRenderer.js +142 -0
  68. package/src/esm/utils/renderers/VoronoiRenderer.js.map +1 -0
  69. package/src/index-gl.js +1 -2
  70. package/src/ts/Circle.ts +23 -1
  71. package/src/ts/CubicBezierCurve.ts +133 -48
  72. package/src/ts/Line.ts +84 -1
  73. package/src/ts/Polygon.ts +58 -18
  74. package/src/ts/VertTuple.ts +30 -2
  75. package/src/ts/Vertex.ts +2 -2
  76. package/src/ts/utils/_AppContext.ts_ +22 -0
  77. package/src/ts/utils/algorithms/delaunay2voronoi.ts +81 -88
  78. package/src/ts/utils/datastructures/PointSet.ts +135 -0
  79. package/src/ts/utils/datastructures/VoronoiCell.ts +198 -169
  80. package/src/ts/utils/renderers/VoronoiRenderer.ts +200 -0
@@ -3,7 +3,8 @@
3
3
  * @date 2018-04-07
4
4
  * @modified 2018-04-11 Using VoronoiCells now (was array before).
5
5
  * @modified 2020-08-15 Ported from vanilla JS to TypeScript.
6
- * @version 1.0.2
6
+ * @modified 2026-09-15 Added the `sharedVertexIndex` attribute to each Voronoi cell.
7
+ * @version 1.1.0
7
8
  **/
8
9
 
9
10
  import { Triangle } from "../../Triangle";
@@ -17,97 +18,89 @@ import { VoronoiCell } from "../datastructures/VoronoiCell";
17
18
  * @requires Triangle
18
19
  */
19
20
  export class delaunay2voronoi {
21
+ public failedTriangleSets: Array<Triangle>;
22
+ public hasErrors: boolean;
20
23
 
21
- public failedTriangleSets : Array<Triangle>;
22
- public hasErrors: boolean;
24
+ private pointList: Array<Vertex>;
25
+ private triangles: Array<Triangle>;
23
26
 
24
- private pointList: Array<Vertex>;
25
- private triangles: Array<Triangle>;
26
-
27
- constructor( pointList:Array<Vertex>, triangles:Array<Triangle> ) {
27
+ constructor(pointList: Array<Vertex>, triangles: Array<Triangle>) {
28
+ this.failedTriangleSets = [];
29
+ this.hasErrors = false;
28
30
 
29
- this.failedTriangleSets = [];
30
- this.hasErrors = false;
31
+ this.pointList = pointList;
32
+ this.triangles = triangles;
33
+ }
31
34
 
32
- this.pointList = pointList;
33
- this.triangles = triangles;
34
- };
35
+ // +---------------------------------------------------------------------------------
36
+ // | Convert the triangle set to the Voronoi diagram.
37
+ // +-------------------------------
38
+ build(): Array<VoronoiCell> {
39
+ const voronoiDiagram: Array<VoronoiCell> = [];
40
+ for (var p = 0; p < this.pointList.length; p++) {
41
+ var point: Vertex = this.pointList[p];
42
+ // Find adjacent triangles for first point
43
+ var adjacentSubset: Array<Triangle> = [];
44
+ for (var t in this.triangles) {
45
+ if (this.triangles[t].a.equals(point) || this.triangles[t].b.equals(point) || this.triangles[t].c.equals(point))
46
+ adjacentSubset.push(this.triangles[t]);
47
+ }
48
+ var path: Array<Triangle> = this.subsetToPath(adjacentSubset);
49
+ if (path)
50
+ // There may be errors
51
+ voronoiDiagram.push(new VoronoiCell(path, point, p));
52
+ }
53
+ return voronoiDiagram;
54
+ }
35
55
 
36
- // +---------------------------------------------------------------------------------
37
- // | Convert the triangle set to the Voronoi diagram.
38
- // +-------------------------------
39
- build() : Array<VoronoiCell> {
40
- const voronoiDiagram : Array<VoronoiCell>= [];
41
- for( var p in this.pointList ) {
42
- var point : Vertex = this.pointList[p];
43
- // Find adjacent triangles for first point
44
- var adjacentSubset : Array<Triangle> = [];
45
- for( var t in this.triangles ) {
46
- if( this.triangles[t].a.equals(point) || this.triangles[t].b.equals(point) || this.triangles[t].c.equals(point) )
47
- adjacentSubset.push( this.triangles[t] );
48
-
49
- }
50
- var path : Array<Triangle> = this.subsetToPath(adjacentSubset);
51
- if( path ) // There may be errors
52
- voronoiDiagram.push( new VoronoiCell(path,point) );
53
- }
54
- return voronoiDiagram;
55
- };
56
+ // +---------------------------------------------------------------------------------
57
+ // | Re-order a tiangle subset so the triangle define a single path.
58
+ // |
59
+ // | It is required that all passed triangles are connected to a
60
+ // | path. Otherwise this function will RAISE AN EXCEPTION.
61
+ // |
62
+ // | The function has a failsafe recursive call for the case the first
63
+ // | element in the array is inside the path (no border element).
64
+ // +-------------------------------
65
+ private subsetToPath(triangleSet: Array<Triangle>, startPosition?: number, tryOnce?: boolean): Array<Triangle> {
66
+ if (triangleSet.length == 0) return [];
56
67
 
68
+ if (typeof startPosition === "undefined") startPosition = 0;
57
69
 
58
- // +---------------------------------------------------------------------------------
59
- // | Re-order a tiangle subset so the triangle define a single path.
60
- // |
61
- // | It is required that all passed triangles are connected to a
62
- // | path. Otherwise this function will RAISE AN EXCEPTION.
63
- // |
64
- // | The function has a failsafe recursive call for the case the first
65
- // | element in the array is inside the path (no border element).
66
- // +-------------------------------
67
- private subsetToPath( triangleSet: Array<Triangle>,
68
- startPosition?:number,
69
- tryOnce?:boolean ) : Array<Triangle> {
70
- if( triangleSet.length == 0 )
71
- return [];
72
-
73
- if( typeof startPosition === 'undefined' )
74
- startPosition = 0;
75
-
76
- let t : number = startPosition;
77
- const result : Array<Triangle> = [ triangleSet[t] ];
78
- const visited : Array<number> = [ t ];
79
- let i : number = 0;
80
- while( result.length < triangleSet.length && i < triangleSet.length ) {
81
- let u : number = (startPosition+i)%triangleSet.length;
82
- if( t != u && visited.indexOf(u) == -1 && triangleSet[t].isAdjacent(triangleSet[u]) ) {
83
- result.push(triangleSet[u]);
84
- visited.push(u);
85
- t = u;
86
- i = 0;
87
- } else {
88
- i++;
89
- }
90
- }
91
- // If not all triangles were used the passed set is NOT CIRCULAR.
92
- // But in this case the triangle at position t is at one end of the path :)
93
- // -> Restart with t.
94
- if( result.length < triangleSet.length ) {
95
- if( tryOnce ) {
96
- // Possibility A (try to fix this): split the triangle set into two arrays and restart with each.
97
- // Possibility B (no fix for this): throw an error and terminate.
98
- // Possibility C (temp solution): Store the error for later reporting and continue.
99
- // this.failedTriangleSets.push( triangleSet );
100
- this.failedTriangleSets = triangleSet;
101
- this.hasErrors = true;
102
- // throw "Error: this triangle set is not connected: " + JSON.stringify(triangleSet);
103
- return null;
104
- } else {
105
- // Triangle inside path found. Rearrange.
106
- return this.subsetToPath( triangleSet, t, true );
107
- }
108
- } else {
109
- return result;
110
- }
111
- };
112
-
113
- }; // END delaunay2voronoi
70
+ let t: number = startPosition;
71
+ const result: Array<Triangle> = [triangleSet[t]];
72
+ const visited: Array<number> = [t];
73
+ let i: number = 0;
74
+ while (result.length < triangleSet.length && i < triangleSet.length) {
75
+ let u: number = (startPosition + i) % triangleSet.length;
76
+ if (t != u && visited.indexOf(u) == -1 && triangleSet[t].isAdjacent(triangleSet[u])) {
77
+ result.push(triangleSet[u]);
78
+ visited.push(u);
79
+ t = u;
80
+ i = 0;
81
+ } else {
82
+ i++;
83
+ }
84
+ }
85
+ // If not all triangles were used the passed set is NOT CIRCULAR.
86
+ // But in this case the triangle at position t is at one end of the path :)
87
+ // -> Restart with t.
88
+ if (result.length < triangleSet.length) {
89
+ if (tryOnce) {
90
+ // Possibility A (try to fix this): split the triangle set into two arrays and restart with each.
91
+ // Possibility B (no fix for this): throw an error and terminate.
92
+ // Possibility C (temp solution): Store the error for later reporting and continue.
93
+ // this.failedTriangleSets.push( triangleSet );
94
+ this.failedTriangleSets = triangleSet;
95
+ this.hasErrors = true;
96
+ // throw "Error: this triangle set is not connected: " + JSON.stringify(triangleSet);
97
+ return null;
98
+ } else {
99
+ // Triangle inside path found. Rearrange.
100
+ return this.subsetToPath(triangleSet, t, true);
101
+ }
102
+ } else {
103
+ return result;
104
+ }
105
+ }
106
+ } // END delaunay2voronoi
@@ -0,0 +1,135 @@
1
+ /**
2
+ * A mutable point set datastructure for holding a finite but variable set of vertices.
3
+ *
4
+ * @date 2026-09-12
5
+ * @author Ikaros Kappler
6
+ * @version 1.0.0
7
+ */
8
+
9
+ import PlotBoilerplate from "../../PlotBoilerplate";
10
+ import { Vertex } from "../../Vertex";
11
+
12
+ export class PointSet {
13
+ private readonly pb: PlotBoilerplate;
14
+ public points: Array<Vertex>;
15
+ readonly dragListeners: Array<Function> = [];
16
+
17
+ constructor(pb: PlotBoilerplate) {
18
+ this.pb = pb;
19
+ this.points = [];
20
+ }
21
+
22
+ private fireDragEvent() {
23
+ this.dragListeners.forEach(listener => {
24
+ listener();
25
+ });
26
+ }
27
+
28
+ /**
29
+ * Adds a random point to the point list.
30
+ *
31
+ * @name addRandomPoint
32
+ * @instance
33
+ * @override
34
+ * @memberof PointSet
35
+ * @return {void}
36
+ */
37
+ addRandomPoint(horizontalSafeArea: number = 0, verticalSafeArea: number = 0) {
38
+ // this.addVertex(Vertex.randomVertex(this.pb.viewport()).scale(0.5));
39
+ this.addVertex(this.pb.viewport().randomPoint(horizontalSafeArea, verticalSafeArea));
40
+ }
41
+
42
+ /**
43
+ * Adds the given point/vertex to the point list.
44
+ *
45
+ * @name addVertex
46
+ * @instance
47
+ * @override
48
+ * @memberof PointSet
49
+ * @param {Vertex} vert - The vertex to add.
50
+ * @return {void}
51
+ */
52
+ addVertex(vert: Vertex) {
53
+ this.points.push(vert);
54
+ this.pb.add(vert, false); // redraw=false
55
+ var _self = this;
56
+ vert.listeners.addDragListener(function () {
57
+ _self.fireDragEvent();
58
+ });
59
+ // vert.listeners.addDragListener(_self.fireDragEvent);
60
+ }
61
+
62
+ /**
63
+ * Remove all vertices from this set and from the plotboilerplate instance.
64
+ *
65
+ * @name clear
66
+ * @instance
67
+ * @override
68
+ * @memberof PointSet
69
+ * @return {void}
70
+ */
71
+ clear() {
72
+ for (var i = 0; i < this.points.length; i++) {
73
+ this.pb.remove(this.points[i], false);
74
+ // TODO: How to remove drag listener?
75
+ // this.points[i].listeners.removeDragListener(this.fireDragEvent);
76
+ }
77
+ this.points = [];
78
+ }
79
+
80
+ /**
81
+ * Add or remove n random points; depends on the config settings.
82
+ *
83
+ * I have no idea how tired I was when I wrote this function but it seems working pretty well.
84
+ */
85
+ randomPoints(pointCount: number, horizontalSafeArea: number = 0, verticalSafeArea: number = 0) {
86
+ // Generate random points.
87
+ for (var i = this.points.length; i < pointCount; i++) {
88
+ this.addRandomPoint(horizontalSafeArea, verticalSafeArea);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Add random points and be sure they cover the whole viewport.
94
+ *
95
+ * I have no idea how tired I was when I wrote this function but it seems working pretty well.
96
+ */
97
+ randomFullCover(pointCount: number) {
98
+ this.clear();
99
+ this.randomPoints(pointCount - 4, 0.0, 0.0); //, true, true);
100
+ // Add 4 more points in the corners.
101
+ var viewport = this.pb.viewport();
102
+ this.addVertex(viewport.getNorthWestPoint());
103
+ this.addVertex(viewport.getNorthEastPoint());
104
+ this.addVertex(viewport.getSouthWestPoint());
105
+ this.addVertex(viewport.getSouthEastPoint());
106
+ }
107
+
108
+ /**
109
+ * Call when the desired number of points changes.
110
+ **/
111
+ updatePointCount(newPointCount: number, horizontalSafeArea: number = 0, verticalSafeArea: number = 0) {
112
+ if (newPointCount > this.points.length) {
113
+ this.randomPoints(newPointCount, horizontalSafeArea, verticalSafeArea);
114
+ }
115
+ // Do not clear ; no full cover ; do rebuild
116
+ else if (newPointCount < this.points.length) {
117
+ // Remove n-m points
118
+ for (var i = newPointCount; i < this.points.length; i++) {
119
+ this.pb.remove(this.points[i]);
120
+ }
121
+ // TODO: MOVE THIS TO THE PointSet class.
122
+ this.points = this.points.slice(0, newPointCount);
123
+ // TODO: also remove listeners?
124
+ // updateAnimator();
125
+ // rebuild();
126
+ }
127
+ }
128
+
129
+ // +---------------------------------------------------------------------------------
130
+ // | Generates a random int value between 0 and max (both inclusive).
131
+ // +-------------------------------
132
+ // private randomInt(max: number): number {
133
+ // return Math.round(Math.random() * max);
134
+ // }
135
+ }