plotboilerplate 1.12.9 → 1.15.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 (113) hide show
  1. package/README.md +5 -1
  2. package/changelog.md +34 -0
  3. package/dist/index.esm.js +435 -92
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.esm.min.js +1 -1
  6. package/dist/index.esm.min.js.map +1 -1
  7. package/dist/plotboilerplate.browser.min.js +1 -1
  8. package/dist/plotboilerplate.browser.min.js.map +1 -1
  9. package/dist/plotboilerplate.js +449 -91
  10. package/dist/plotboilerplate.min.js +1 -1
  11. package/package.json +1 -1
  12. package/src/cjs/BezierPath.d.ts +12 -1
  13. package/src/cjs/BezierPath.js +34 -5
  14. package/src/cjs/BezierPath.js.map +1 -1
  15. package/src/cjs/PBText.d.ts +116 -0
  16. package/src/cjs/PBText.js +66 -0
  17. package/src/cjs/PBText.js.map +1 -0
  18. package/src/cjs/PlotBoilerplate.d.ts +2 -1
  19. package/src/cjs/PlotBoilerplate.js +43 -15
  20. package/src/cjs/PlotBoilerplate.js.map +1 -1
  21. package/src/cjs/Polygon.d.ts +22 -1
  22. package/src/cjs/Polygon.js +102 -39
  23. package/src/cjs/Polygon.js.map +1 -1
  24. package/src/cjs/Vertex.d.ts +42 -4
  25. package/src/cjs/Vertex.js +62 -7
  26. package/src/cjs/Vertex.js.map +1 -1
  27. package/src/cjs/draw.d.ts +30 -2
  28. package/src/cjs/draw.js +51 -6
  29. package/src/cjs/draw.js.map +1 -1
  30. package/src/cjs/drawgl.d.ts +29 -2
  31. package/src/cjs/drawgl.js +21 -4
  32. package/src/cjs/drawgl.js.map +1 -1
  33. package/src/cjs/drawutilssvg.d.ts +25 -7
  34. package/src/cjs/drawutilssvg.js +62 -14
  35. package/src/cjs/drawutilssvg.js.map +1 -1
  36. package/src/cjs/entry.js +1 -0
  37. package/src/cjs/index.d.ts +1 -0
  38. package/src/cjs/index.js +1 -0
  39. package/src/cjs/index.js.map +1 -1
  40. package/src/cjs/interfaces/DrawLib.d.ts +27 -6
  41. package/src/cjs/interfaces/DrawLib.js +3 -0
  42. package/src/cjs/interfaces/DrawLib.js.map +1 -1
  43. package/src/cjs/interfaces/core.d.ts +9 -1
  44. package/src/cjs/interfaces/core.js +1 -0
  45. package/src/cjs/interfaces/core.js.map +1 -1
  46. package/src/cjs/utils/datastructures/Color.d.ts +28 -15
  47. package/src/cjs/utils/datastructures/Color.js +276 -88
  48. package/src/cjs/utils/datastructures/Color.js.map +1 -1
  49. package/src/cjs/utils/findInVertexArray.d.ts +19 -0
  50. package/src/cjs/utils/findInVertexArray.js +29 -0
  51. package/src/cjs/utils/findInVertexArray.js.map +1 -0
  52. package/src/esm/BezierPath.d.ts +12 -1
  53. package/src/esm/BezierPath.js +34 -5
  54. package/src/esm/BezierPath.js.map +1 -1
  55. package/src/esm/PBText.d.ts +116 -0
  56. package/src/esm/PBText.js +61 -0
  57. package/src/esm/PBText.js.map +1 -0
  58. package/src/esm/PlotBoilerplate.d.ts +2 -1
  59. package/src/esm/PlotBoilerplate.js +43 -15
  60. package/src/esm/PlotBoilerplate.js.map +1 -1
  61. package/src/esm/Polygon.d.ts +22 -1
  62. package/src/esm/Polygon.js +102 -39
  63. package/src/esm/Polygon.js.map +1 -1
  64. package/src/esm/Vertex.d.ts +42 -4
  65. package/src/esm/Vertex.js +62 -7
  66. package/src/esm/Vertex.js.map +1 -1
  67. package/src/esm/draw.d.ts +30 -2
  68. package/src/esm/draw.js +51 -6
  69. package/src/esm/draw.js.map +1 -1
  70. package/src/esm/drawgl.d.ts +29 -2
  71. package/src/esm/drawgl.js +21 -4
  72. package/src/esm/drawgl.js.map +1 -1
  73. package/src/esm/drawutilssvg.d.ts +25 -7
  74. package/src/esm/drawutilssvg.js +62 -14
  75. package/src/esm/drawutilssvg.js.map +1 -1
  76. package/src/esm/entry.js +1 -0
  77. package/src/esm/index.d.ts +1 -0
  78. package/src/esm/index.js +1 -0
  79. package/src/esm/index.js.map +1 -1
  80. package/src/esm/interfaces/DrawLib.d.ts +27 -6
  81. package/src/esm/interfaces/DrawLib.js +3 -0
  82. package/src/esm/interfaces/DrawLib.js.map +1 -1
  83. package/src/esm/interfaces/core.d.ts +9 -1
  84. package/src/esm/interfaces/core.js +1 -0
  85. package/src/esm/interfaces/core.js.map +1 -1
  86. package/src/esm/utils/datastructures/Color.d.ts +28 -15
  87. package/src/esm/utils/datastructures/Color.js +277 -89
  88. package/src/esm/utils/datastructures/Color.js.map +1 -1
  89. package/src/esm/utils/findInVertexArray.d.ts +19 -0
  90. package/src/esm/utils/findInVertexArray.js +25 -0
  91. package/src/esm/utils/findInVertexArray.js.map +1 -0
  92. package/src/ts/BezierPath.ts +37 -5
  93. package/src/ts/PBText.ts +147 -0
  94. package/src/ts/PlotBoilerplate.ts +47 -19
  95. package/src/ts/Polygon.ts +493 -451
  96. package/src/ts/Vertex.ts +66 -7
  97. package/src/ts/draw.ts +71 -8
  98. package/src/ts/drawgl.ts +48 -8
  99. package/src/ts/drawutilssvg.ts +94 -17
  100. package/src/ts/index.ts +1 -0
  101. package/src/ts/interfaces/DrawLib.ts +30 -4
  102. package/src/ts/interfaces/core.ts +9 -0
  103. package/src/ts/utils/datastructures/Color.ts +695 -508
  104. package/src/ts/utils/findInVertexArray.ts +28 -0
  105. package/dist/plotboilerplate.browser.min.js.LICENSE.txt +0 -8
  106. package/src/ts/utils/algorithms/clearPolygonDuplicateVertices.ts~ +0 -5
  107. package/src/ts/utils/algorithms/findPolygonSelfIntersections.ts~ +0 -45
  108. package/src/ts/utils/algorithms/sh-tmp.ts~ +0 -59
  109. package/src/ts/utils/algorithms/splitPolygonToNonIntersecting.ts~ +0 -113
  110. package/src/ts/utils/algorithms/sutherlandHodgman.ts~ +0 -88
  111. package/src/ts/utils/datastructures/Color.ts~ +0 -331
  112. package/src/ts/utils/datastructures/Girih.ts~ +0 -151
  113. package/src/ts/utils/datastructures/GirihTile.ts~ +0 -419
package/src/ts/Polygon.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * @modified 2020-03-24 Ported this class from vanilla-JS to Typescript.
12
12
  * @modified 2020-10-30 Added the `addVertex` function.
13
13
  * @modified 2020-10-31 Added the `getVertexAt` function.
14
- * @modified 2020-11-06 Added the `move` function.
14
+ * @modified 2020-11-06 Added the `move` function.
15
15
  * @modified 2020-11-10 Added the `getBounds` function.
16
16
  * @modified 2020-11-11 Generalized `move(Vertex)` to `move(XYCoords)`.
17
17
  * @modified 2021-01-20 Added UID.
@@ -19,7 +19,9 @@
19
19
  * @modified 2021-01-29 Added the `isClockwise` function.
20
20
  * @modified 2021-01-29 Added the `area` function.
21
21
  * @modified 2021-01-29 Changed the param type for `containsVert` from Vertex to XYCoords.
22
- * @version 1.7.0
22
+ * @modified 2021-12-14 Added the `perimeter()` function.
23
+ * @modified 2021-12-16 Added the `getEvenDistributionPolygon()` function.
24
+ * @version 1.8.0
23
25
  *
24
26
  * @file Polygon
25
27
  * @public
@@ -31,7 +33,6 @@ import { UIDGenerator } from "./UIDGenerator";
31
33
  import { Vertex } from "./Vertex";
32
34
  import { XYCoords, SVGSerializable, UID } from "./interfaces";
33
35
 
34
-
35
36
  /**
36
37
  * @classdesc A polygon class. Any polygon consists of an array of vertices; polygons can be open or closed.
37
38
  *
@@ -44,465 +45,506 @@ import { XYCoords, SVGSerializable, UID } from "./interfaces";
44
45
  * @requires XYCoords
45
46
  */
46
47
  export class Polygon implements SVGSerializable {
47
-
48
-
49
- /**
50
- * Required to generate proper CSS classes and other class related IDs.
51
- **/
52
- readonly className : string = "Polygon";
53
-
54
-
55
- /**
56
- * The UID of this drawable object.
57
- *
58
- * @member {UID}
59
- * @memberof Polygon
60
- * @instance
61
- * @readonly
62
- */
63
- readonly uid : UID;
64
-
65
-
66
- /**
67
- * @member {Array<Vertex>}
68
- * @memberof Polygon
69
- * @type {Array<Vertex>}
70
- * @instance
71
- */
72
- vertices:Array<Vertex>;
73
-
74
-
75
- /**
76
- * @member {boolean}
77
- * @memberof Polygon
78
- * @type {boolean}
79
- * @instance
80
- */
81
- isOpen:boolean;
82
-
83
-
84
- /**
85
- * The constructor.
86
- *
87
- * @constructor
88
- * @name Polygon
89
- * @param {Vertex[]} vertices - An array of 2d vertices that shape the polygon.
90
- * @param {boolean} isOpen - Indicates if the polygon should be rendered as an open or closed shape.
91
- **/
92
- constructor( vertices?:Array<Vertex>, isOpen?:boolean ) {
93
- this.uid = UIDGenerator.next();
94
- if( typeof vertices == 'undefined' )
95
- vertices = [];
96
- this.vertices = vertices;
97
- this.isOpen = isOpen;
98
- };
99
-
100
-
101
- /**
102
- * Add a vertex to the end of the `vertices` array.
103
- *
104
- * @method addVert
105
- * @param {Vertex} vert - The vertex to add.
106
- * @instance
107
- * @memberof Polygon
108
- **/
109
- addVertex( vert:Vertex ) : void {
110
- this.vertices.push( vert );
111
- };
112
-
113
-
114
- /**
115
- * Get the polygon vertex at the given position (index).
116
- *
117
- * The index may exceed the total vertex count, and will be wrapped around then (modulo).
118
- *
119
- * For k >= 0:
120
- * - getVertexAt( vertices.length ) == getVertexAt( 0 )
121
- * - getVertexAt( vertices.length + k ) == getVertexAt( k )
122
- * - getVertexAt( -k ) == getVertexAt( vertices.length -k )
123
- *
124
- * @metho getVertexAt
125
- * @param {number} index - The index of the desired vertex.
126
- * @instance
127
- * @memberof Polygon
128
- * @return {Vertex} At the given index.
129
- **/
130
- getVertexAt( index:number ) : Vertex {
131
- if( index < 0 )
132
- return this.vertices[ this.vertices.length - (Math.abs(index)%this.vertices.length) ];
133
- else
134
- return this.vertices[ index % this.vertices.length ];
135
- };
136
-
137
-
138
- /**
139
- * Move the polygon's vertices by the given amount.
140
- *
141
- * @method move
142
- * @param {XYCoords} amount - The amount to move.
143
- * @instance
144
- * @memberof Polygon
145
- * @return {Polygon} this for chaining
146
- **/
147
- move( vert:XYCoords ) : Polygon {
148
- for( var i in this.vertices ) {
149
- this.vertices[i].add( vert );
150
- }
151
- return this;
152
- };
153
-
154
-
155
- /**
156
- * Check if the given vertex is inside this polygon.<br>
157
- * <br>
158
- * Ray-casting algorithm found at<br>
159
- * https://stackoverflow.com/questions/22521982/check-if-point-inside-a-polygon
160
- *
161
- * @method containsVert
162
- * @param {XYCoords} vert - The vertex to check. The new x-component.
163
- * @return {boolean} True if the passed vertex is inside this polygon. The polygon is considered closed.
164
- * @instance
165
- * @memberof Polygon
166
- **/
167
- containsVert( vert:XYCoords ) : boolean {
168
- // ray-casting algorithm based on
169
- // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
170
- var inside : boolean = false;
171
- for (var i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {
172
- let xi : number = this.vertices[i].x, yi : number = this.vertices[i].y;
173
- let xj : number = this.vertices[j].x, yj : number = this.vertices[j].y;
174
-
175
- var intersect : boolean = ((yi > vert.y) != (yj > vert.y))
176
- && (vert.x < (xj - xi) * (vert.y - yi) / (yj - yi) + xi);
177
- if (intersect) inside = !inside;
178
- }
179
- return inside;
180
- };
181
-
182
-
48
+ /**
49
+ * Required to generate proper CSS classes and other class related IDs.
50
+ **/
51
+ readonly className: string = "Polygon";
52
+
53
+ /**
54
+ * The UID of this drawable object.
55
+ *
56
+ * @member {UID}
57
+ * @memberof Polygon
58
+ * @instance
59
+ * @readonly
60
+ */
61
+ readonly uid: UID;
62
+
63
+ /**
64
+ * @member {Array<Vertex>}
65
+ * @memberof Polygon
66
+ * @type {Array<Vertex>}
67
+ * @instance
68
+ */
69
+ vertices: Array<Vertex>;
70
+
71
+ /**
72
+ * @member {boolean}
73
+ * @memberof Polygon
74
+ * @type {boolean}
75
+ * @instance
76
+ */
77
+ isOpen: boolean;
78
+
79
+ /**
80
+ * The constructor.
81
+ *
82
+ * @constructor
83
+ * @name Polygon
84
+ * @param {Vertex[]} vertices - An array of 2d vertices that shape the polygon.
85
+ * @param {boolean} isOpen - Indicates if the polygon should be rendered as an open or closed shape.
86
+ **/
87
+ constructor(vertices?: Array<Vertex>, isOpen?: boolean) {
88
+ this.uid = UIDGenerator.next();
89
+ if (typeof vertices == "undefined") vertices = [];
90
+ this.vertices = vertices;
91
+ this.isOpen = isOpen;
92
+ }
93
+
94
+ /**
95
+ * Add a vertex to the end of the `vertices` array.
96
+ *
97
+ * @method addVert
98
+ * @param {Vertex} vert - The vertex to add.
99
+ * @instance
100
+ * @memberof Polygon
101
+ **/
102
+ addVertex(vert: Vertex): void {
103
+ this.vertices.push(vert);
104
+ }
105
+
106
+ /**
107
+ * Get the polygon vertex at the given position (index).
108
+ *
109
+ * The index may exceed the total vertex count, and will be wrapped around then (modulo).
110
+ *
111
+ * For k >= 0:
112
+ * - getVertexAt( vertices.length ) == getVertexAt( 0 )
113
+ * - getVertexAt( vertices.length + k ) == getVertexAt( k )
114
+ * - getVertexAt( -k ) == getVertexAt( vertices.length -k )
115
+ *
116
+ * @metho getVertexAt
117
+ * @param {number} index - The index of the desired vertex.
118
+ * @instance
119
+ * @memberof Polygon
120
+ * @return {Vertex} At the given index.
121
+ **/
122
+ getVertexAt(index: number): Vertex {
123
+ if (index < 0) return this.vertices[this.vertices.length - (Math.abs(index) % this.vertices.length)];
124
+ else return this.vertices[index % this.vertices.length];
125
+ }
126
+
127
+ /**
128
+ * Move the polygon's vertices by the given amount.
129
+ *
130
+ * @method move
131
+ * @param {XYCoords} amount - The amount to move.
132
+ * @instance
133
+ * @memberof Polygon
134
+ * @return {Polygon} this for chaining
135
+ **/
136
+ move(vert: XYCoords): Polygon {
137
+ for (var i in this.vertices) {
138
+ this.vertices[i].add(vert);
139
+ }
140
+ return this;
141
+ }
142
+
143
+ /**
144
+ * Check if the given vertex is inside this polygon.<br>
145
+ * <br>
146
+ * Ray-casting algorithm found at<br>
147
+ * https://stackoverflow.com/questions/22521982/check-if-point-inside-a-polygon
148
+ *
149
+ * @method containsVert
150
+ * @param {XYCoords} vert - The vertex to check. The new x-component.
151
+ * @return {boolean} True if the passed vertex is inside this polygon. The polygon is considered closed.
152
+ * @instance
153
+ * @memberof Polygon
154
+ **/
155
+ containsVert(vert: XYCoords): boolean {
156
+ // ray-casting algorithm based on
157
+ // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
158
+ var inside: boolean = false;
159
+ for (var i = 0, j = this.vertices.length - 1; i < this.vertices.length; j = i++) {
160
+ let xi: number = this.vertices[i].x,
161
+ yi: number = this.vertices[i].y;
162
+ let xj: number = this.vertices[j].x,
163
+ yj: number = this.vertices[j].y;
164
+
165
+ var intersect: boolean = yi > vert.y != yj > vert.y && vert.x < ((xj - xi) * (vert.y - yi)) / (yj - yi) + xi;
166
+ if (intersect) inside = !inside;
167
+ }
168
+ return inside;
169
+ }
170
+
171
+ /**
172
+ * Calculate the area of the given polygon (unsigned).
173
+ *
174
+ * Note that this does not work for self-intersecting polygons.
175
+ *
176
+ * @method area
177
+ * @instance
178
+ * @memberof Polygon
179
+ * @return {number}
180
+ */
181
+ area(): number {
182
+ return Polygon.utils.area(this.vertices);
183
+ }
184
+
185
+ /**
186
+ * Calulate the signed polyon area by interpreting the polygon as a matrix
187
+ * and calculating its determinant.
188
+ *
189
+ * @method signedArea
190
+ * @instance
191
+ * @memberof Polygon
192
+ * @return {number}
193
+ */
194
+ signedArea(): number {
195
+ return Polygon.utils.signedArea(this.vertices);
196
+ }
197
+
198
+ /**
199
+ * Get the winding order of this polgon: clockwise or counterclockwise.
200
+ *
201
+ * @method isClockwise
202
+ * @instance
203
+ * @memberof Polygon
204
+ * @return {boolean}
205
+ */
206
+ isClockwise(): boolean {
207
+ return Polygon.utils.signedArea(this.vertices) < 0;
208
+ }
209
+
210
+ /**
211
+ * Get the perimeter of this polygon.
212
+ * The perimeter is the absolute length of the outline.
213
+ *
214
+ * If this polygon is open then the last segment (connecting the first and the
215
+ * last vertex) will be skipped.
216
+ *
217
+ * @method perimeter
218
+ * @instance
219
+ * @memberof Polygon
220
+ * @return {number}
221
+ */
222
+ perimeter(): number {
223
+ let length: number = 0;
224
+ for (var i = 1; i < this.vertices.length; i++) {
225
+ length += this.vertices[i - 1].distance(this.vertices[i]);
226
+ }
227
+ if (!this.isOpen && this.vertices.length > 1) {
228
+ length += this.vertices[0].distance(this.vertices[this.vertices.length - 1]);
229
+ }
230
+ return length;
231
+ }
232
+
233
+ /**
234
+ * Scale the polygon relative to the given center.
235
+ *
236
+ * @method scale
237
+ * @param {number} factor - The scale factor.
238
+ * @param {Vertex} center - The center of scaling.
239
+ * @return {Polygon} this, for chaining.
240
+ * @instance
241
+ * @memberof Polygon
242
+ **/
243
+ scale(factor: number, center: Vertex): Polygon {
244
+ for (var i in this.vertices) {
245
+ if (typeof this.vertices[i].scale == "function") this.vertices[i].scale(factor, center);
246
+ else console.log("There seems to be a null vertex!", this.vertices[i]);
247
+ }
248
+ return this;
249
+ }
250
+
251
+ /**
252
+ * Rotate the polygon around the given center.
253
+ *
254
+ * @method rotate
255
+ * @param {number} angle - The rotation angle.
256
+ * @param {Vertex} center - The center of rotation.
257
+ * @instance
258
+ * @memberof Polygon
259
+ * @return {Polygon} this, for chaining.
260
+ **/
261
+ rotate(angle: number, center: Vertex): Polygon {
262
+ for (var i in this.vertices) {
263
+ this.vertices[i].rotate(angle, center);
264
+ }
265
+ return this;
266
+ }
267
+
268
+ /**
269
+ * Convert this polygon into a new polygon with n evenly distributed vertices.
270
+ *
271
+ * @param {number} pointCount - Must not be negative.
272
+ */
273
+ getEvenDistributionPolygon(pointCount: number): Polygon {
274
+ if (pointCount <= 0) {
275
+ throw new Error("pointCount must be larger than zero; is " + pointCount + ".");
276
+ }
277
+ const result: Polygon = new Polygon([], this.isOpen);
278
+ if (this.vertices.length === 0) {
279
+ return result;
280
+ }
281
+
282
+ // Fetch and add the start point from the source polygon
283
+ let polygonPoint: Vertex = new Vertex(this.vertices[0]);
284
+ result.vertices.push(polygonPoint);
285
+ if (this.vertices.length === 1) {
286
+ return result;
287
+ }
288
+
289
+ const perimeter: number = this.perimeter();
290
+ const stepSize: number = perimeter / pointCount;
291
+ const n: number = this.vertices.length;
292
+
293
+ let polygonIndex: number = 1;
294
+ let nextPolygonPoint: Vertex = new Vertex(this.vertices[1]);
295
+ let segmentLength: number = polygonPoint.distance(nextPolygonPoint);
296
+ let loopMax: number = this.isOpen ? n : n + 1;
297
+ let curSegmentU: number = stepSize;
298
+ var i = 1;
299
+ while (i < pointCount && polygonIndex < loopMax) {
300
+ // Check if next eq point is inside this segment
301
+ if (curSegmentU < segmentLength) {
302
+ let newPoint: Vertex = polygonPoint.clone().lerpAbs(nextPolygonPoint, curSegmentU);
303
+ result.vertices.push(newPoint);
304
+ curSegmentU += stepSize;
305
+ i++;
306
+ } else {
307
+ polygonIndex++;
308
+ polygonPoint = nextPolygonPoint;
309
+ nextPolygonPoint = new Vertex(this.vertices[polygonIndex % n]);
310
+ curSegmentU = curSegmentU - segmentLength;
311
+ segmentLength = polygonPoint.distance(nextPolygonPoint);
312
+ }
313
+ }
314
+ return result;
315
+ }
316
+
317
+ /**
318
+ * Get the bounding box (bounds) of this polygon.
319
+ *
320
+ * @method getBounds
321
+ * @instance
322
+ * @memberof Polygon
323
+ * @return {Bounds} The rectangular bounds of this polygon.
324
+ **/
325
+ getBounds(): Bounds {
326
+ return Bounds.computeFromVertices(this.vertices);
327
+ }
328
+
329
+ /**
330
+ * Convert this polygon to a sequence of quadratic Bézier curves.<br>
331
+ * <br>
332
+ * The first vertex in the returned array is the start point.<br>
333
+ * The following sequence are pairs of control-point-and-end-point:
334
+ * <pre>startPoint, controlPoint0, pathPoint1, controlPoint1, pathPoint2, controlPoint2, ..., endPoint</pre>
335
+ *
336
+ * @method toQuadraticBezierData
337
+ * @return {Vertex[]} An array of 2d vertices that shape the quadratic Bézier curve.
338
+ * @instance
339
+ * @memberof Polygon
340
+ **/
341
+ toQuadraticBezierData(): Array<Vertex> {
342
+ if (this.vertices.length < 3) return [];
343
+ var qbezier: Array<Vertex> = [];
344
+ var cc0: Vertex = this.vertices[0];
345
+ var cc1: Vertex = this.vertices[1];
346
+ var edgeCenter: Vertex = new Vertex(cc0.x + (cc1.x - cc0.x) / 2, cc0.y + (cc1.y - cc0.y) / 2);
347
+ qbezier.push(edgeCenter);
348
+ var limit = this.isOpen ? this.vertices.length : this.vertices.length + 1;
349
+ for (var t = 1; t < limit; t++) {
350
+ cc0 = this.vertices[t % this.vertices.length];
351
+ cc1 = this.vertices[(t + 1) % this.vertices.length];
352
+ var edgeCenter: Vertex = new Vertex(cc0.x + (cc1.x - cc0.x) / 2, cc0.y + (cc1.y - cc0.y) / 2);
353
+ qbezier.push(cc0);
354
+ qbezier.push(edgeCenter);
355
+ cc0 = cc1;
356
+ }
357
+ return qbezier;
358
+ }
359
+
360
+ /**
361
+ * Convert this polygon to a quadratic bezier curve, represented as an SVG data string.
362
+ *
363
+ * @method toQuadraticBezierSVGString
364
+ * @return {string} The 'd' part for an SVG 'path' element.
365
+ * @instance
366
+ * @memberof Polygon
367
+ **/
368
+ toQuadraticBezierSVGString(): string {
369
+ var qdata: Array<Vertex> = this.toQuadraticBezierData();
370
+ if (qdata.length == 0) return "";
371
+ var buffer = ["M " + qdata[0].x + " " + qdata[0].y];
372
+ for (var i = 1; i < qdata.length; i += 2) {
373
+ buffer.push("Q " + qdata[i].x + " " + qdata[i].y + ", " + qdata[i + 1].x + " " + qdata[i + 1].y);
374
+ }
375
+ return buffer.join(" ");
376
+ }
377
+
378
+ /**
379
+ * Convert this polygon to a sequence of cubic Bézier curves.<br>
380
+ * <br>
381
+ * The first vertex in the returned array is the start point.<br>
382
+ * The following sequence are triplets of (first-control-point, secnond-control-point, end-point):<br>
383
+ * <pre>startPoint, controlPoint0_0, controlPoint1_1, pathPoint1, controlPoint1_0, controlPoint1_1, ..., endPoint</pre>
384
+ *
385
+ * @method toCubicBezierData
386
+ * @param {number=} threshold - An optional threshold (default=1.0) how strong the curve segments
387
+ * should over-/under-drive. Should be between 0.0 and 1.0 for best
388
+ * results but other values are allowed.
389
+ * @return {Vertex[]} An array of 2d vertices that shape the cubic Bézier curve.
390
+ * @instance
391
+ * @memberof Polygon
392
+ **/
393
+ toCubicBezierData(threshold: number | undefined): Array<Vertex> {
394
+ if (typeof threshold == "undefined") threshold = 1.0;
395
+
396
+ if (this.vertices.length < 3) return [];
397
+ var cbezier: Array<Vertex> = [];
398
+ var a: Vertex = this.vertices[0];
399
+ var b: Vertex = this.vertices[1];
400
+ var edgeCenter = new Vertex(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) / 2);
401
+ cbezier.push(edgeCenter);
402
+
403
+ var limit: number = this.isOpen ? this.vertices.length - 1 : this.vertices.length;
404
+ for (var t = 0; t < limit; t++) {
405
+ var a = this.vertices[t % this.vertices.length];
406
+ var b = this.vertices[(t + 1) % this.vertices.length];
407
+ var c = this.vertices[(t + 2) % this.vertices.length];
408
+
409
+ var aCenter: Vertex = new Vertex(a.x + (b.x - a.x) / 2, a.y + (b.y - a.y) / 2);
410
+ var bCenter: Vertex = new Vertex(b.x + (c.x - b.x) / 2, b.y + (c.y - b.y) / 2);
411
+
412
+ var a2: Vertex = new Vertex(aCenter.x + (b.x - aCenter.x) * threshold, aCenter.y + (b.y - aCenter.y) * threshold);
413
+ var b0: Vertex = new Vertex(bCenter.x + (b.x - bCenter.x) * threshold, bCenter.y + (b.y - bCenter.y) * threshold);
414
+
415
+ cbezier.push(a2);
416
+ cbezier.push(b0);
417
+ cbezier.push(bCenter);
418
+ }
419
+ return cbezier;
420
+ }
421
+
422
+ /**
423
+ * Convert this polygon to a cubic bezier curve, represented as an SVG data string.
424
+ *
425
+ * @method toCubicBezierSVGString
426
+ * @return {string} The 'd' part for an SVG 'path' element.
427
+ * @instance
428
+ * @memberof Polygon
429
+ **/
430
+ toCubicBezierSVGString(threshold: number): string {
431
+ var qdata: Array<Vertex> = this.toCubicBezierData(threshold);
432
+ if (qdata.length == 0) return "";
433
+ var buffer = ["M " + qdata[0].x + " " + qdata[0].y];
434
+ for (var i = 1; i < qdata.length; i += 3) {
435
+ buffer.push(
436
+ "C " +
437
+ qdata[i].x +
438
+ " " +
439
+ qdata[i].y +
440
+ ", " +
441
+ qdata[i + 1].x +
442
+ " " +
443
+ qdata[i + 1].y +
444
+ ", " +
445
+ qdata[i + 2].x +
446
+ " " +
447
+ qdata[i + 2].y
448
+ );
449
+ }
450
+ return buffer.join(" ");
451
+ }
452
+
453
+ /**
454
+ * Convert this polygon to a cubic bezier path instance.
455
+ *
456
+ * @method toCubicBezierPath
457
+ * @param {number} threshold - The threshold, usually from 0.0 to 1.0.
458
+ * @return {BezierPath} - A bezier path instance.
459
+ * @instance
460
+ * @memberof Polygon
461
+ **/
462
+ toCubicBezierPath(threshold: number): BezierPath {
463
+ var qdata: Array<Vertex> = this.toCubicBezierData(threshold);
464
+ // Conver the linear path vertices to a two-dimensional path array
465
+ var pathdata: Array<Array<Vertex>> = [];
466
+ for (var i = 0; i + 3 < qdata.length; i += 3) {
467
+ pathdata.push([qdata[i], qdata[i + 3], qdata[i + 1], qdata[i + 2]]);
468
+ }
469
+ return BezierPath.fromArray(pathdata);
470
+ }
471
+
472
+ /**
473
+ * Create an SVG representation of this polygon.
474
+ *
475
+ * @deprecated DEPRECATION Please use the drawutilssvg library and an XMLSerializer instead.
476
+ * @method toSVGString
477
+ * @param {object=} options - An optional set of options, like 'className'.
478
+ * @return {string} The SVG string.
479
+ * @instance
480
+ * @memberof Polygon
481
+ **/
482
+ toSVGString(options: { className?: string } | undefined): string {
483
+ options = options || {};
484
+ var buffer: Array<string> = [];
485
+ buffer.push("<path");
486
+ if (options.className) buffer.push(' class="' + options.className + '"');
487
+ buffer.push(' d="');
488
+ if (this.vertices.length > 0) {
489
+ buffer.push("M ");
490
+ buffer.push(this.vertices[0].x.toString());
491
+ buffer.push(" ");
492
+ buffer.push(this.vertices[0].y.toString());
493
+ for (var i = 1; i < this.vertices.length; i++) {
494
+ buffer.push(" L ");
495
+ buffer.push(this.vertices[i].x.toString());
496
+ buffer.push(" ");
497
+ buffer.push(this.vertices[i].y.toString());
498
+ }
499
+ if (!this.isOpen) {
500
+ buffer.push(" Z");
501
+ }
502
+ }
503
+ buffer.push('" />');
504
+ return buffer.join("");
505
+ }
506
+
507
+ static utils = {
183
508
  /**
184
- * Calculate the area of the given polygon (unsigned).
509
+ * Calculate the area of the given polygon (unsigned).
185
510
  *
186
511
  * Note that this does not work for self-intersecting polygons.
187
512
  *
188
- * @method area
189
- * @instance
190
- * @memberof Polygon
513
+ * @name area
191
514
  * @return {number}
192
515
  */
193
- area() : number {
194
- return Polygon.utils.area(this.vertices);
195
- };
196
-
516
+ area(vertices: Array<XYCoords>): number {
517
+ // Found at:
518
+ // https://stackoverflow.com/questions/16285134/calculating-polygon-area
519
+ let total: number = 0.0;
520
+
521
+ for (var i = 0, l = vertices.length; i < l; i++) {
522
+ const addX = vertices[i].x;
523
+ const addY = vertices[(i + 1) % l].y;
524
+ const subX = vertices[(i + 1) % l].x;
525
+ const subY = vertices[i].y;
526
+
527
+ total += addX * addY * 0.5;
528
+ total -= subX * subY * 0.5;
529
+ }
530
+ return Math.abs(total);
531
+ },
197
532
 
198
533
  /**
199
534
  * Calulate the signed polyon area by interpreting the polygon as a matrix
200
535
  * and calculating its determinant.
201
536
  *
202
- * @method signedArea
203
- * @instance
204
- * @memberof Polygon
537
+ * @name signedArea
205
538
  * @return {number}
206
539
  */
207
- signedArea() : number {
208
- return Polygon.utils.signedArea(this.vertices)
209
- };
210
-
211
-
212
- /**
213
- * Get the winding order of this polgon: clockwise or counterclockwise.
214
- *
215
- * @method isClockwise
216
- * @instance
217
- * @memberof Polygon
218
- * @return {boolean}
219
- */
220
- isClockwise() : boolean {
221
- return Polygon.utils.signedArea(this.vertices) < 0;
222
- };
223
-
224
-
225
-
226
- /**
227
- * Scale the polygon relative to the given center.
228
- *
229
- * @method scale
230
- * @param {number} factor - The scale factor.
231
- * @param {Vertex} center - The center of scaling.
232
- * @return {Polygon} this, for chaining.
233
- * @instance
234
- * @memberof Polygon
235
- **/
236
- scale( factor:number, center:Vertex ) : Polygon {
237
- for( var i in this.vertices ) {
238
- if( typeof this.vertices[i].scale == 'function' )
239
- this.vertices[i].scale( factor, center );
240
- else
241
- console.log( 'There seems to be a null vertex!', this.vertices[i] );
242
- }
243
- return this;
244
- };
245
-
246
-
247
- /**
248
- * Rotate the polygon around the given center.
249
- *
250
- * @method rotate
251
- * @param {number} angle - The rotation angle.
252
- * @param {Vertex} center - The center of rotation.
253
- * @instance
254
- * @memberof Polygon
255
- * @return {Polygon} this, for chaining.
256
- **/
257
- rotate( angle:number, center:Vertex ) : Polygon {
258
- for( var i in this.vertices ) {
259
- this.vertices[i].rotate( angle, center );
260
- }
261
- return this;
262
- };
263
-
264
-
265
- /**
266
- * Get the bounding box (bounds) of this polygon.
267
- *
268
- * @method getBounds
269
- * @instance
270
- * @memberof Polygon
271
- * @return {Bounds} The rectangular bounds of this polygon.
272
- **/
273
- getBounds() : Bounds {
274
- return Bounds.computeFromVertices( this.vertices );
275
- };
276
-
277
-
278
- /**
279
- * Convert this polygon to a sequence of quadratic Bézier curves.<br>
280
- * <br>
281
- * The first vertex in the returned array is the start point.<br>
282
- * The following sequence are pairs of control-point-and-end-point:
283
- * <pre>startPoint, controlPoint0, pathPoint1, controlPoint1, pathPoint2, controlPoint2, ..., endPoint</pre>
284
- *
285
- * @method toQuadraticBezierData
286
- * @return {Vertex[]} An array of 2d vertices that shape the quadratic Bézier curve.
287
- * @instance
288
- * @memberof Polygon
289
- **/
290
- toQuadraticBezierData() : Array<Vertex> {
291
- if( this.vertices.length < 3 )
292
- return [];
293
- var qbezier : Array<Vertex> = [];
294
- var cc0 : Vertex = this.vertices[0];
295
- var cc1 : Vertex = this.vertices[1];
296
- var edgeCenter : Vertex = new Vertex( cc0.x + (cc1.x-cc0.x)/2,
297
- cc0.y + (cc1.y-cc0.y)/2 );
298
- qbezier.push( edgeCenter );
299
- var limit = this.isOpen ? this.vertices.length : this.vertices.length+1;
300
- for( var t = 1; t < limit; t++ ) {
301
- cc0 = this.vertices[ t%this.vertices.length ];
302
- cc1 = this.vertices[ (t+1)%this.vertices.length ];
303
- var edgeCenter : Vertex = new Vertex( cc0.x + (cc1.x-cc0.x)/2,
304
- cc0.y + (cc1.y-cc0.y)/2 );
305
- qbezier.push( cc0 );
306
- qbezier.push( edgeCenter );
307
- cc0 = cc1;
308
- }
309
- return qbezier;
310
- };
311
-
312
-
313
- /**
314
- * Convert this polygon to a quadratic bezier curve, represented as an SVG data string.
315
- *
316
- * @method toQuadraticBezierSVGString
317
- * @return {string} The 'd' part for an SVG 'path' element.
318
- * @instance
319
- * @memberof Polygon
320
- **/
321
- toQuadraticBezierSVGString() : string {
322
- var qdata : Array<Vertex> = this.toQuadraticBezierData();
323
- if( qdata.length == 0 )
324
- return "";
325
- var buffer = [ 'M ' + qdata[0].x+' '+qdata[0].y ];
326
- for( var i = 1; i < qdata.length; i+=2 ) {
327
- buffer.push( 'Q ' + qdata[i].x+' '+qdata[i].y + ', ' + qdata[i+1].x+' '+qdata[i+1].y );
328
- }
329
- return buffer.join(' ');
330
- };
331
-
332
-
333
-
334
- /**
335
- * Convert this polygon to a sequence of cubic Bézier curves.<br>
336
- * <br>
337
- * The first vertex in the returned array is the start point.<br>
338
- * The following sequence are triplets of (first-control-point, secnond-control-point, end-point):<br>
339
- * <pre>startPoint, controlPoint0_0, controlPoint1_1, pathPoint1, controlPoint1_0, controlPoint1_1, ..., endPoint</pre>
340
- *
341
- * @method toCubicBezierData
342
- * @param {number=} threshold - An optional threshold (default=1.0) how strong the curve segments
343
- * should over-/under-drive. Should be between 0.0 and 1.0 for best
344
- * results but other values are allowed.
345
- * @return {Vertex[]} An array of 2d vertices that shape the cubic Bézier curve.
346
- * @instance
347
- * @memberof Polygon
348
- **/
349
- toCubicBezierData( threshold:number|undefined ) : Array<Vertex> {
350
- if( typeof threshold == 'undefined' )
351
- threshold = 1.0;
352
-
353
- if( this.vertices.length < 3 )
354
- return [];
355
- var cbezier : Array<Vertex> = [];
356
- var a : Vertex = this.vertices[0];
357
- var b : Vertex = this.vertices[1];
358
- var edgeCenter = new Vertex( a.x + (b.x-a.x)/2, a.y + (b.y-a.y)/2 );
359
- cbezier.push( edgeCenter );
360
-
361
- var limit : number = this.isOpen ? this.vertices.length-1 : this.vertices.length;
362
- for( var t = 0; t < limit; t++ ) {
363
- var a = this.vertices[ t%this.vertices.length ];
364
- var b = this.vertices[ (t+1)%this.vertices.length ];
365
- var c = this.vertices[ (t+2)%this.vertices.length ];
366
-
367
- var aCenter : Vertex = new Vertex( a.x + (b.x-a.x)/2, a.y + (b.y-a.y)/2 );
368
- var bCenter : Vertex = new Vertex( b.x + (c.x-b.x)/2, b.y + (c.y-b.y)/2 );
369
-
370
- var a2 : Vertex = new Vertex( aCenter.x + (b.x-aCenter.x)*threshold, aCenter.y + (b.y-aCenter.y)*threshold );
371
- var b0 : Vertex = new Vertex( bCenter.x + (b.x-bCenter.x)*threshold, bCenter.y + (b.y-bCenter.y)*threshold );
372
-
373
- cbezier.push( a2 );
374
- cbezier.push( b0 );
375
- cbezier.push( bCenter );
376
-
377
- }
378
- return cbezier;
379
-
380
- };
381
-
382
-
383
-
384
- /**
385
- * Convert this polygon to a cubic bezier curve, represented as an SVG data string.
386
- *
387
- * @method toCubicBezierSVGString
388
- * @return {string} The 'd' part for an SVG 'path' element.
389
- * @instance
390
- * @memberof Polygon
391
- **/
392
- toCubicBezierSVGString( threshold:number ) : string {
393
- var qdata : Array<Vertex> = this.toCubicBezierData( threshold );
394
- if( qdata.length == 0 )
395
- return "";
396
- var buffer = [ 'M ' + qdata[0].x+' '+qdata[0].y ];
397
- for( var i = 1; i < qdata.length; i+=3 ) {
398
- buffer.push( 'C ' + qdata[i].x+' '+qdata[i].y + ', ' + qdata[i+1].x+' '+qdata[i+1].y + ', ' + qdata[i+2].x + ' ' + qdata[i+2].y );
399
- }
400
- return buffer.join(' ');
401
- };
402
-
403
-
404
-
405
- /**
406
- * Convert this polygon to a cubic bezier path instance.
407
- *
408
- * @method toCubicBezierPath
409
- * @param {number} threshold - The threshold, usually from 0.0 to 1.0.
410
- * @return {BezierPath} - A bezier path instance.
411
- * @instance
412
- * @memberof Polygon
413
- **/
414
- toCubicBezierPath( threshold:number ) : BezierPath {
415
- var qdata : Array<Vertex> = this.toCubicBezierData( threshold );
416
- // Conver the linear path vertices to a two-dimensional path array
417
- var pathdata : Array<Array<Vertex>> = [];
418
- for( var i = 0; i+3 < qdata.length; i+=3 ) {
419
- pathdata.push( [ qdata[i], qdata[i+3], qdata[i+1], qdata[i+2] ] );
420
- }
421
- return BezierPath.fromArray( pathdata );
422
- };
423
-
424
-
425
- /**
426
- * Create an SVG representation of this polygon.
427
- *
428
- * @deprecated DEPRECATION Please use the drawutilssvg library and an XMLSerializer instead.
429
- * @method toSVGString
430
- * @param {object=} options - An optional set of options, like 'className'.
431
- * @return {string} The SVG string.
432
- * @instance
433
- * @memberof Polygon
434
- **/
435
- toSVGString( options:{ className? : string }|undefined ) : string {
436
- options = options || {};
437
- var buffer : Array<string> = [];
438
- buffer.push( '<path' );
439
- if( options.className )
440
- buffer.push( ' class="' + options.className + '"' );
441
- buffer.push( ' d="' );
442
- if( this.vertices.length > 0 ) {
443
- buffer.push( 'M ' );
444
- buffer.push( this.vertices[0].x.toString() )
445
- buffer.push( ' ' );
446
- buffer.push( this.vertices[0].y.toString() );
447
- for( var i = 1; i < this.vertices.length; i++ ) {
448
- buffer.push( ' L ' );
449
- buffer.push( this.vertices[i].x.toString() )
450
- buffer.push( ' ' );
451
- buffer.push( this.vertices[i].y.toString() );
452
- }
453
- if( !this.isOpen ) {
454
- buffer.push( ' Z' );
455
- }
456
- }
457
- buffer.push( '" />' );
458
- return buffer.join('');
459
- };
460
-
461
- static utils = {
462
-
463
- /**
464
- * Calculate the area of the given polygon (unsigned).
465
- *
466
- * Note that this does not work for self-intersecting polygons.
467
- *
468
- * @name area
469
- * @return {number}
470
- */
471
- area( vertices : Array<XYCoords> ) : number {
472
- // Found at:
473
- // https://stackoverflow.com/questions/16285134/calculating-polygon-area
474
- let total : number = 0.0;
475
-
476
- for (var i = 0, l = vertices.length; i < l; i++) {
477
- const addX = vertices[i].x;
478
- const addY = vertices[(i + 1)%l].y;
479
- const subX = vertices[(i + 1)%l].x;
480
- const subY = vertices[i].y;
481
-
482
- total += (addX * addY * 0.5);
483
- total -= (subX * subY * 0.5);
484
- }
485
- return Math.abs(total);
486
- },
487
-
488
-
489
- /**
490
- * Calulate the signed polyon area by interpreting the polygon as a matrix
491
- * and calculating its determinant.
492
- *
493
- * @name signedArea
494
- * @return {number}
495
- */
496
- signedArea( vertices : Array<XYCoords> ) : number {
497
- let sum : number = 0;
498
- const n = vertices.length;
499
- for (var i = 0; i < n; i++ ) {
500
- const j = (i+1) % n;
501
- sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);
502
- }
503
- return sum;
504
- }
505
-
506
- };
507
-
540
+ signedArea(vertices: Array<XYCoords>): number {
541
+ let sum: number = 0;
542
+ const n = vertices.length;
543
+ for (var i = 0; i < n; i++) {
544
+ const j = (i + 1) % n;
545
+ sum += (vertices[j].x - vertices[i].x) * (vertices[i].y + vertices[j].y);
546
+ }
547
+ return sum;
548
+ }
549
+ };
508
550
  }