@immugio/three-math-extensions 0.2.29 → 0.2.30
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/CHANGELOG.md +7 -1
- package/cjs/Line2D.js +3 -13
- package/cjs/Polygon.js +29 -6
- package/cjs/offsetPolyline.js +10 -3
- package/esm/Line2D.js +3 -13
- package/esm/Polygon.js +29 -6
- package/esm/offsetPolyline.js +10 -3
- package/package.json +1 -1
- package/src/Line2D.ts +3 -14
- package/src/Polygon.ts +37 -6
- package/src/offsetPolyline.ts +13 -3
- package/types/Line2D.d.ts +1 -9
package/CHANGELOG.md
CHANGED
|
@@ -7,7 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
9
9
|
|
|
10
|
-
## [0.2.
|
|
10
|
+
## [0.2.30](https://github.com/Immugio/three-math-extensions/compare/0.2.29...0.2.30)
|
|
11
|
+
|
|
12
|
+
### Commits
|
|
13
|
+
|
|
14
|
+
- Improve offset algorithm implementation [`79bac64`](https://github.com/Immugio/three-math-extensions/commit/79bac64c799de39d022fcf4496dab3fcef497b60)
|
|
15
|
+
|
|
16
|
+
## [0.2.29](https://github.com/Immugio/three-math-extensions/compare/0.2.28...0.2.29) - 2024-09-12
|
|
11
17
|
|
|
12
18
|
### Commits
|
|
13
19
|
|
package/cjs/Line2D.js
CHANGED
|
@@ -27,28 +27,18 @@ class Line2D {
|
|
|
27
27
|
/**
|
|
28
28
|
* Creates a polygon formed by an array of lines from points provided.
|
|
29
29
|
* The polygon will only be closed if either
|
|
30
|
-
* 1) the first and last points are the same or 2)
|
|
31
|
-
* Similar to Line2.fromVectors but creates new instances of Vec2.
|
|
30
|
+
* 1) the first and last points are the same or 2) `forceClosedPolygon` is true.
|
|
32
31
|
*/
|
|
33
32
|
static fromPolygon(polygon, forceClosedPolygon = false) {
|
|
34
|
-
return Line2D.fromVectors(polygon?.map(p => Vec2_1.Vec2.fromPoint(p)), forceClosedPolygon);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Creates a polygon formed by an array of lines from points provided.
|
|
38
|
-
* The polygon will only be closed if either
|
|
39
|
-
* 1) the first and last points are the same or 2) `@forceClosedPolygon` is true.
|
|
40
|
-
* Similar to Line2.fromPolygon but keeps the original instances of Vec2.
|
|
41
|
-
*/
|
|
42
|
-
static fromVectors(polygon, forceClosedPolygon = false) {
|
|
43
33
|
if (!polygon || polygon.length < 2) {
|
|
44
34
|
return [];
|
|
45
35
|
}
|
|
46
|
-
if (forceClosedPolygon &&
|
|
36
|
+
if (forceClosedPolygon && (polygon[0].x !== polygon.at(-1).x || polygon[0].y !== polygon.at(-1).y)) {
|
|
47
37
|
polygon = [...polygon, polygon[0]];
|
|
48
38
|
}
|
|
49
39
|
const lines = [];
|
|
50
40
|
for (let i = 0; i < polygon.length - 1; i++) {
|
|
51
|
-
lines.push(
|
|
41
|
+
lines.push(Line2D.fromPoints(polygon[i], polygon[i + 1], i));
|
|
52
42
|
}
|
|
53
43
|
return lines;
|
|
54
44
|
}
|
package/cjs/Polygon.js
CHANGED
|
@@ -7,8 +7,6 @@ const BoundingBox_1 = require("./BoundingBox");
|
|
|
7
7
|
const polygonPerimeter_1 = require("./polygonPerimeter");
|
|
8
8
|
const isPointInPolygon_1 = require("./isPointInPolygon");
|
|
9
9
|
const Line2D_1 = require("./Line2D");
|
|
10
|
-
const offsetPolyline_1 = require("./offsetPolyline");
|
|
11
|
-
const extendOrTrimPolylinesAtIntersections_1 = require("./extendOrTrimPolylinesAtIntersections");
|
|
12
10
|
class Polygon {
|
|
13
11
|
contour;
|
|
14
12
|
holes;
|
|
@@ -124,13 +122,38 @@ class Polygon {
|
|
|
124
122
|
return this;
|
|
125
123
|
}
|
|
126
124
|
offsetContour(offset) {
|
|
127
|
-
|
|
125
|
+
if (!this.contour[0].equals(this.contour.at(-1))) {
|
|
126
|
+
console.error("The contour should be closed");
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
for (let i = 0; i < this.contour.length - 1; i++) {
|
|
130
|
+
this.translateContourLine(i, offset);
|
|
131
|
+
}
|
|
128
132
|
return this;
|
|
129
133
|
}
|
|
130
134
|
translateContourLine(index, offset) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
if (index < 0 || index > this.contour.length - 2) {
|
|
136
|
+
console.error(`Index out of bounds: ${index}`);
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
if (!this.contour[0].equals(this.contour.at(-1))) {
|
|
140
|
+
console.error("The contour should be closed");
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
const line = Line2D_1.Line2D.fromPoints(this.contour[index], this.contour[index + 1]);
|
|
144
|
+
const prev = Line2D_1.Line2D.fromPoints(this.contour[(index - 1 + this.contour.length) % this.contour.length], this.contour[index]);
|
|
145
|
+
const next = Line2D_1.Line2D.fromPoints(this.contour[index + 1], this.contour[(index + 2) % this.contour.length]);
|
|
146
|
+
line.translateLeft(offset);
|
|
147
|
+
line.extendToOrTrimAtIntersection(prev);
|
|
148
|
+
line.extendToOrTrimAtIntersection(next);
|
|
149
|
+
this.contour[index].copy(line.start);
|
|
150
|
+
this.contour[index + 1].copy(line.end);
|
|
151
|
+
if (index === 0) {
|
|
152
|
+
this.contour.at(-1).copy(line.start);
|
|
153
|
+
}
|
|
154
|
+
if (index === this.contour.length - 2) {
|
|
155
|
+
this.contour[0].copy(line.end);
|
|
156
|
+
}
|
|
134
157
|
return this;
|
|
135
158
|
}
|
|
136
159
|
rotate(angle, center = this.center()) {
|
package/cjs/offsetPolyline.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.offsetPolyline = void 0;
|
|
4
|
-
const extendOrTrimPolylinesAtIntersections_1 = require("./extendOrTrimPolylinesAtIntersections");
|
|
5
4
|
function offsetPolyline(lines, offset) {
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
for (let i = 0; i < lines.length; i++) {
|
|
6
|
+
const line = lines[i];
|
|
7
|
+
line.translateLeft(offset);
|
|
8
|
+
const next = lines[(i + 1) % lines.length];
|
|
9
|
+
line.extendToOrTrimAtIntersection(next);
|
|
10
|
+
next.extendToOrTrimAtIntersection(line);
|
|
11
|
+
const previous = lines[(i + lines.length - 1) % lines.length];
|
|
12
|
+
line.extendToOrTrimAtIntersection(previous);
|
|
13
|
+
previous.extendToOrTrimAtIntersection(line);
|
|
14
|
+
}
|
|
8
15
|
return lines;
|
|
9
16
|
}
|
|
10
17
|
exports.offsetPolyline = offsetPolyline;
|
package/esm/Line2D.js
CHANGED
|
@@ -24,28 +24,18 @@ export class Line2D {
|
|
|
24
24
|
/**
|
|
25
25
|
* Creates a polygon formed by an array of lines from points provided.
|
|
26
26
|
* The polygon will only be closed if either
|
|
27
|
-
* 1) the first and last points are the same or 2)
|
|
28
|
-
* Similar to Line2.fromVectors but creates new instances of Vec2.
|
|
27
|
+
* 1) the first and last points are the same or 2) `forceClosedPolygon` is true.
|
|
29
28
|
*/
|
|
30
29
|
static fromPolygon(polygon, forceClosedPolygon = false) {
|
|
31
|
-
return Line2D.fromVectors(polygon?.map(p => Vec2.fromPoint(p)), forceClosedPolygon);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Creates a polygon formed by an array of lines from points provided.
|
|
35
|
-
* The polygon will only be closed if either
|
|
36
|
-
* 1) the first and last points are the same or 2) `@forceClosedPolygon` is true.
|
|
37
|
-
* Similar to Line2.fromPolygon but keeps the original instances of Vec2.
|
|
38
|
-
*/
|
|
39
|
-
static fromVectors(polygon, forceClosedPolygon = false) {
|
|
40
30
|
if (!polygon || polygon.length < 2) {
|
|
41
31
|
return [];
|
|
42
32
|
}
|
|
43
|
-
if (forceClosedPolygon &&
|
|
33
|
+
if (forceClosedPolygon && (polygon[0].x !== polygon.at(-1).x || polygon[0].y !== polygon.at(-1).y)) {
|
|
44
34
|
polygon = [...polygon, polygon[0]];
|
|
45
35
|
}
|
|
46
36
|
const lines = [];
|
|
47
37
|
for (let i = 0; i < polygon.length - 1; i++) {
|
|
48
|
-
lines.push(
|
|
38
|
+
lines.push(Line2D.fromPoints(polygon[i], polygon[i + 1], i));
|
|
49
39
|
}
|
|
50
40
|
return lines;
|
|
51
41
|
}
|
package/esm/Polygon.js
CHANGED
|
@@ -4,8 +4,6 @@ import { BoundingBox } from "./BoundingBox";
|
|
|
4
4
|
import { polygonPerimeter } from "./polygonPerimeter";
|
|
5
5
|
import { isPointInPolygon } from "./isPointInPolygon";
|
|
6
6
|
import { Line2D } from "./Line2D";
|
|
7
|
-
import { offsetPolyline } from "./offsetPolyline";
|
|
8
|
-
import { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
|
|
9
7
|
export class Polygon {
|
|
10
8
|
contour;
|
|
11
9
|
holes;
|
|
@@ -121,13 +119,38 @@ export class Polygon {
|
|
|
121
119
|
return this;
|
|
122
120
|
}
|
|
123
121
|
offsetContour(offset) {
|
|
124
|
-
|
|
122
|
+
if (!this.contour[0].equals(this.contour.at(-1))) {
|
|
123
|
+
console.error("The contour should be closed");
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
for (let i = 0; i < this.contour.length - 1; i++) {
|
|
127
|
+
this.translateContourLine(i, offset);
|
|
128
|
+
}
|
|
125
129
|
return this;
|
|
126
130
|
}
|
|
127
131
|
translateContourLine(index, offset) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
if (index < 0 || index > this.contour.length - 2) {
|
|
133
|
+
console.error(`Index out of bounds: ${index}`);
|
|
134
|
+
return this;
|
|
135
|
+
}
|
|
136
|
+
if (!this.contour[0].equals(this.contour.at(-1))) {
|
|
137
|
+
console.error("The contour should be closed");
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
const line = Line2D.fromPoints(this.contour[index], this.contour[index + 1]);
|
|
141
|
+
const prev = Line2D.fromPoints(this.contour[(index - 1 + this.contour.length) % this.contour.length], this.contour[index]);
|
|
142
|
+
const next = Line2D.fromPoints(this.contour[index + 1], this.contour[(index + 2) % this.contour.length]);
|
|
143
|
+
line.translateLeft(offset);
|
|
144
|
+
line.extendToOrTrimAtIntersection(prev);
|
|
145
|
+
line.extendToOrTrimAtIntersection(next);
|
|
146
|
+
this.contour[index].copy(line.start);
|
|
147
|
+
this.contour[index + 1].copy(line.end);
|
|
148
|
+
if (index === 0) {
|
|
149
|
+
this.contour.at(-1).copy(line.start);
|
|
150
|
+
}
|
|
151
|
+
if (index === this.contour.length - 2) {
|
|
152
|
+
this.contour[0].copy(line.end);
|
|
153
|
+
}
|
|
131
154
|
return this;
|
|
132
155
|
}
|
|
133
156
|
rotate(angle, center = this.center()) {
|
package/esm/offsetPolyline.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
|
|
2
1
|
export function offsetPolyline(lines, offset) {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3
|
+
const line = lines[i];
|
|
4
|
+
line.translateLeft(offset);
|
|
5
|
+
const next = lines[(i + 1) % lines.length];
|
|
6
|
+
line.extendToOrTrimAtIntersection(next);
|
|
7
|
+
next.extendToOrTrimAtIntersection(line);
|
|
8
|
+
const previous = lines[(i + lines.length - 1) % lines.length];
|
|
9
|
+
line.extendToOrTrimAtIntersection(previous);
|
|
10
|
+
previous.extendToOrTrimAtIntersection(line);
|
|
11
|
+
}
|
|
5
12
|
return lines;
|
|
6
13
|
}
|
package/package.json
CHANGED
package/src/Line2D.ts
CHANGED
|
@@ -26,31 +26,20 @@ export class Line2D {
|
|
|
26
26
|
/**
|
|
27
27
|
* Creates a polygon formed by an array of lines from points provided.
|
|
28
28
|
* The polygon will only be closed if either
|
|
29
|
-
* 1) the first and last points are the same or 2)
|
|
30
|
-
* Similar to Line2.fromVectors but creates new instances of Vec2.
|
|
29
|
+
* 1) the first and last points are the same or 2) `forceClosedPolygon` is true.
|
|
31
30
|
*/
|
|
32
31
|
public static fromPolygon(polygon: Point2[], forceClosedPolygon: boolean = false): Line2D[] {
|
|
33
|
-
return Line2D.fromVectors(polygon?.map(p => Vec2.fromPoint(p)), forceClosedPolygon);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Creates a polygon formed by an array of lines from points provided.
|
|
38
|
-
* The polygon will only be closed if either
|
|
39
|
-
* 1) the first and last points are the same or 2) `@forceClosedPolygon` is true.
|
|
40
|
-
* Similar to Line2.fromPolygon but keeps the original instances of Vec2.
|
|
41
|
-
*/
|
|
42
|
-
public static fromVectors(polygon: Vec2[], forceClosedPolygon: boolean = false): Line2D[] {
|
|
43
32
|
if (!polygon || polygon.length < 2) {
|
|
44
33
|
return [];
|
|
45
34
|
}
|
|
46
35
|
|
|
47
|
-
if (forceClosedPolygon &&
|
|
36
|
+
if (forceClosedPolygon && (polygon[0].x !== polygon.at(-1).x || polygon[0].y !== polygon.at(-1).y)) {
|
|
48
37
|
polygon = [...polygon, polygon[0]];
|
|
49
38
|
}
|
|
50
39
|
|
|
51
40
|
const lines: Line2D[] = [];
|
|
52
41
|
for (let i = 0; i < polygon.length - 1; i++) {
|
|
53
|
-
lines.push(
|
|
42
|
+
lines.push(Line2D.fromPoints(polygon[i], polygon[i + 1], i));
|
|
54
43
|
}
|
|
55
44
|
|
|
56
45
|
return lines;
|
package/src/Polygon.ts
CHANGED
|
@@ -5,8 +5,6 @@ import { BoundingBox } from "./BoundingBox";
|
|
|
5
5
|
import { polygonPerimeter } from "./polygonPerimeter";
|
|
6
6
|
import { isPointInPolygon } from "./isPointInPolygon";
|
|
7
7
|
import { Line2D } from "./Line2D";
|
|
8
|
-
import { offsetPolyline } from "./offsetPolyline";
|
|
9
|
-
import { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
|
|
10
8
|
|
|
11
9
|
export class Polygon {
|
|
12
10
|
|
|
@@ -144,14 +142,47 @@ export class Polygon {
|
|
|
144
142
|
}
|
|
145
143
|
|
|
146
144
|
public offsetContour(offset: number): this {
|
|
147
|
-
|
|
145
|
+
if (!this.contour[0].equals(this.contour.at(-1))) {
|
|
146
|
+
console.error("The contour should be closed");
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
for (let i = 0; i < this.contour.length - 1; i++) {
|
|
151
|
+
this.translateContourLine(i, offset);
|
|
152
|
+
}
|
|
148
153
|
return this;
|
|
149
154
|
}
|
|
150
155
|
|
|
151
156
|
public translateContourLine(index: number, offset: number): this {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
if (index < 0 || index > this.contour.length - 2) {
|
|
158
|
+
console.error(`Index out of bounds: ${index}`);
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (!this.contour[0].equals(this.contour.at(-1))) {
|
|
163
|
+
console.error("The contour should be closed");
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const line = Line2D.fromPoints(this.contour[index], this.contour[index + 1]);
|
|
168
|
+
const prev = Line2D.fromPoints(this.contour[(index - 1 + this.contour.length) % this.contour.length], this.contour[index]);
|
|
169
|
+
const next = Line2D.fromPoints(this.contour[index + 1], this.contour[(index + 2) % this.contour.length]);
|
|
170
|
+
|
|
171
|
+
line.translateLeft(offset);
|
|
172
|
+
line.extendToOrTrimAtIntersection(prev);
|
|
173
|
+
line.extendToOrTrimAtIntersection(next);
|
|
174
|
+
|
|
175
|
+
this.contour[index].copy(line.start);
|
|
176
|
+
this.contour[index + 1].copy(line.end);
|
|
177
|
+
|
|
178
|
+
if (index === 0) {
|
|
179
|
+
this.contour.at(-1).copy(line.start);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (index === this.contour.length - 2) {
|
|
183
|
+
this.contour[0].copy(line.end);
|
|
184
|
+
}
|
|
185
|
+
|
|
155
186
|
return this;
|
|
156
187
|
}
|
|
157
188
|
|
package/src/offsetPolyline.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { Line2D } from "./Line2D";
|
|
2
|
-
import { extendOrTrimPolylinesAtIntersections } from "./extendOrTrimPolylinesAtIntersections";
|
|
3
2
|
|
|
4
3
|
export function offsetPolyline(lines: Line2D[], offset: number): Line2D[] {
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
for (let i = 0; i < lines.length; i++){
|
|
5
|
+
const line = lines[i];
|
|
6
|
+
line.translateLeft(offset);
|
|
7
|
+
|
|
8
|
+
const next = lines[(i + 1) % lines.length];
|
|
9
|
+
line.extendToOrTrimAtIntersection(next);
|
|
10
|
+
next.extendToOrTrimAtIntersection(line);
|
|
11
|
+
|
|
12
|
+
const previous = lines[(i + lines.length - 1) % lines.length];
|
|
13
|
+
line.extendToOrTrimAtIntersection(previous);
|
|
14
|
+
previous.extendToOrTrimAtIntersection(line);
|
|
15
|
+
}
|
|
16
|
+
|
|
7
17
|
return lines;
|
|
8
18
|
}
|
package/types/Line2D.d.ts
CHANGED
|
@@ -13,17 +13,9 @@ export declare class Line2D {
|
|
|
13
13
|
/**
|
|
14
14
|
* Creates a polygon formed by an array of lines from points provided.
|
|
15
15
|
* The polygon will only be closed if either
|
|
16
|
-
* 1) the first and last points are the same or 2)
|
|
17
|
-
* Similar to Line2.fromVectors but creates new instances of Vec2.
|
|
16
|
+
* 1) the first and last points are the same or 2) `forceClosedPolygon` is true.
|
|
18
17
|
*/
|
|
19
18
|
static fromPolygon(polygon: Point2[], forceClosedPolygon?: boolean): Line2D[];
|
|
20
|
-
/**
|
|
21
|
-
* Creates a polygon formed by an array of lines from points provided.
|
|
22
|
-
* The polygon will only be closed if either
|
|
23
|
-
* 1) the first and last points are the same or 2) `@forceClosedPolygon` is true.
|
|
24
|
-
* Similar to Line2.fromPolygon but keeps the original instances of Vec2.
|
|
25
|
-
*/
|
|
26
|
-
static fromVectors(polygon: Vec2[], forceClosedPolygon?: boolean): Line2D[];
|
|
27
19
|
static fromLength(length: number): Line2D;
|
|
28
20
|
get center(): Vec2;
|
|
29
21
|
/**
|