dgeoutils 2.2.1 → 2.2.5
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.
- package/dist/DCircle.d.ts +8 -4
- package/dist/DCircle.js +11 -7
- package/dist/DLine.d.ts +14 -7
- package/dist/DLine.js +61 -81
- package/dist/DPoint.d.ts +105 -12
- package/dist/DPoint.js +22 -22
- package/dist/DPolygon.d.ts +61 -34
- package/dist/DPolygon.js +156 -185
- package/dist/DPolygonLoop.d.ts +84 -6
- package/dist/DPolygonLoop.js +11 -4
- package/dist/TraceMatrix.d.ts +1 -1
- package/dist/TraceMatrix.js +8 -10
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +4 -2
- package/package.json +2 -2
package/dist/DPolygon.js
CHANGED
|
@@ -8,18 +8,47 @@ const DCircle_1 = require("./DCircle");
|
|
|
8
8
|
const DNumbers_1 = require("./DNumbers");
|
|
9
9
|
const jsts_1 = require("jsts");
|
|
10
10
|
const DPolygonLoop_1 = require("./DPolygonLoop");
|
|
11
|
+
const { buffer: { BufferParameters: { CAP_ROUND, CAP_FLAT, CAP_SQUARE } } } = jsts_1.operation;
|
|
11
12
|
exports.MIN_POINTS_IN_VALID_POLYGON = 3;
|
|
12
13
|
const APPROXIMATION_VALUE = 0.1;
|
|
13
14
|
const MAX_CONVEX_ITERATIONS = 100;
|
|
14
15
|
const CLOSE_TO_INTERSECTION_DISTANCE = 0.001;
|
|
15
16
|
class DPolygon {
|
|
16
|
-
|
|
17
|
+
// eslint-disable-next-line no-useless-constructor,no-empty-function
|
|
18
|
+
constructor(pPoints = []) {
|
|
19
|
+
this.pPoints = pPoints;
|
|
17
20
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
21
|
this.properties = {};
|
|
19
22
|
this.holes = [];
|
|
20
|
-
this.pPoints = [];
|
|
21
23
|
this.searchStore = {};
|
|
22
|
-
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Transform array of triangles to Three.JS vertices
|
|
27
|
+
*
|
|
28
|
+
* ```
|
|
29
|
+
* const geometry = new THREE.BufferGeometry();
|
|
30
|
+
* // create a simple square shape. We duplicate the top left and bottom right
|
|
31
|
+
* // vertices because each vertex needs to appear once per triangle.
|
|
32
|
+
* const vertices = new Float32Array( DPolygon.arrayOfTrianglesToVertices(triangles, 10) );
|
|
33
|
+
*
|
|
34
|
+
* // itemSize = 3 because there are 3 values (components) per vertex
|
|
35
|
+
* geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
|
|
36
|
+
* const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
|
|
37
|
+
* mesh = new THREE.Mesh( geometry, material );
|
|
38
|
+
*
|
|
39
|
+
* scene.add( mesh );
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param triangles
|
|
43
|
+
* @param [height=0]
|
|
44
|
+
*/
|
|
45
|
+
static arrayOfTrianglesToVertices(triangles, height = 0) {
|
|
46
|
+
return triangles.map((v) => v
|
|
47
|
+
.loop()
|
|
48
|
+
.height(height)
|
|
49
|
+
.run()
|
|
50
|
+
.toArrayOfCoords())
|
|
51
|
+
.flat(2);
|
|
23
52
|
}
|
|
24
53
|
/**
|
|
25
54
|
* Get size of min area rectangle.
|
|
@@ -93,7 +122,7 @@ class DPolygon {
|
|
|
93
122
|
return res;
|
|
94
123
|
}
|
|
95
124
|
static createSquareBySize(size) {
|
|
96
|
-
return new DPolygon([DPoint_1.DPoint.
|
|
125
|
+
return new DPolygon([DPoint_1.DPoint.zero(), size.clone().setX(0), size.clone(), size.clone().setY(0)]).close();
|
|
97
126
|
}
|
|
98
127
|
loop() {
|
|
99
128
|
return new DPolygonLoop_1.DPolygonLoop(this);
|
|
@@ -209,8 +238,8 @@ class DPolygon {
|
|
|
209
238
|
const closed = this.deintersection;
|
|
210
239
|
let sum = 0;
|
|
211
240
|
for (let i = 1; i < closed.length; i++) {
|
|
212
|
-
const cur = closed.
|
|
213
|
-
const prev = closed.
|
|
241
|
+
const cur = closed.at(i);
|
|
242
|
+
const prev = closed.at(i - 1);
|
|
214
243
|
sum += prev.x * cur.y - prev.y * cur.x;
|
|
215
244
|
}
|
|
216
245
|
return Math.abs(sum / 2) - this.holes.reduce((a, hole) => a + hole.area, 0);
|
|
@@ -222,8 +251,8 @@ class DPolygon {
|
|
|
222
251
|
const p = this.clone().close();
|
|
223
252
|
for (let i = 0; i < p.length - 1; i++) {
|
|
224
253
|
for (let j = i + 2; j < p.length - 1; j++) {
|
|
225
|
-
const firstLine = p.
|
|
226
|
-
const secondLine = p.
|
|
254
|
+
const firstLine = p.at(i).findLine(p.at(i + 1));
|
|
255
|
+
const secondLine = p.at(j).findLine(p.at(j + 1));
|
|
227
256
|
const intersectionPoint = firstLine.intersection(secondLine);
|
|
228
257
|
if (intersectionPoint &&
|
|
229
258
|
![...firstLine.points, ...secondLine.points].some((t) => t.like(intersectionPoint))) {
|
|
@@ -246,19 +275,19 @@ class DPolygon {
|
|
|
246
275
|
* Get first point
|
|
247
276
|
*/
|
|
248
277
|
get first() {
|
|
249
|
-
return this.
|
|
278
|
+
return this.at(0);
|
|
250
279
|
}
|
|
251
280
|
/**
|
|
252
281
|
* Get second point
|
|
253
282
|
*/
|
|
254
283
|
get second() {
|
|
255
|
-
return this.
|
|
284
|
+
return this.at(1);
|
|
256
285
|
}
|
|
257
286
|
/**
|
|
258
287
|
* Get last point
|
|
259
288
|
*/
|
|
260
289
|
get last() {
|
|
261
|
-
return this.
|
|
290
|
+
return this.at(this.length - 1);
|
|
262
291
|
}
|
|
263
292
|
/**
|
|
264
293
|
* Get min area rectangle
|
|
@@ -268,21 +297,21 @@ class DPolygon {
|
|
|
268
297
|
let resultPolygon = new DPolygon();
|
|
269
298
|
let resultArea = Infinity;
|
|
270
299
|
for (let k = 0; k < p.length - 1; k++) {
|
|
271
|
-
const l = p.
|
|
300
|
+
const l = p.at(k).findLine(p.at(k + 1));
|
|
272
301
|
let maxWidth = 0;
|
|
273
302
|
let maxWidthPoint1 = null;
|
|
274
303
|
let maxWidthPoint2 = null;
|
|
275
304
|
let maxHeight = 0;
|
|
276
305
|
let maxHeightPoint = null;
|
|
277
306
|
for (let i = 0; i < p.length - 1; i++) {
|
|
278
|
-
const p1 = l.findPoint(l.findPerpendicular(p.
|
|
279
|
-
const h = p1.distance(p.
|
|
307
|
+
const p1 = l.findPoint(l.findPerpendicular(p.at(i)));
|
|
308
|
+
const h = p1.distance(p.at(i));
|
|
280
309
|
if (h >= maxHeight) {
|
|
281
310
|
maxHeight = h;
|
|
282
|
-
maxHeightPoint = p.
|
|
311
|
+
maxHeightPoint = p.at(i);
|
|
283
312
|
}
|
|
284
313
|
for (let j = i; j < p.length - 1; j++) {
|
|
285
|
-
const p2 = l.findPoint(l.findPerpendicular(p.
|
|
314
|
+
const p2 = l.findPoint(l.findPerpendicular(p.at(j)));
|
|
286
315
|
const w = p1.distance(p2);
|
|
287
316
|
if (w >= maxWidth) {
|
|
288
317
|
maxWidth = w;
|
|
@@ -338,9 +367,9 @@ class DPolygon {
|
|
|
338
367
|
p = p.deintersection;
|
|
339
368
|
l = p.length;
|
|
340
369
|
for (let i = 1; i < p.length - 1; i++) {
|
|
341
|
-
const p1 = p.
|
|
342
|
-
const p2 = p.
|
|
343
|
-
const p3 = p.
|
|
370
|
+
const p1 = p.at(i - 1);
|
|
371
|
+
const p2 = p.at(i);
|
|
372
|
+
const p3 = p.at(i + 1);
|
|
344
373
|
const d = p2.findInnerAngle(p1, p3);
|
|
345
374
|
if (d > Math.PI || DNumbers_1.DNumbers.likeZero(DNumbers_1.DNumbers.rad2Deg(d)) || DNumbers_1.DNumbers.likePI(d) || DNumbers_1.DNumbers.like2PI(d)) {
|
|
346
375
|
p.removePart(--i, 1);
|
|
@@ -360,8 +389,8 @@ class DPolygon {
|
|
|
360
389
|
let sum = 0;
|
|
361
390
|
const p = this.clone().close();
|
|
362
391
|
for (let i = 1; i < p.length; i++) {
|
|
363
|
-
const p1 = p.
|
|
364
|
-
const p2 = p.
|
|
392
|
+
const p1 = p.at(i - 1);
|
|
393
|
+
const p2 = p.at(i);
|
|
365
394
|
sum += (p2.x - p1.x) * (p2.y + p1.y);
|
|
366
395
|
}
|
|
367
396
|
return sum < 0;
|
|
@@ -406,23 +435,25 @@ class DPolygon {
|
|
|
406
435
|
* @param newCenter
|
|
407
436
|
*/
|
|
408
437
|
setCenter(newCenter) {
|
|
409
|
-
return this.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
let h = '';
|
|
413
|
-
if (this.holes && this.holes.length) {
|
|
414
|
-
h = `, ${this.holes.map((hole) => hole.toString()).join(', ')}`;
|
|
415
|
-
}
|
|
416
|
-
return `POLYGON ((${this.deintersection.pPoints.map((r) => `${r.x} ${r.y}`).join(', ')})${h})`;
|
|
438
|
+
return this.loop()
|
|
439
|
+
.move(newCenter.clone().move(this.center.minus()))
|
|
440
|
+
.run();
|
|
417
441
|
}
|
|
418
442
|
/**
|
|
419
|
-
*
|
|
420
|
-
* @param a Radians
|
|
443
|
+
* @param [type = DPolygon.WKT_POLYGON] Available values `DPolygon.WKT_POLYGON`, `DPolygon.WKT_LINESTRING`
|
|
421
444
|
*/
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
445
|
+
toWKT(type = DPolygon.WKT_POLYGON) {
|
|
446
|
+
if (type === DPolygon.WKT_POLYGON) {
|
|
447
|
+
let h = '';
|
|
448
|
+
if (this.holes && this.holes.length) {
|
|
449
|
+
h = `, ${this.holes.map((hole) => hole.toString())
|
|
450
|
+
.join(', ')}`;
|
|
451
|
+
}
|
|
452
|
+
return `POLYGON ((${this.deintersection.pPoints.map((r) => `${r.x} ${r.y}`)
|
|
453
|
+
.join(', ')})${h})`;
|
|
454
|
+
}
|
|
455
|
+
return `LINESTRING (${this.pPoints.map((r) => `${r.x} ${r.y}`)
|
|
456
|
+
.join(', ')})`;
|
|
426
457
|
}
|
|
427
458
|
/**
|
|
428
459
|
* Filter points
|
|
@@ -432,60 +463,14 @@ class DPolygon {
|
|
|
432
463
|
this.pPoints = this.pPoints.filter(f);
|
|
433
464
|
return this;
|
|
434
465
|
}
|
|
435
|
-
move(x = 0, y) {
|
|
436
|
-
this.pPoints = this.pPoints.map((p) => p.move(x, y));
|
|
437
|
-
this.holes = this.holes.map((h) => h.move(x, y));
|
|
438
|
-
return this;
|
|
439
|
-
}
|
|
440
|
-
scale(x = 0, y) {
|
|
441
|
-
this.pPoints = this.pPoints.map((p) => p.scale(x, y));
|
|
442
|
-
this.holes = this.holes.map((h) => h.scale(x, y));
|
|
443
|
-
return this;
|
|
444
|
-
}
|
|
445
|
-
divide(x = 0, y) {
|
|
446
|
-
this.pPoints = this.pPoints.map((p) => p.divide(x, y));
|
|
447
|
-
this.holes = this.holes.map((h) => h.divide(x, y));
|
|
448
|
-
return this;
|
|
449
|
-
}
|
|
450
|
-
round() {
|
|
451
|
-
this.pPoints = this.pPoints.map((p) => p.round());
|
|
452
|
-
this.holes = this.holes.map((h) => h.round());
|
|
453
|
-
return this;
|
|
454
|
-
}
|
|
455
|
-
floor() {
|
|
456
|
-
this.pPoints = this.pPoints.map((p) => p.floor());
|
|
457
|
-
this.holes = this.holes.map((h) => h.floor());
|
|
458
|
-
return this;
|
|
459
|
-
}
|
|
460
|
-
ceil() {
|
|
461
|
-
this.pPoints = this.pPoints.map((p) => p.ceil());
|
|
462
|
-
this.holes = this.holes.map((h) => h.ceil());
|
|
463
|
-
return this;
|
|
464
|
-
}
|
|
465
|
-
flipVertically(size) {
|
|
466
|
-
this.pPoints = this.pPoints.map((p) => p.flipVertically(size));
|
|
467
|
-
this.holes = this.holes.map((h) => h.flipVertically(size));
|
|
468
|
-
return this;
|
|
469
|
-
}
|
|
470
|
-
toFixed(n = 2) {
|
|
471
|
-
this.pPoints = this.pPoints.map((p) => p.toFixed(n));
|
|
472
|
-
this.holes = this.holes.map((h) => h.toFixed(n));
|
|
473
|
-
return this;
|
|
474
|
-
}
|
|
475
466
|
map(f) {
|
|
476
467
|
this.pPoints = this.pPoints.map(f);
|
|
477
468
|
this.holes = this.holes.map((h) => h.map(f));
|
|
478
469
|
return this;
|
|
479
470
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
while (t < 0) {
|
|
484
|
-
t += this.length;
|
|
485
|
-
}
|
|
486
|
-
return this.pPoints[t % this.length];
|
|
487
|
-
}
|
|
488
|
-
return this.pPoints[index];
|
|
471
|
+
at(index) {
|
|
472
|
+
const { length } = this;
|
|
473
|
+
return this.points[(index % length + length) % length];
|
|
489
474
|
}
|
|
490
475
|
pop() {
|
|
491
476
|
return this.pPoints.pop();
|
|
@@ -508,26 +493,6 @@ class DPolygon {
|
|
|
508
493
|
return (this.pPoints.map((r) => r.getValue()) + this.holes
|
|
509
494
|
.reduce((a, h) => a + h.getValue(), ''));
|
|
510
495
|
}
|
|
511
|
-
degreeToMeters() {
|
|
512
|
-
this.pPoints = this.pPoints.map((r) => r.degreeToMeters());
|
|
513
|
-
this.holes = this.holes.map((h) => h.degreeToMeters());
|
|
514
|
-
return this;
|
|
515
|
-
}
|
|
516
|
-
metersToDegree() {
|
|
517
|
-
this.pPoints = this.pPoints.map((r) => r.metersToDegree());
|
|
518
|
-
this.holes = this.holes.map((h) => h.metersToDegree());
|
|
519
|
-
return this;
|
|
520
|
-
}
|
|
521
|
-
radiansToMeters() {
|
|
522
|
-
this.pPoints = this.pPoints.map((r) => r.radiansToMeters());
|
|
523
|
-
this.holes = this.holes.map((h) => h.radiansToMeters());
|
|
524
|
-
return this;
|
|
525
|
-
}
|
|
526
|
-
metersToRadians() {
|
|
527
|
-
this.pPoints = this.pPoints.map((r) => r.metersToRadians());
|
|
528
|
-
this.holes = this.holes.map((h) => h.metersToRadians());
|
|
529
|
-
return this;
|
|
530
|
-
}
|
|
531
496
|
toString() {
|
|
532
497
|
return `(${this.pPoints.map((r) => r.toString()).join(', ')})`;
|
|
533
498
|
}
|
|
@@ -536,7 +501,7 @@ class DPolygon {
|
|
|
536
501
|
*/
|
|
537
502
|
close() {
|
|
538
503
|
const p0 = this.first;
|
|
539
|
-
if (p0 && !
|
|
504
|
+
if (p0 && !this.closed) {
|
|
540
505
|
this.push(p0.clone());
|
|
541
506
|
}
|
|
542
507
|
return this;
|
|
@@ -546,20 +511,11 @@ class DPolygon {
|
|
|
546
511
|
*/
|
|
547
512
|
open() {
|
|
548
513
|
const p = this.first;
|
|
549
|
-
if (this.length > 2 && p &&
|
|
514
|
+
if (this.length > 2 && p && this.closed) {
|
|
550
515
|
this.pop();
|
|
551
516
|
}
|
|
552
517
|
return this;
|
|
553
518
|
}
|
|
554
|
-
/**
|
|
555
|
-
* Set `height` (`z`)
|
|
556
|
-
* @param z
|
|
557
|
-
*/
|
|
558
|
-
height(z) {
|
|
559
|
-
this.map((p) => p.height(z));
|
|
560
|
-
this.holes = this.holes.map((h) => h.height(z));
|
|
561
|
-
return this;
|
|
562
|
-
}
|
|
563
519
|
add(poly) {
|
|
564
520
|
const res = new DPolygon([...this.points, ...poly.points]).close();
|
|
565
521
|
res.holes = [...this.holes, ...poly.holes].map((h) => h.clone());
|
|
@@ -586,7 +542,7 @@ class DPolygon {
|
|
|
586
542
|
if (!(p instanceof DPolygon)) {
|
|
587
543
|
return false;
|
|
588
544
|
}
|
|
589
|
-
if (this.
|
|
545
|
+
if (this.length !== p.length || this.holes.length !== p.holes.length) {
|
|
590
546
|
return false;
|
|
591
547
|
}
|
|
592
548
|
return (this.same(p) &&
|
|
@@ -597,20 +553,18 @@ class DPolygon {
|
|
|
597
553
|
* @param p
|
|
598
554
|
*/
|
|
599
555
|
same(p) {
|
|
600
|
-
const pClone = p.clone().
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
pClone.
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
.toString());
|
|
613
|
-
}, false);
|
|
556
|
+
const pClone = p.clone().close();
|
|
557
|
+
const thisAsString = this.clone()
|
|
558
|
+
.close()
|
|
559
|
+
.toString();
|
|
560
|
+
for (let i = 0; i < pClone.length; i++) {
|
|
561
|
+
if (thisAsString === pClone.toString() || thisAsString === pClone.clone().reverse()
|
|
562
|
+
.toString()) {
|
|
563
|
+
return true;
|
|
564
|
+
}
|
|
565
|
+
pClone.nextStart();
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
614
568
|
}
|
|
615
569
|
findIndex(p) {
|
|
616
570
|
return this.points.findIndex((t) => t.equal(p));
|
|
@@ -618,7 +572,7 @@ class DPolygon {
|
|
|
618
572
|
/**
|
|
619
573
|
* Get polygon approximation by
|
|
620
574
|
* [Ramer–Douglas–Peucker algorithm](https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm)
|
|
621
|
-
* @param e
|
|
575
|
+
* @param [e=Math.sqrt(this.perimeter)*APPROXIMATION_VALUE]
|
|
622
576
|
*/
|
|
623
577
|
approximation(e = Math.sqrt(this.perimeter) * APPROXIMATION_VALUE) {
|
|
624
578
|
return new DPolygon(this.clone().douglasPeucker(this.pPoints, e));
|
|
@@ -692,10 +646,10 @@ class DPolygon {
|
|
|
692
646
|
/**
|
|
693
647
|
* Check if contain point
|
|
694
648
|
* @param p
|
|
695
|
-
* @param isBorderInside
|
|
696
|
-
* @param move Ignore this parameter
|
|
649
|
+
* @param [isBorderInside=false]
|
|
650
|
+
* @param [move=(0,0)] Ignore this parameter
|
|
697
651
|
*/
|
|
698
|
-
contain(p, isBorderInside = false, move = DPoint_1.DPoint.
|
|
652
|
+
contain(p, isBorderInside = false, move = DPoint_1.DPoint.zero()) {
|
|
699
653
|
const simpleInclude = this.simpleInclude(p);
|
|
700
654
|
if (!simpleInclude) {
|
|
701
655
|
return false;
|
|
@@ -708,7 +662,7 @@ class DPolygon {
|
|
|
708
662
|
const poly = this.deintersection;
|
|
709
663
|
const intersectionPoints = [];
|
|
710
664
|
for (let i = 0; i < poly.length - 1; i++) {
|
|
711
|
-
const polygonLine = poly.
|
|
665
|
+
const polygonLine = poly.at(i).findLine(poly.at(i + 1));
|
|
712
666
|
const intersection = line.intersection(polygonLine, CLOSE_TO_INTERSECTION_DISTANCE);
|
|
713
667
|
if (intersection) {
|
|
714
668
|
intersectionPoints.push(intersection);
|
|
@@ -733,8 +687,8 @@ class DPolygon {
|
|
|
733
687
|
return true;
|
|
734
688
|
}
|
|
735
689
|
for (let i = 0; i < poly.length - 1; i++) {
|
|
736
|
-
const p0 = poly.
|
|
737
|
-
const p1 = poly.
|
|
690
|
+
const p0 = poly.at(i);
|
|
691
|
+
const p1 = poly.at(i + 1);
|
|
738
692
|
const polygonLine = p0.findLine(p1);
|
|
739
693
|
const onBorder = polygonLine.x(p).equal(p) && polygonLine.inRange(p);
|
|
740
694
|
if (onBorder) {
|
|
@@ -758,8 +712,8 @@ class DPolygon {
|
|
|
758
712
|
*/
|
|
759
713
|
removeDuplicates() {
|
|
760
714
|
for (let i = 0; i < this.length - 1; i++) {
|
|
761
|
-
const p1 = this.
|
|
762
|
-
const p2 = this.
|
|
715
|
+
const p1 = this.at(i);
|
|
716
|
+
const p2 = this.at(i + 1);
|
|
763
717
|
if (p1.equal(p2)) {
|
|
764
718
|
this.removePart(i, 1);
|
|
765
719
|
i--;
|
|
@@ -767,11 +721,6 @@ class DPolygon {
|
|
|
767
721
|
}
|
|
768
722
|
return this;
|
|
769
723
|
}
|
|
770
|
-
/**
|
|
771
|
-
* Parse from [OpenLayers](https://openlayers.org/) coordinates or
|
|
772
|
-
* [GeoJSON](https://en.wikipedia.org/wiki/GeoJSON) coordinates
|
|
773
|
-
* @param a
|
|
774
|
-
*/
|
|
775
724
|
static parse(a) {
|
|
776
725
|
return new DPolygon(a.map((r) => DPoint_1.DPoint.parse(r)));
|
|
777
726
|
}
|
|
@@ -878,10 +827,9 @@ class DPolygon {
|
|
|
878
827
|
return this.simpleLogicFunction(p, true, false);
|
|
879
828
|
}
|
|
880
829
|
smartUnion(p) {
|
|
881
|
-
var _a;
|
|
882
830
|
const res = this.clone().simpleUnion(p);
|
|
883
831
|
if (res) {
|
|
884
|
-
let allHoles = [...this.holes, ...p.holes, ...
|
|
832
|
+
let allHoles = [...this.holes, ...p.holes, ...res.holes].map((h) => h.clone());
|
|
885
833
|
for (const a of allHoles) {
|
|
886
834
|
for (const b of allHoles) {
|
|
887
835
|
if (a.equal(b)) {
|
|
@@ -890,12 +838,7 @@ class DPolygon {
|
|
|
890
838
|
const r = a.simpleUnion(b);
|
|
891
839
|
if (r) {
|
|
892
840
|
allHoles = allHoles.filter((v) => !v.equal(a) && !v.equal(b));
|
|
893
|
-
|
|
894
|
-
allHoles = [...allHoles, ...r];
|
|
895
|
-
}
|
|
896
|
-
else {
|
|
897
|
-
allHoles.push(r);
|
|
898
|
-
}
|
|
841
|
+
allHoles.push(r);
|
|
899
842
|
}
|
|
900
843
|
}
|
|
901
844
|
}
|
|
@@ -906,9 +849,36 @@ class DPolygon {
|
|
|
906
849
|
/**
|
|
907
850
|
* Divide polygon to triangles
|
|
908
851
|
*
|
|
909
|
-
* 
|
|
852
|
+
* 
|
|
910
853
|
*/
|
|
911
854
|
toTriangles() {
|
|
855
|
+
const innerAndNotIntersect = (poly, p1, p2) => {
|
|
856
|
+
const l = p1.findLine(p2);
|
|
857
|
+
const { center } = l;
|
|
858
|
+
const intersections = poly.holes.reduce((a, hole) => a && Boolean(hole.clone().close()
|
|
859
|
+
.intersection(l, true).length), Boolean(poly.clone().close()
|
|
860
|
+
.intersection(l, true).length));
|
|
861
|
+
const contain = poly.holes.reduce((a, hole) => a && !hole
|
|
862
|
+
.contain(center), poly.contain(center));
|
|
863
|
+
return !intersections && contain;
|
|
864
|
+
};
|
|
865
|
+
const getTriangle = (poly) => {
|
|
866
|
+
for (let i = 0; i < poly.length; i++) {
|
|
867
|
+
const p0 = poly.at(0);
|
|
868
|
+
const p1 = poly.at(1);
|
|
869
|
+
const p2 = poly.at(2);
|
|
870
|
+
if (innerAndNotIntersect(poly, p0, p2)) {
|
|
871
|
+
poly.removePart(0, 1);
|
|
872
|
+
return new DPolygon([
|
|
873
|
+
p0.clone(),
|
|
874
|
+
p1.clone(),
|
|
875
|
+
p2.clone()
|
|
876
|
+
]);
|
|
877
|
+
}
|
|
878
|
+
poly.push(poly.shift());
|
|
879
|
+
}
|
|
880
|
+
return undefined;
|
|
881
|
+
};
|
|
912
882
|
const p = this.clone().clockWise.open();
|
|
913
883
|
while (p.holes.length) {
|
|
914
884
|
const h = p.holes.shift()
|
|
@@ -917,7 +887,7 @@ class DPolygon {
|
|
|
917
887
|
.reverse()
|
|
918
888
|
.close();
|
|
919
889
|
for (let i = 0; i < p.length; i++) {
|
|
920
|
-
if (
|
|
890
|
+
if (innerAndNotIntersect(p, p.first, h.first)) {
|
|
921
891
|
p.insertAfter(0, ...h.points, p.first);
|
|
922
892
|
break;
|
|
923
893
|
}
|
|
@@ -926,7 +896,7 @@ class DPolygon {
|
|
|
926
896
|
}
|
|
927
897
|
const res = [];
|
|
928
898
|
while (p.length > 3) {
|
|
929
|
-
const triangle =
|
|
899
|
+
const triangle = getTriangle(p);
|
|
930
900
|
if (triangle) {
|
|
931
901
|
res.push(triangle);
|
|
932
902
|
}
|
|
@@ -934,35 +904,22 @@ class DPolygon {
|
|
|
934
904
|
res.push(p);
|
|
935
905
|
return res;
|
|
936
906
|
}
|
|
907
|
+
get closed() {
|
|
908
|
+
return this.first.equal(this.last);
|
|
909
|
+
}
|
|
937
910
|
/**
|
|
938
|
-
* @
|
|
911
|
+
* @param v
|
|
912
|
+
* @param [quadrantSegments=64]
|
|
913
|
+
* @param [type=DPolygon.CAP_ROUND] DPolygon.CAP_ROUND || DPolygon.CAP_FLAT || DPolygon.CAP_SQUARE
|
|
939
914
|
*/
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
p0.clone(),
|
|
949
|
-
p1.clone(),
|
|
950
|
-
p2.clone()
|
|
951
|
-
]);
|
|
952
|
-
}
|
|
953
|
-
this.push(this.shift());
|
|
954
|
-
}
|
|
955
|
-
return undefined;
|
|
956
|
-
}
|
|
957
|
-
innerAndNotIntersect(p1, p2) {
|
|
958
|
-
const l = p1.findLine(p2);
|
|
959
|
-
const { center } = l;
|
|
960
|
-
const intersections = this.holes.reduce((a, hole) => a && Boolean(hole.clone().close()
|
|
961
|
-
.intersection(l, true).length), Boolean(this.clone().close()
|
|
962
|
-
.intersection(l, true).length));
|
|
963
|
-
const contain = this.holes.reduce((a, hole) => a && !hole
|
|
964
|
-
.contain(center), this.contain(center));
|
|
965
|
-
return !intersections && contain;
|
|
915
|
+
buffer(v, quadrantSegments = 64, type = DPolygon.CAP_ROUND) {
|
|
916
|
+
const reader = new jsts_1.io.WKTReader();
|
|
917
|
+
const { noHoles, closed } = this;
|
|
918
|
+
const points = reader
|
|
919
|
+
.read(noHoles.toWKT(closed ? DPolygon.WKT_POLYGON : DPolygon.WKT_LINESTRING))
|
|
920
|
+
.buffer(v, quadrantSegments, type)
|
|
921
|
+
.getCoordinates();
|
|
922
|
+
return new DPolygon(points.map(({ x, y }) => new DPoint_1.DPoint(x, y)));
|
|
966
923
|
}
|
|
967
924
|
simpleIncludeX(p) {
|
|
968
925
|
const { x } = p;
|
|
@@ -996,7 +953,7 @@ class DPolygon {
|
|
|
996
953
|
const start = this.first;
|
|
997
954
|
ctx.moveTo(start.x, start.y);
|
|
998
955
|
for (let i = 1; i <= (steps % this.length); i++) {
|
|
999
|
-
const { x, y } = this.
|
|
956
|
+
const { x, y } = this.at(i);
|
|
1000
957
|
ctx.lineTo(x, y);
|
|
1001
958
|
}
|
|
1002
959
|
}
|
|
@@ -1012,8 +969,8 @@ class DPolygon {
|
|
|
1012
969
|
const poly = this.deintersection;
|
|
1013
970
|
let totalFi = 0;
|
|
1014
971
|
for (let i = 0; i < poly.length - 1; i++) {
|
|
1015
|
-
const p1 = poly.
|
|
1016
|
-
const p2 = poly.
|
|
972
|
+
const p1 = poly.at(i);
|
|
973
|
+
const p2 = poly.at(i + 1);
|
|
1017
974
|
const line1 = new DLine_1.DLine(p1.x - p.x, p1.y - p.y, 0);
|
|
1018
975
|
const line2 = new DLine_1.DLine(p2.x - p.x, p2.y - p.y, 0);
|
|
1019
976
|
const fiDif = line1.findFi(line2);
|
|
@@ -1125,3 +1082,17 @@ class DPolygon {
|
|
|
1125
1082
|
}
|
|
1126
1083
|
}
|
|
1127
1084
|
exports.DPolygon = DPolygon;
|
|
1085
|
+
/**
|
|
1086
|
+
* Specifies a round line buffer end cap style.
|
|
1087
|
+
*/
|
|
1088
|
+
DPolygon.CAP_ROUND = CAP_ROUND;
|
|
1089
|
+
/**
|
|
1090
|
+
* Specifies a flat line buffer end cap style.
|
|
1091
|
+
*/
|
|
1092
|
+
DPolygon.CAP_FLAT = CAP_FLAT;
|
|
1093
|
+
/**
|
|
1094
|
+
* Specifies a square line buffer end cap style.
|
|
1095
|
+
*/
|
|
1096
|
+
DPolygon.CAP_SQUARE = CAP_SQUARE;
|
|
1097
|
+
DPolygon.WKT_LINESTRING = 'LINESTRING';
|
|
1098
|
+
DPolygon.WKT_POLYGON = 'POLYGON';
|
package/dist/DPolygonLoop.d.ts
CHANGED
|
@@ -10,20 +10,89 @@ export declare class DPolygonLoop {
|
|
|
10
10
|
* Run loop
|
|
11
11
|
*/
|
|
12
12
|
run(): DPolygon;
|
|
13
|
+
/**
|
|
14
|
+
* @param zoom default value would be `z` of point
|
|
15
|
+
*/
|
|
13
16
|
getTileFromCoords(zoom?: number): DPolygonLoop;
|
|
17
|
+
/**
|
|
18
|
+
* @param zoom default value would be `z` of point
|
|
19
|
+
*/
|
|
14
20
|
getCoordsFromTile(zoom?: number): DPolygonLoop;
|
|
15
21
|
height(z: number): DPolygonLoop;
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Set `x` value
|
|
24
|
+
* @param x
|
|
25
|
+
*/
|
|
26
|
+
setX(x: number): DPolygonLoop;
|
|
27
|
+
/**
|
|
28
|
+
* Transform `x` value by function
|
|
29
|
+
* @param f
|
|
30
|
+
*/
|
|
31
|
+
setX(f: SetterFunction): DPolygonLoop;
|
|
32
|
+
/**
|
|
33
|
+
* Set `y` value
|
|
34
|
+
* @param y
|
|
35
|
+
*/
|
|
36
|
+
setY(y: number): DPolygonLoop;
|
|
37
|
+
/**
|
|
38
|
+
* Transform `y` value by function
|
|
39
|
+
* @param f
|
|
40
|
+
*/
|
|
41
|
+
setY(f: SetterFunction): DPolygonLoop;
|
|
18
42
|
rotate(a: number): DPolygonLoop;
|
|
19
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Add `v` to `x` and `y`
|
|
45
|
+
* @param v
|
|
46
|
+
*/
|
|
47
|
+
move(v: number): DPolygonLoop;
|
|
48
|
+
/**
|
|
49
|
+
* Add `p.x` to `x` field and `p.y` to `y` field.
|
|
50
|
+
* @param p
|
|
51
|
+
*/
|
|
52
|
+
move(p: DPoint): DPolygonLoop;
|
|
53
|
+
/**
|
|
54
|
+
* Add `x` to `x` field and `y` to `y` field.
|
|
55
|
+
* @param x
|
|
56
|
+
* @param y
|
|
57
|
+
*/
|
|
58
|
+
move(x: number, y: number): DPolygonLoop;
|
|
20
59
|
round(): DPolygonLoop;
|
|
21
60
|
ceil(): DPolygonLoop;
|
|
22
61
|
floor(): DPolygonLoop;
|
|
23
62
|
toFixed(n?: number): DPolygonLoop;
|
|
24
63
|
abs(): DPolygonLoop;
|
|
25
|
-
|
|
26
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Multiply `v` to `x` and `y`
|
|
66
|
+
* @param v
|
|
67
|
+
*/
|
|
68
|
+
scale(v: number): DPolygonLoop;
|
|
69
|
+
/**
|
|
70
|
+
* Multiply `p.x` to `x` field and `p.y` to `y` field.
|
|
71
|
+
* @param p
|
|
72
|
+
*/
|
|
73
|
+
scale(p: DPoint): DPolygonLoop;
|
|
74
|
+
/**
|
|
75
|
+
* Multiply `x` to `x` field and `y` to `y` field.
|
|
76
|
+
* @param x
|
|
77
|
+
* @param y
|
|
78
|
+
*/
|
|
79
|
+
scale(x: number, y: number): DPolygonLoop;
|
|
80
|
+
/**
|
|
81
|
+
* Divide `x` and `y` to `v`
|
|
82
|
+
* @param v
|
|
83
|
+
*/
|
|
84
|
+
divide(v: number): DPolygonLoop;
|
|
85
|
+
/**
|
|
86
|
+
* Divide `x` field to `p.x` and `y` field to `p.y`.
|
|
87
|
+
* @param p
|
|
88
|
+
*/
|
|
89
|
+
divide(p: DPoint): DPolygonLoop;
|
|
90
|
+
/**
|
|
91
|
+
* Divide `x` field to `x` and `y` field to `y`.
|
|
92
|
+
* @param x
|
|
93
|
+
* @param y
|
|
94
|
+
*/
|
|
95
|
+
divide(x: number, y: number): DPolygonLoop;
|
|
27
96
|
degreeToRadians(): DPolygonLoop;
|
|
28
97
|
radiansToDegrees(): DPolygonLoop;
|
|
29
98
|
radiansToMeters(): DPolygonLoop;
|
|
@@ -37,5 +106,14 @@ export declare class DPolygonLoop {
|
|
|
37
106
|
minus(): DPolygonLoop;
|
|
38
107
|
degreeToMeters(): DPolygonLoop;
|
|
39
108
|
metersToDegree(): DPolygonLoop;
|
|
40
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Flip vertically
|
|
111
|
+
* @param size canvas size
|
|
112
|
+
*/
|
|
113
|
+
flipVertically(size: DPoint): DPolygonLoop;
|
|
114
|
+
/**
|
|
115
|
+
* Flip vertically
|
|
116
|
+
* @param height canvas height
|
|
117
|
+
*/
|
|
118
|
+
flipVertically(height: number): DPolygonLoop;
|
|
41
119
|
}
|