dgeoutils 2.2.18 → 2.2.24
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/DLine.js +11 -14
- package/dist/DPolygon.d.ts +10 -0
- package/dist/DPolygon.js +127 -62
- package/dist/utils.d.ts +1 -1
- package/package.json +2 -2
package/dist/DLine.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DLine = void 0;
|
|
4
4
|
const DPoint_1 = require("./DPoint");
|
|
5
5
|
const utils_1 = require("./utils");
|
|
6
|
+
const DNumbers_1 = require("./DNumbers");
|
|
6
7
|
class DLine {
|
|
7
8
|
constructor(a, b, c, begin = DPoint_1.DPoint.zero(), end = DPoint_1.DPoint.zero()) {
|
|
8
9
|
this.a = a;
|
|
@@ -49,7 +50,7 @@ class DLine {
|
|
|
49
50
|
intersectionWithCircle(circle) {
|
|
50
51
|
const { center, r } = circle;
|
|
51
52
|
const per = this.findPerpendicular(center);
|
|
52
|
-
const t = this.
|
|
53
|
+
const t = this.findPoint(per);
|
|
53
54
|
let distance = t.distance(center);
|
|
54
55
|
if (this.begin.equal(center)) {
|
|
55
56
|
distance = 0;
|
|
@@ -221,19 +222,15 @@ class DLine {
|
|
|
221
222
|
}
|
|
222
223
|
movePoint(p, d) {
|
|
223
224
|
const fi = this.findFi(new DLine(1, 0, 0));
|
|
224
|
-
const td = this.
|
|
225
|
-
const
|
|
226
|
-
const
|
|
227
|
-
const p1T =
|
|
228
|
-
const p2T =
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (this.inRange(p1T) || this.inRange(p2T)) {
|
|
234
|
-
return p2;
|
|
235
|
-
}
|
|
236
|
-
return p3;
|
|
225
|
+
const td = this.x(new DPoint_1.DPoint(1, 1)).distance(this.x(new DPoint_1.DPoint(2, 2))) / 2;
|
|
226
|
+
const sinCos = new DPoint_1.DPoint(Math.sin(fi), Math.cos(fi));
|
|
227
|
+
const dt = sinCos.clone().scale(td);
|
|
228
|
+
const p1T = p.clone().move(dt.clone().minus());
|
|
229
|
+
const p2T = p.clone().move(dt);
|
|
230
|
+
if (DNumbers_1.DNumbers.like(this.y(p1T).y, p1T.y) || DNumbers_1.DNumbers.like(this.y(p2T).y, p2T.y)) {
|
|
231
|
+
return p.clone().move(sinCos.scale(d));
|
|
232
|
+
}
|
|
233
|
+
return p.clone().move(sinCos.scale(d).setX(({ x }) => -x));
|
|
237
234
|
}
|
|
238
235
|
findFi({ a, b }, delta = 1.0001) {
|
|
239
236
|
const { a: q, b: w } = this;
|
package/dist/DPolygon.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { DCoord, DPoint, LatLng } from './DPoint';
|
|
3
3
|
import { DLine } from './DLine';
|
|
4
4
|
import { DPolygonLoop } from './DPolygonLoop';
|
|
5
|
+
import { True } from './utils';
|
|
5
6
|
export declare const MIN_POINTS_IN_VALID_POLYGON = 3;
|
|
6
7
|
export declare class DPolygon {
|
|
7
8
|
private pPoints;
|
|
@@ -50,6 +51,8 @@ export declare class DPolygon {
|
|
|
50
51
|
get isClockwise(): boolean;
|
|
51
52
|
get clockWise(): DPolygon;
|
|
52
53
|
get noHoles(): DPolygon;
|
|
54
|
+
reduce<T>(f: (a: T, p: DPoint) => T, v: T): T;
|
|
55
|
+
reduce<T>(f: (a: T, p: DPoint, index: number) => T, v: T): T;
|
|
53
56
|
intersection(l: DLine, includeOnly?: boolean): DPoint[];
|
|
54
57
|
setCenter(newCenter: DPoint): DPolygon;
|
|
55
58
|
static WKT_LINESTRING: string;
|
|
@@ -58,6 +61,8 @@ export declare class DPolygon {
|
|
|
58
61
|
filter(f: (p: DPoint) => boolean): DPolygon;
|
|
59
62
|
map(f: (r: DPoint) => DPoint): DPolygon;
|
|
60
63
|
map(f: (r: DPoint, index: number) => DPoint): DPolygon;
|
|
64
|
+
mapArray<T>(f: (r: DPoint) => T): T[];
|
|
65
|
+
mapArray<T>(f: (r: DPoint, index: number) => T): T[];
|
|
61
66
|
sort(f: (a: DPoint, b: DPoint) => number): DPolygon;
|
|
62
67
|
at(index: number): DPoint;
|
|
63
68
|
pop(): DPoint;
|
|
@@ -75,6 +80,8 @@ export declare class DPolygon {
|
|
|
75
80
|
equal(p: DPolygon | null): boolean;
|
|
76
81
|
same(p: DPolygon): boolean;
|
|
77
82
|
findIndex(p: DPoint): number;
|
|
83
|
+
findIndex(f: (p: DPoint) => boolean): number;
|
|
84
|
+
findIndex(f: (p: DPoint, index: number) => boolean): number;
|
|
78
85
|
approximation(e?: number): DPolygon;
|
|
79
86
|
insertAfter(index: number, ...points: DPoint[]): void;
|
|
80
87
|
removePart(index: number, count: number): DPoint[];
|
|
@@ -102,8 +109,11 @@ export declare class DPolygon {
|
|
|
102
109
|
getTrianglesPointIndexes(): number[];
|
|
103
110
|
get closed(): boolean;
|
|
104
111
|
buffer(v: number, quadrantSegments?: number, type?: number): DPolygon;
|
|
112
|
+
sideBuffers(v: number, quadrantSegments?: number): [DPolygon, DPolygon];
|
|
105
113
|
bezier(step?: number): DPolygon;
|
|
106
114
|
setGrowingHeight(from: number, to: number): DPolygon;
|
|
115
|
+
loopPointsGenerator(): () => Generator<[DPoint, DPoint, undefined, number]>;
|
|
116
|
+
loopPointsGenerator(withLine: True): () => Generator<[DPoint, DPoint, DLine, number]>;
|
|
107
117
|
private getBezierPoint;
|
|
108
118
|
private simpleIncludeX;
|
|
109
119
|
private simpleIncludeY;
|
package/dist/DPolygon.js
CHANGED
|
@@ -13,6 +13,43 @@ exports.MIN_POINTS_IN_VALID_POLYGON = 3;
|
|
|
13
13
|
const APPROXIMATION_VALUE = 0.1;
|
|
14
14
|
const MAX_CONVEX_ITERATIONS = 100;
|
|
15
15
|
const CLOSE_TO_INTERSECTION_DISTANCE = 0.001;
|
|
16
|
+
const containCalculator = (poly, p) => {
|
|
17
|
+
const hasSamePoint = poly.points.some((point) => point.equal(p));
|
|
18
|
+
if (hasSamePoint) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
for (const [, , polygonLine] of poly.loopPointsGenerator(true)()) {
|
|
22
|
+
const onBorder = polygonLine.x(p).equal(p) && polygonLine.inRange(p);
|
|
23
|
+
if (onBorder) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let totalFi = 0;
|
|
28
|
+
for (const [{ x, y }, { x: a, y: b }] of poly.loopPointsGenerator()()) {
|
|
29
|
+
const line1 = new DLine_1.DLine(x - p.x, y - p.y, 0);
|
|
30
|
+
const line2 = new DLine_1.DLine(a - p.x, b - p.y, 0);
|
|
31
|
+
const fiDif = line1.findFi(line2);
|
|
32
|
+
if (line1.vectorProduct(line2).c > 0) {
|
|
33
|
+
totalFi += fiDif;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
totalFi -= fiDif;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const eps = Math.PI / 10000;
|
|
40
|
+
let result = false;
|
|
41
|
+
const absTotalFi = Math.abs(totalFi);
|
|
42
|
+
if (absTotalFi < eps) {
|
|
43
|
+
result = false;
|
|
44
|
+
}
|
|
45
|
+
else if (Math.abs(2 * Math.PI - absTotalFi) < eps) {
|
|
46
|
+
result = true;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
throw new Error('contains2 faild');
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
};
|
|
16
53
|
class DPolygon {
|
|
17
54
|
constructor(pPoints = []) {
|
|
18
55
|
this.pPoints = pPoints;
|
|
@@ -100,16 +137,16 @@ class DPolygon {
|
|
|
100
137
|
return this.pPoints;
|
|
101
138
|
}
|
|
102
139
|
get maxX() {
|
|
103
|
-
return this.
|
|
140
|
+
return this.reduce((a, r) => Math.max(a, r.x), -Infinity);
|
|
104
141
|
}
|
|
105
142
|
get minX() {
|
|
106
|
-
return this.
|
|
143
|
+
return this.reduce((a, r) => Math.min(a, r.x), Infinity);
|
|
107
144
|
}
|
|
108
145
|
get maxY() {
|
|
109
|
-
return this.
|
|
146
|
+
return this.reduce((a, r) => Math.max(a, r.y), -Infinity);
|
|
110
147
|
}
|
|
111
148
|
get minY() {
|
|
112
|
-
return this.
|
|
149
|
+
return this.reduce((a, r) => Math.min(a, r.y), Infinity);
|
|
113
150
|
}
|
|
114
151
|
get center() {
|
|
115
152
|
return this.leftTop.move(this.size.divide(2));
|
|
@@ -156,24 +193,25 @@ class DPolygon {
|
|
|
156
193
|
}
|
|
157
194
|
get perimeter() {
|
|
158
195
|
let p = 0;
|
|
159
|
-
for (
|
|
160
|
-
p +=
|
|
196
|
+
for (const [p1, p2] of this.loopPointsGenerator()()) {
|
|
197
|
+
p += p1.distance(p2);
|
|
161
198
|
}
|
|
162
199
|
return p;
|
|
163
200
|
}
|
|
164
201
|
get area() {
|
|
165
|
-
const closed = this.deintersection;
|
|
166
202
|
let sum = 0;
|
|
167
|
-
for (
|
|
168
|
-
|
|
169
|
-
const prev = closed.at(i - 1);
|
|
170
|
-
sum += prev.x * cur.y - prev.y * cur.x;
|
|
203
|
+
for (const [{ x, y }, { x: a, y: b }] of this.deintersection.loopPointsGenerator()()) {
|
|
204
|
+
sum += x * b - y * a;
|
|
171
205
|
}
|
|
172
206
|
return Math.abs(sum / 2) - this.holes.reduce((a, hole) => a + hole.area, 0);
|
|
173
207
|
}
|
|
174
208
|
get deintersection() {
|
|
175
|
-
|
|
209
|
+
let p = this.clone().close();
|
|
210
|
+
const store = {};
|
|
176
211
|
for (let i = 0; i < p.length - 1; i++) {
|
|
212
|
+
const k = p.at(i).toString();
|
|
213
|
+
store[k] = store[k] || [];
|
|
214
|
+
store[k].push(i);
|
|
177
215
|
for (let j = i + 2; j < p.length - 1; j++) {
|
|
178
216
|
const firstLine = p.at(i).findLine(p.at(i + 1));
|
|
179
217
|
const secondLine = p.at(j).findLine(p.at(j + 1));
|
|
@@ -187,6 +225,23 @@ class DPolygon {
|
|
|
187
225
|
}
|
|
188
226
|
}
|
|
189
227
|
}
|
|
228
|
+
for (const key of Object.keys(store)) {
|
|
229
|
+
const record = store[key];
|
|
230
|
+
if (record.length > 1) {
|
|
231
|
+
for (let j = record.length - 1; j > 0; j--) {
|
|
232
|
+
const origin = p.clone();
|
|
233
|
+
const d = record[j] - record[j - 1];
|
|
234
|
+
if (d > 1) {
|
|
235
|
+
const part = new DPolygon(origin.removePart(record[j - 1], d));
|
|
236
|
+
const allInside = part.reduce((a, e) => a && containCalculator(origin, e), true);
|
|
237
|
+
if (allInside && origin.isClockwise === part.isClockwise) {
|
|
238
|
+
origin.insertAfter(record[j - 1] - 1, ...part.reverse().points);
|
|
239
|
+
p = origin;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
190
245
|
return p;
|
|
191
246
|
}
|
|
192
247
|
get valid() {
|
|
@@ -205,19 +260,18 @@ class DPolygon {
|
|
|
205
260
|
const p = this.convex;
|
|
206
261
|
let resultPolygon = new DPolygon();
|
|
207
262
|
let resultArea = Infinity;
|
|
208
|
-
for (
|
|
209
|
-
const l = p.at(k).findLine(p.at(k + 1));
|
|
263
|
+
for (const [, , l] of p.loopPointsGenerator(true)()) {
|
|
210
264
|
let maxWidth = 0;
|
|
211
265
|
let maxWidthPoint1 = null;
|
|
212
266
|
let maxWidthPoint2 = null;
|
|
213
267
|
let maxHeight = 0;
|
|
214
268
|
let maxHeightPoint = null;
|
|
215
|
-
for (
|
|
216
|
-
const p1 = l.findPoint(l.findPerpendicular(
|
|
217
|
-
const h = p1.distance(
|
|
269
|
+
for (const [z, , , i] of p.loopPointsGenerator()()) {
|
|
270
|
+
const p1 = l.findPoint(l.findPerpendicular(z));
|
|
271
|
+
const h = p1.distance(z);
|
|
218
272
|
if (h >= maxHeight) {
|
|
219
273
|
maxHeight = h;
|
|
220
|
-
maxHeightPoint =
|
|
274
|
+
maxHeightPoint = z;
|
|
221
275
|
}
|
|
222
276
|
for (let j = i; j < p.length - 1; j++) {
|
|
223
277
|
const p2 = l.findPoint(l.findPerpendicular(p.at(j)));
|
|
@@ -290,11 +344,9 @@ class DPolygon {
|
|
|
290
344
|
}
|
|
291
345
|
get isClockwise() {
|
|
292
346
|
let sum = 0;
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
const p2 = p.at(i);
|
|
297
|
-
sum += (p2.x - p1.x) * (p2.y + p1.y);
|
|
347
|
+
for (const [{ x, y }, { x: a, y: b }] of this.clone().close()
|
|
348
|
+
.loopPointsGenerator()()) {
|
|
349
|
+
sum += (a - x) * (b + y);
|
|
298
350
|
}
|
|
299
351
|
return sum < 0;
|
|
300
352
|
}
|
|
@@ -309,12 +361,12 @@ class DPolygon {
|
|
|
309
361
|
res.holes = [];
|
|
310
362
|
return res;
|
|
311
363
|
}
|
|
364
|
+
reduce(f, v) {
|
|
365
|
+
return this.pPoints.reduce(f, v);
|
|
366
|
+
}
|
|
312
367
|
intersection(l, includeOnly = false) {
|
|
313
368
|
const res = [];
|
|
314
|
-
for (
|
|
315
|
-
const p1 = this.pPoints[i];
|
|
316
|
-
const p2 = this.pPoints[i + 1];
|
|
317
|
-
const line = p1.findLine(p2);
|
|
369
|
+
for (const [, , line] of this.loopPointsGenerator(true)()) {
|
|
318
370
|
const intersect = line.intersection(l, 0, includeOnly);
|
|
319
371
|
if (intersect) {
|
|
320
372
|
res.push(intersect);
|
|
@@ -334,10 +386,10 @@ class DPolygon {
|
|
|
334
386
|
h = `, ${this.holes.map((hole) => hole.toString())
|
|
335
387
|
.join(', ')}`;
|
|
336
388
|
}
|
|
337
|
-
return `POLYGON ((${this.deintersection.
|
|
389
|
+
return `POLYGON ((${this.deintersection.mapArray((r) => `${r.x} ${r.y}${withZ ? ` ${r.z}` : ''}`)
|
|
338
390
|
.join(', ')})${h})`;
|
|
339
391
|
}
|
|
340
|
-
return `LINESTRING (${this.
|
|
392
|
+
return `LINESTRING (${this.mapArray((r) => `${r.x} ${r.y}${withZ ? ` ${r.z}` : ''}`)
|
|
341
393
|
.join(', ')})`;
|
|
342
394
|
}
|
|
343
395
|
filter(f) {
|
|
@@ -345,10 +397,13 @@ class DPolygon {
|
|
|
345
397
|
return this;
|
|
346
398
|
}
|
|
347
399
|
map(f) {
|
|
348
|
-
this.pPoints = this.
|
|
400
|
+
this.pPoints = this.mapArray(f);
|
|
349
401
|
this.holes = this.holes.map((h) => h.map(f));
|
|
350
402
|
return this;
|
|
351
403
|
}
|
|
404
|
+
mapArray(f) {
|
|
405
|
+
return this.pPoints.map(f);
|
|
406
|
+
}
|
|
352
407
|
sort(f) {
|
|
353
408
|
this.points.sort(f);
|
|
354
409
|
return this;
|
|
@@ -379,7 +434,7 @@ class DPolygon {
|
|
|
379
434
|
.reduce((a, h) => a + h.getValue(), ''));
|
|
380
435
|
}
|
|
381
436
|
toString() {
|
|
382
|
-
return `(${this.
|
|
437
|
+
return `(${this.mapArray((r) => r.toString()).join(', ')})`;
|
|
383
438
|
}
|
|
384
439
|
close() {
|
|
385
440
|
const p0 = this.first;
|
|
@@ -433,8 +488,11 @@ class DPolygon {
|
|
|
433
488
|
}
|
|
434
489
|
return false;
|
|
435
490
|
}
|
|
436
|
-
findIndex(
|
|
437
|
-
|
|
491
|
+
findIndex(a) {
|
|
492
|
+
if (a instanceof DPoint_1.DPoint) {
|
|
493
|
+
return this.points.findIndex((t) => t.equal(a));
|
|
494
|
+
}
|
|
495
|
+
return this.points.findIndex(a);
|
|
438
496
|
}
|
|
439
497
|
approximation(e = Math.sqrt(this.perimeter) * APPROXIMATION_VALUE) {
|
|
440
498
|
return new DPolygon(this.clone().douglasPeucker(this.pPoints, e));
|
|
@@ -508,11 +566,9 @@ class DPolygon {
|
|
|
508
566
|
}
|
|
509
567
|
const poly = this.deintersection;
|
|
510
568
|
let totalFi = 0;
|
|
511
|
-
for (
|
|
512
|
-
const
|
|
513
|
-
const
|
|
514
|
-
const line1 = new DLine_1.DLine(p1.x - p.x, p1.y - p.y, 0);
|
|
515
|
-
const line2 = new DLine_1.DLine(p2.x - p.x, p2.y - p.y, 0);
|
|
569
|
+
for (const [{ x, y }, { x: a, y: b }] of poly.loopPointsGenerator()()) {
|
|
570
|
+
const line1 = new DLine_1.DLine(x - p.x, y - p.y, 0);
|
|
571
|
+
const line2 = new DLine_1.DLine(a - p.x, b - p.y, 0);
|
|
516
572
|
const fiDif = line1.findFi(line2);
|
|
517
573
|
if (line1.vectorProduct(line2).c > 0) {
|
|
518
574
|
totalFi += fiDif;
|
|
@@ -522,18 +578,14 @@ class DPolygon {
|
|
|
522
578
|
}
|
|
523
579
|
}
|
|
524
580
|
const eps = Math.PI / 10000;
|
|
525
|
-
let result = false;
|
|
526
581
|
const absTotalFi = Math.abs(totalFi);
|
|
527
582
|
if (absTotalFi < eps) {
|
|
528
|
-
|
|
583
|
+
return false;
|
|
529
584
|
}
|
|
530
585
|
else if (Math.abs(2 * Math.PI - absTotalFi) < eps) {
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
throw new Error('contains2 faild');
|
|
586
|
+
return true;
|
|
535
587
|
}
|
|
536
|
-
|
|
588
|
+
throw new Error('contains2 faild');
|
|
537
589
|
}
|
|
538
590
|
onBorder(p) {
|
|
539
591
|
const simpleInclude = this.simpleInclude(p);
|
|
@@ -543,10 +595,7 @@ class DPolygon {
|
|
|
543
595
|
if (hasSamePoint) {
|
|
544
596
|
return true;
|
|
545
597
|
}
|
|
546
|
-
for (
|
|
547
|
-
const p0 = poly.at(i);
|
|
548
|
-
const p1 = poly.at(i + 1);
|
|
549
|
-
const polygonLine = p0.findLine(p1);
|
|
598
|
+
for (const [, , polygonLine] of poly.loopPointsGenerator(true)()) {
|
|
550
599
|
const onBorder = polygonLine.x(p).equal(p) && polygonLine.inRange(p);
|
|
551
600
|
if (onBorder) {
|
|
552
601
|
return true;
|
|
@@ -576,21 +625,19 @@ class DPolygon {
|
|
|
576
625
|
return new DPolygon(a.map((r) => DPoint_1.DPoint.parse(r)));
|
|
577
626
|
}
|
|
578
627
|
toArrayOfCoords() {
|
|
579
|
-
return this.
|
|
628
|
+
return this.mapArray((r) => r.toCoords());
|
|
580
629
|
}
|
|
581
630
|
divideToPieces(piecesCount) {
|
|
582
631
|
const { fullLength } = this;
|
|
583
632
|
const pieceLength = fullLength / piecesCount;
|
|
584
633
|
let currentPieceLength = pieceLength;
|
|
585
|
-
for (
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
if (p1.distance(p2) === currentPieceLength) {
|
|
634
|
+
for (const [p1, p2, , i] of this.loopPointsGenerator()()) {
|
|
635
|
+
const d = p1.distance(p2);
|
|
636
|
+
if (d === currentPieceLength) {
|
|
589
637
|
p2.properties.pieceBorder = true;
|
|
590
638
|
currentPieceLength = pieceLength;
|
|
591
|
-
continue;
|
|
592
639
|
}
|
|
593
|
-
if (
|
|
640
|
+
else if (d - currentPieceLength > 0) {
|
|
594
641
|
const circle = new DCircle_1.DCircle(p1, currentPieceLength);
|
|
595
642
|
const line = p1.findLine(p2);
|
|
596
643
|
const intersectionPoint = line.intersectionWithCircle(circle)
|
|
@@ -598,10 +645,9 @@ class DPolygon {
|
|
|
598
645
|
intersectionPoint.properties.pieceBorder = true;
|
|
599
646
|
this.insertAfter(i, intersectionPoint);
|
|
600
647
|
currentPieceLength = pieceLength;
|
|
601
|
-
continue;
|
|
602
648
|
}
|
|
603
|
-
|
|
604
|
-
currentPieceLength -=
|
|
649
|
+
else {
|
|
650
|
+
currentPieceLength -= d;
|
|
605
651
|
}
|
|
606
652
|
}
|
|
607
653
|
return this;
|
|
@@ -812,6 +858,17 @@ class DPolygon {
|
|
|
812
858
|
.getCoordinates();
|
|
813
859
|
return new DPolygon(points.map(({ x, y }) => new DPoint_1.DPoint(x, y)));
|
|
814
860
|
}
|
|
861
|
+
sideBuffers(v, quadrantSegments = 64) {
|
|
862
|
+
const { first, last } = this;
|
|
863
|
+
const buffer = this.buffer(v, quadrantSegments, DPolygon.CAP_FLAT).open();
|
|
864
|
+
const [start0, start1] = first.sortByDistance(buffer).points.map((r) => r.properties.index);
|
|
865
|
+
const [end0, end1] = last.sortByDistance(buffer).points.map((r) => r.properties.index);
|
|
866
|
+
const fromPoint = Math.min(Math.max(start0, start1), Math.max(end0, end1));
|
|
867
|
+
const toPoint = Math.max(Math.min(start0, start1), Math.min(end0, end1));
|
|
868
|
+
const linePart = new DPolygon(buffer.removePart(fromPoint - 1, toPoint - fromPoint + 1));
|
|
869
|
+
buffer.unshift(buffer.pop());
|
|
870
|
+
return [linePart, buffer];
|
|
871
|
+
}
|
|
815
872
|
bezier(step = 0.1) {
|
|
816
873
|
const res = new DPolygon();
|
|
817
874
|
for (let i = 0; i < 1; i += step) {
|
|
@@ -833,13 +890,21 @@ class DPolygon {
|
|
|
833
890
|
.run();
|
|
834
891
|
return this;
|
|
835
892
|
}
|
|
893
|
+
loopPointsGenerator(withLine = false) {
|
|
894
|
+
const that = this;
|
|
895
|
+
return function* () {
|
|
896
|
+
for (let i = 0; i < that.length - 1; i++) {
|
|
897
|
+
const p1 = that.at(i);
|
|
898
|
+
const p2 = that.at(i + 1);
|
|
899
|
+
yield [p1, p2, withLine ? p1.findLine(p2) : undefined, i];
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
}
|
|
836
903
|
getBezierPoint(v) {
|
|
837
904
|
if (this.length === 1) {
|
|
838
905
|
return this.first;
|
|
839
906
|
}
|
|
840
|
-
for (
|
|
841
|
-
const p1 = this.at(i);
|
|
842
|
-
const p2 = this.at(i + 1);
|
|
907
|
+
for (const [p1, p2] of this.loopPointsGenerator()()) {
|
|
843
908
|
p1.move(p2.clone().move(p1.clone().minus())
|
|
844
909
|
.scale(v));
|
|
845
910
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare const gaussianElimination: {
|
|
|
22
22
|
(matrix: number[][]): number[];
|
|
23
23
|
MIN: number;
|
|
24
24
|
};
|
|
25
|
-
declare type True = true;
|
|
25
|
+
export declare type True = true;
|
|
26
26
|
export declare const createCanvas: {
|
|
27
27
|
(size: number): [HTMLCanvasElement, CanvasRenderingContext2D];
|
|
28
28
|
(size: number, offscreen: True): [OffscreenCanvas, OffscreenCanvasRenderingContext2D];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dgeoutils",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.24",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "node_modules/.bin/tsc",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"jest-html-reporter": "^3.4.2",
|
|
46
46
|
"jsdom": "^17.0.0",
|
|
47
47
|
"ts-jest": "^27.0.4",
|
|
48
|
-
"typedoc": "^0.
|
|
48
|
+
"typedoc": "^0.22.11",
|
|
49
49
|
"typescript": "^4.4.3"
|
|
50
50
|
},
|
|
51
51
|
"jest": {
|