@escapace/minimum-perimeter-triangle 0.2.4 → 0.2.6
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/LICENSE +2 -1
- package/lib/neutral/index.js +557 -0
- package/lib/neutral/index.js.map +1 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/inscribe.d.ts +11 -10
- package/lib/types/inscribe.d.ts.map +1 -1
- package/lib/types/line.d.ts +17 -17
- package/lib/types/line.d.ts.map +1 -1
- package/lib/types/vec2.d.ts +13 -13
- package/lib/types/vec2.d.ts.map +1 -1
- package/package.json +39 -42
- package/lib/esm/index.mjs +0 -399
- package/lib/esm/index.mjs.map +0 -7
package/lib/types/inscribe.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Line } from './line';
|
|
2
2
|
import { Vec2 } from './vec2';
|
|
3
|
-
|
|
3
|
+
interface Circle {
|
|
4
4
|
centre: Vec2;
|
|
5
5
|
r: number;
|
|
6
6
|
}
|
|
@@ -10,26 +10,27 @@ export interface Circle {
|
|
|
10
10
|
* in this case they must point in the same direction
|
|
11
11
|
*/
|
|
12
12
|
export declare class Wedge {
|
|
13
|
+
readonly isDegenerate: boolean;
|
|
13
14
|
readonly leftArm: Line;
|
|
14
15
|
readonly rightArm: Line;
|
|
15
|
-
readonly isDegenerate: boolean;
|
|
16
16
|
private constructor();
|
|
17
|
-
static new(leftArm: Line, rightArm: Line,
|
|
18
|
-
formTriangle(line: Line, err: number): boolean;
|
|
19
|
-
looselyContains(p: Vec2, err: number): boolean;
|
|
20
|
-
strictlyContains(p: Vec2, err: number): boolean;
|
|
21
|
-
private fit_Dp;
|
|
17
|
+
static new(leftArm: Line, rightArm: Line, error: number): Wedge | null;
|
|
22
18
|
private fit_Dl;
|
|
23
|
-
private
|
|
19
|
+
private fit_Dp;
|
|
24
20
|
private fit_NDl;
|
|
25
|
-
|
|
21
|
+
private fit_NDp;
|
|
22
|
+
fitCircles(element: Vec2, error: number): Array<{
|
|
26
23
|
circle: Circle;
|
|
27
24
|
tangent: Line;
|
|
28
25
|
}> | null;
|
|
29
|
-
fitCircles(element: Line
|
|
26
|
+
fitCircles(element: Line, error: number): Array<{
|
|
30
27
|
circle: Circle;
|
|
31
28
|
tangentParameter: number;
|
|
32
29
|
}> | null;
|
|
30
|
+
formTriangle(line: Line, error: number): boolean;
|
|
31
|
+
looselyContains(p: Vec2, error: number): boolean;
|
|
32
|
+
strictlyContains(p: Vec2, error: number): boolean;
|
|
33
33
|
toString(): string;
|
|
34
34
|
}
|
|
35
|
+
export {};
|
|
35
36
|
//# sourceMappingURL=inscribe.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inscribe.d.ts","sourceRoot":"","sources":["../../src/inscribe.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"inscribe.d.ts","sourceRoot":"","sources":["../../src/inscribe.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAQ,MAAM,QAAQ,CAAA;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,UAAU,MAAM;IACd,MAAM,EAAE,IAAI,CAAA;IACZ,CAAC,EAAE,MAAM,CAAA;CACV;AAED;;;;GAIG;AACH,qBAAa,KAAK;IAChB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;IAEvB,OAAO;IAMP,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI;IA4DtE,OAAO,CAAC,MAAM;IAkDd,OAAO,CAAC,MAAM;IA6Dd,OAAO,CAAC,OAAO;IAgHf,OAAO,CAAC,OAAO;IAqEf,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,IAAI,CAAA;KAAE,CAAC,GAAG,IAAI;IAEzF,UAAU,CACR,OAAO,EAAE,IAAI,EACb,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAc7D,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAwBhD,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAqBhD,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAsBjD,QAAQ,IAAI,MAAM;CAMnB"}
|
package/lib/types/line.d.ts
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
import { Vec2 } from './vec2';
|
|
1
|
+
import type { Vec2 } from './vec2';
|
|
2
2
|
export declare enum Side {
|
|
3
|
+
Left = 1,
|
|
3
4
|
Right = -1,
|
|
4
|
-
Top = 0
|
|
5
|
-
Left = 1
|
|
5
|
+
Top = 0
|
|
6
6
|
}
|
|
7
7
|
export declare class Line {
|
|
8
|
-
readonly start: Vec2;
|
|
9
|
-
readonly end: Vec2;
|
|
10
8
|
readonly delta: Vec2;
|
|
9
|
+
readonly end: Vec2;
|
|
10
|
+
readonly start: Vec2;
|
|
11
11
|
constructor(start: Vec2, end: Vec2);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
get length(): number;
|
|
16
|
-
evaluate(t: number): Vec2;
|
|
12
|
+
closestPoint(p: Vec2): Vec2;
|
|
13
|
+
closestPointParam(p: Vec2): number;
|
|
17
14
|
distanceToPoint(p: Vec2): number;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
evaluate(t: number): Vec2;
|
|
16
|
+
intersectionParameter(that: Line, error: number): number | null;
|
|
17
|
+
intersectionPoint(that: Line, error: number): Vec2 | null;
|
|
18
|
+
overlaps(that: Line, error: number): boolean;
|
|
21
19
|
/**
|
|
22
20
|
* If alpha is less than deviationFromZeroAngle, the 2 lines are
|
|
23
21
|
* considered parallel.
|
|
@@ -28,9 +26,11 @@ export declare class Line {
|
|
|
28
26
|
* /
|
|
29
27
|
*/
|
|
30
28
|
parallel(that: Line, deviationFromZeroAngle: number): boolean;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
pointOnSide(p: Vec2, error?: number): number;
|
|
30
|
+
pointOnTop(p: Vec2, error: number): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Length of a line is the length between its two defining points
|
|
33
|
+
*/
|
|
34
|
+
get length(): number;
|
|
35
35
|
}
|
|
36
36
|
//# sourceMappingURL=line.d.ts.map
|
package/lib/types/line.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../src/line.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../src/line.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAElC,oBAAY,IAAI;IACd,IAAI,IAAI;IACR,KAAK,KAAK;IACV,GAAG,IAAI;CACR;AAED,qBAAa,IAAI;IACf,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAA;IAClB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAA;gBAER,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI;IAMlC,YAAY,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI;IAI3B,iBAAiB,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM;IAIlC,eAAe,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM;IAIhC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAIzB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAS/D,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKzD,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAI5C;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,GAAG,OAAO;IAM7D,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,SAAI,GAAG,MAAM;IAQvC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAI3C;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF"}
|
package/lib/types/vec2.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
export declare class Vec2 {
|
|
2
|
-
private readonly _x;
|
|
3
|
-
private readonly _y;
|
|
4
|
-
private _normSquared;
|
|
5
2
|
private _norm;
|
|
6
3
|
private _normalized;
|
|
4
|
+
private _normSquared;
|
|
5
|
+
private readonly _x;
|
|
6
|
+
private readonly _y;
|
|
7
7
|
constructor(x: number, y: number);
|
|
8
|
-
|
|
8
|
+
cross(that: Vec2): number;
|
|
9
|
+
dot(that: Vec2): number;
|
|
10
|
+
equals(that: Vec2, error: number): boolean;
|
|
11
|
+
minus(that: Vec2): Vec2;
|
|
12
|
+
normal(): Vec2;
|
|
9
13
|
over(s: number): Vec2;
|
|
10
|
-
get x(): number;
|
|
11
|
-
get y(): number;
|
|
12
14
|
plus(that: Vec2): Vec2;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
times(s: number): Vec2;
|
|
16
|
+
toString(): string;
|
|
15
17
|
get norm(): number;
|
|
16
18
|
get normalized(): Vec2;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
normal(): Vec2;
|
|
21
|
-
toString(): string;
|
|
19
|
+
get normSquared(): number;
|
|
20
|
+
get x(): number;
|
|
21
|
+
get y(): number;
|
|
22
22
|
}
|
|
23
23
|
//# sourceMappingURL=vec2.d.ts.map
|
package/lib/types/vec2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vec2.d.ts","sourceRoot":"","sources":["../../src/vec2.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vec2.d.ts","sourceRoot":"","sources":["../../src/vec2.ts"],"names":[],"mappings":"AACA,qBAAa,IAAI;IACf,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,WAAW,CAAkB;IAErC,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAQ;gBAEf,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM;IAKhC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAIzB,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAIvB,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAO1C,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIvB,MAAM,IAAI,IAAI;IAId,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAIrB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAItB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IAItB,QAAQ,IAAI,MAAM;IAIlB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,UAAU,IAAI,IAAI,CAIrB;IAED,IAAI,WAAW,IAAI,MAAM,CAIxB;IAED,IAAI,CAAC,IAAI,MAAM,CAEd;IAED,IAAI,CAAC,IAAI,MAAM,CAEd;CACF"}
|
package/package.json
CHANGED
|
@@ -1,66 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@escapace/minimum-perimeter-triangle",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "0.2.
|
|
5
|
-
"author":
|
|
4
|
+
"version": "0.2.6",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "escapace",
|
|
7
|
+
"email": "opensource@escapace.com"
|
|
8
|
+
},
|
|
6
9
|
"bugs": "https://github.com/escapace/minimum-perimeter-triangle/issues",
|
|
7
10
|
"devDependencies": {
|
|
8
|
-
"@commitlint/cli": "
|
|
9
|
-
"@commitlint/config-conventional": "
|
|
10
|
-
"@
|
|
11
|
-
"@
|
|
12
|
-
"@
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"execa": "7.1.1",
|
|
25
|
-
"fast-glob": "3.2.12",
|
|
26
|
-
"fs-extra": "11.1.1",
|
|
27
|
-
"husky": "8.0.3",
|
|
28
|
-
"is-ci": "3.0.1",
|
|
29
|
-
"lint-staged": "13.2.2",
|
|
30
|
-
"mocha": "10.2.0",
|
|
31
|
-
"prettier": "2.8.8",
|
|
32
|
-
"prettier-config-escapace": "1.0.5",
|
|
33
|
-
"semver": "7.5.1",
|
|
34
|
-
"syncpack": "10.1.0",
|
|
35
|
-
"ts-node": "10.9.1",
|
|
36
|
-
"typescript": "5.0.4"
|
|
11
|
+
"@commitlint/cli": "19.6.0",
|
|
12
|
+
"@commitlint/config-conventional": "19.6.0",
|
|
13
|
+
"@escapace/pnpm-pack": "0.5.3",
|
|
14
|
+
"@ls-lint/ls-lint": "2.2.3",
|
|
15
|
+
"@vitest/coverage-v8": "2.1.8",
|
|
16
|
+
"eslint": "9.17.0",
|
|
17
|
+
"eslint-config-escapace": "5.4.0",
|
|
18
|
+
"esroll": "0.3.0",
|
|
19
|
+
"knip": "5.40.0",
|
|
20
|
+
"lefthook": "1.9.2",
|
|
21
|
+
"prettier": "3.4.2",
|
|
22
|
+
"prettier-config-escapace": "1.2.1",
|
|
23
|
+
"syncpack": "13.0.0",
|
|
24
|
+
"tsx": "4.19.2",
|
|
25
|
+
"typescript": "5.7.2",
|
|
26
|
+
"vitest": "2.1.8"
|
|
37
27
|
},
|
|
38
28
|
"engines": {
|
|
39
|
-
"
|
|
40
|
-
"pnpm": ">= 8.6.0"
|
|
29
|
+
"pnpm": ">=9.14.4"
|
|
41
30
|
},
|
|
42
31
|
"exports": {
|
|
43
32
|
".": {
|
|
44
|
-
"
|
|
45
|
-
"
|
|
33
|
+
"types": "./lib/types/index.d.ts",
|
|
34
|
+
"import": "./lib/neutral/index.js"
|
|
46
35
|
}
|
|
47
36
|
},
|
|
48
37
|
"files": [
|
|
49
|
-
"lib/
|
|
38
|
+
"lib/neutral",
|
|
50
39
|
"lib/types"
|
|
51
40
|
],
|
|
52
|
-
"homepage": "https://github.com/escapace/minimum-perimeter-triangle",
|
|
41
|
+
"homepage": "https://github.com/escapace/minimum-perimeter-triangle#readme",
|
|
53
42
|
"license": "MPL-2.0",
|
|
54
|
-
"module": "lib/
|
|
43
|
+
"module": "lib/neutral/index.js",
|
|
55
44
|
"private": false,
|
|
56
|
-
"
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"provenance": true
|
|
48
|
+
},
|
|
49
|
+
"repository": "escapace/minimum-perimeter-triangle",
|
|
57
50
|
"sideEffects": false,
|
|
58
51
|
"type": "module",
|
|
59
52
|
"types": "lib/types/index.d.ts",
|
|
60
53
|
"scripts": {
|
|
61
|
-
"build": "
|
|
62
|
-
"
|
|
63
|
-
"
|
|
54
|
+
"build": "tsx scripts/build.ts",
|
|
55
|
+
"format": "syncpack format && eslint --no-warn-ignored --fix && prettier -uw .",
|
|
56
|
+
"lint": "ls-lint --config .ls-lint.yaml && knip --no-config-hints && eslint",
|
|
57
|
+
"ls-lint": "ls-lint --config .ls-lint.yaml",
|
|
58
|
+
"pack": "pnpm-pack package --pack-destination lib",
|
|
59
|
+
"syncpack": "syncpack fix-mismatches && syncpack set-semver-ranges && syncpack format",
|
|
60
|
+
"test": "vitest --no-watch --coverage",
|
|
64
61
|
"typecheck": "tsc --noEmit"
|
|
65
62
|
}
|
|
66
63
|
}
|
package/lib/esm/index.mjs
DELETED
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
// src/line.ts
|
|
2
|
-
var Line = class {
|
|
3
|
-
start;
|
|
4
|
-
end;
|
|
5
|
-
delta;
|
|
6
|
-
constructor(start, end) {
|
|
7
|
-
this.start = start, this.end = end, this.delta = end.minus(start);
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Length of a line is the length between its two defining points
|
|
11
|
-
*/
|
|
12
|
-
get length() {
|
|
13
|
-
return this.delta.norm;
|
|
14
|
-
}
|
|
15
|
-
evaluate(t) {
|
|
16
|
-
return this.start.plus(this.delta.times(t));
|
|
17
|
-
}
|
|
18
|
-
distanceToPoint(p) {
|
|
19
|
-
return Math.abs(p.cross(this.delta) - this.start.cross(this.end)) / this.delta.norm;
|
|
20
|
-
}
|
|
21
|
-
pointOnSide(p, err = 0) {
|
|
22
|
-
let num = this.start.cross(this.end) - p.cross(this.delta);
|
|
23
|
-
return num === 0 || Math.abs(num) / this.delta.norm < err ? 0 /* Top */ : num > 0 ? 1 /* Left */ : -1 /* Right */;
|
|
24
|
-
}
|
|
25
|
-
pointOnTop(p, err) {
|
|
26
|
-
return this.pointOnSide(p, err) === 0 /* Top */;
|
|
27
|
-
}
|
|
28
|
-
overlaps(that, err) {
|
|
29
|
-
return this.pointOnTop(that.start, err) && this.pointOnTop(that.end, err);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* If alpha is less than deviationFromZeroAngle, the 2 lines are
|
|
33
|
-
* considered parallel.
|
|
34
|
-
* _______________________________
|
|
35
|
-
* alpha (/
|
|
36
|
-
* /
|
|
37
|
-
* /
|
|
38
|
-
* /
|
|
39
|
-
*/
|
|
40
|
-
parallel(that, deviationFromZeroAngle) {
|
|
41
|
-
let d = Math.abs(this.delta.cross(that.delta));
|
|
42
|
-
return d === 0 || d < this.length * this.length * Math.sin(deviationFromZeroAngle);
|
|
43
|
-
}
|
|
44
|
-
intersectionParameter(that, err) {
|
|
45
|
-
let d = this.delta.cross(that.delta);
|
|
46
|
-
if (d === 0 || Math.abs(d) < err)
|
|
47
|
-
return null;
|
|
48
|
-
let dStart = this.start.minus(that.start);
|
|
49
|
-
return that.delta.cross(dStart) / d;
|
|
50
|
-
}
|
|
51
|
-
closestPointParam(p) {
|
|
52
|
-
return this.delta.dot(p.minus(this.start)) / this.delta.normSquared;
|
|
53
|
-
}
|
|
54
|
-
closestPoint(p) {
|
|
55
|
-
return this.evaluate(this.closestPointParam(p));
|
|
56
|
-
}
|
|
57
|
-
intersectionPoint(that, err) {
|
|
58
|
-
let t = this.intersectionParameter(that, err);
|
|
59
|
-
return t === null ? null : this.evaluate(t);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// src/vec2.ts
|
|
64
|
-
var Vec2 = class {
|
|
65
|
-
_x;
|
|
66
|
-
_y;
|
|
67
|
-
_normSquared;
|
|
68
|
-
_norm;
|
|
69
|
-
_normalized;
|
|
70
|
-
constructor(x, y) {
|
|
71
|
-
this._x = x, this._y = y;
|
|
72
|
-
}
|
|
73
|
-
times(s) {
|
|
74
|
-
return new Vec2(this._x * s, this._y * s);
|
|
75
|
-
}
|
|
76
|
-
over(s) {
|
|
77
|
-
return new Vec2(this._x / s, this._y / s);
|
|
78
|
-
}
|
|
79
|
-
get x() {
|
|
80
|
-
return this._x;
|
|
81
|
-
}
|
|
82
|
-
get y() {
|
|
83
|
-
return this._y;
|
|
84
|
-
}
|
|
85
|
-
plus(that) {
|
|
86
|
-
return new Vec2(this._x + that._x, this._y + that._y);
|
|
87
|
-
}
|
|
88
|
-
minus(that) {
|
|
89
|
-
return new Vec2(this._x - that._x, this._y - that._y);
|
|
90
|
-
}
|
|
91
|
-
get normSquared() {
|
|
92
|
-
return this._normSquared === void 0 ? this._normSquared = this.dot(this) : this._normSquared;
|
|
93
|
-
}
|
|
94
|
-
get norm() {
|
|
95
|
-
return this._norm === void 0 ? this._norm = Math.sqrt(this.normSquared) : this._norm;
|
|
96
|
-
}
|
|
97
|
-
get normalized() {
|
|
98
|
-
return this._normalized === void 0 ? this._normalized = this.over(this.norm) : this._normalized;
|
|
99
|
-
}
|
|
100
|
-
dot(that) {
|
|
101
|
-
return this._x * that._x + this._y * that._y;
|
|
102
|
-
}
|
|
103
|
-
cross(that) {
|
|
104
|
-
return this._x * that._y - this._y * that._x;
|
|
105
|
-
}
|
|
106
|
-
equals(that, err) {
|
|
107
|
-
return err === 0 ? this.x === that.x && this.y === that.y : this.minus(that).normSquared < err * err;
|
|
108
|
-
}
|
|
109
|
-
normal() {
|
|
110
|
-
return new Vec2(this._y, -this._x);
|
|
111
|
-
}
|
|
112
|
-
toString() {
|
|
113
|
-
return `(${this.x}, ${this.y})`;
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
// src/inscribe.ts
|
|
118
|
-
var Wedge = class {
|
|
119
|
-
leftArm;
|
|
120
|
-
rightArm;
|
|
121
|
-
isDegenerate;
|
|
122
|
-
constructor(leftArm, rightArm, isDegenerate = !1) {
|
|
123
|
-
this.leftArm = leftArm, this.rightArm = rightArm, this.isDegenerate = isDegenerate;
|
|
124
|
-
}
|
|
125
|
-
static new(leftArm, rightArm, err) {
|
|
126
|
-
if (leftArm === null || rightArm === null || err !== 0 && leftArm.overlaps(rightArm, err))
|
|
127
|
-
return null;
|
|
128
|
-
let deviationFromZeroAngle = 0.1 / (leftArm.length * rightArm.length);
|
|
129
|
-
if (leftArm.parallel(rightArm, deviationFromZeroAngle)) {
|
|
130
|
-
let p = new Line(leftArm.evaluate(0.5), rightArm.evaluate(0.5)).evaluate(0.5), sideLeft = leftArm.pointOnSide(p, err), sideRight = rightArm.pointOnSide(p, err);
|
|
131
|
-
if (sideLeft === 0 /* Top */ || sideRight === 0 /* Top */)
|
|
132
|
-
throw new Error();
|
|
133
|
-
return sideLeft !== sideRight ? new Wedge(leftArm, rightArm, !0) : new Wedge(leftArm, new Line(rightArm.end, rightArm.start));
|
|
134
|
-
}
|
|
135
|
-
let tLA = leftArm.intersectionParameter(rightArm, 0), tRA = rightArm.intersectionParameter(leftArm, 0);
|
|
136
|
-
if (tLA === 0.5 || tRA === 0.5)
|
|
137
|
-
return null;
|
|
138
|
-
let W = leftArm.evaluate(tLA), eLA = tLA < 1 - tLA ? leftArm.end : leftArm.start, eRA = tRA < 1 - tRA ? rightArm.end : rightArm.start;
|
|
139
|
-
return new Wedge(new Line(W, eLA), new Line(W, eRA));
|
|
140
|
-
}
|
|
141
|
-
formTriangle(line, err) {
|
|
142
|
-
if (this.leftArm.parallel(line, 0.1 / (this.leftArm.length * line.length)) || this.rightArm.parallel(line, 0.1 / (this.rightArm.length * line.length)))
|
|
143
|
-
return !1;
|
|
144
|
-
let A = line.intersectionPoint(this.leftArm, 0), B = line.intersectionPoint(this.rightArm, 0);
|
|
145
|
-
if (this.isDegenerate)
|
|
146
|
-
return !A.equals(B, err);
|
|
147
|
-
let C = this.leftArm.intersectionPoint(this.rightArm, 0);
|
|
148
|
-
return !C.equals(A, err) && !C.equals(B, err) && !A.equals(B, err) && !new Line(A, B).pointOnTop(C, err);
|
|
149
|
-
}
|
|
150
|
-
looselyContains(p, err) {
|
|
151
|
-
let pLeft = this.leftArm.pointOnSide(p, err), pRight = this.rightArm.pointOnSide(p, err);
|
|
152
|
-
return pLeft === 0 /* Top */ || pRight === 0 /* Top */ ? !0 : pLeft === pRight ? !1 : this.isDegenerate ? (
|
|
153
|
-
// degenerate + different sides => true
|
|
154
|
-
!0
|
|
155
|
-
) : (
|
|
156
|
-
// 2. (Because the arms intersect)
|
|
157
|
-
// Projection params of the point onto the arms must be larger than 0
|
|
158
|
-
this.leftArm.closestPointParam(p) >= 0 && this.rightArm.closestPointParam(p) >= 0
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
strictlyContains(p, err) {
|
|
162
|
-
let pLeft = this.leftArm.pointOnSide(p, err), pRight = this.rightArm.pointOnSide(p, err);
|
|
163
|
-
return pLeft === 0 /* Top */ || pRight === 0 /* Top */ || pLeft === pRight ? !1 : this.isDegenerate ? (
|
|
164
|
-
// degenerate + different sides => true
|
|
165
|
-
!0
|
|
166
|
-
) : (
|
|
167
|
-
// 2. (Because the arms intersect)
|
|
168
|
-
// Projection params of the point onto the arms must be larger than 0
|
|
169
|
-
this.leftArm.closestPointParam(p) >= 0 && this.rightArm.closestPointParam(p) >= 0
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
// While fitting circles into a wedge
|
|
173
|
-
// There are four distinct cases:
|
|
174
|
-
// 1. Wedge is degenerate and additional element is a point
|
|
175
|
-
// 2. Wedge is degenerate and additional element is a line
|
|
176
|
-
// 3. Wedge is non-degenerate and additional element is a point
|
|
177
|
-
// 4. Wedge is non-degenerate and additional element is a line
|
|
178
|
-
// according to these assumptions, the following methods are named
|
|
179
|
-
fit_Dp(p, err) {
|
|
180
|
-
if (!this.strictlyContains(p, err))
|
|
181
|
-
return null;
|
|
182
|
-
let A = this.rightArm.closestPoint(p), Ap = this.leftArm.closestPoint(A), I = A.plus(Ap).over(2), r = A.minus(Ap).norm / 2, a = this.rightArm.delta.normSquared, b = I.minus(p).dot(this.rightArm.delta) * 2, c = I.minus(p).normSquared - r * r, discriminant = b * b - 4 * a * c;
|
|
183
|
-
if (discriminant < (-10) ** -5)
|
|
184
|
-
return null;
|
|
185
|
-
let t = [];
|
|
186
|
-
Math.abs(discriminant) < 10 ** -5 ? t.push(-b / (2 * a)) : (t.push((-b + Math.sqrt(discriminant)) / (2 * a)), t.push((-b - Math.sqrt(discriminant)) / (2 * a)));
|
|
187
|
-
let result = [];
|
|
188
|
-
return t.forEach((t0) => {
|
|
189
|
-
let O = this.rightArm.delta.times(t0).plus(I);
|
|
190
|
-
result.push({
|
|
191
|
-
circle: { centre: O, r },
|
|
192
|
-
tangent: new Line(p, p.plus(O.minus(p).normal()))
|
|
193
|
-
});
|
|
194
|
-
}), result;
|
|
195
|
-
}
|
|
196
|
-
fit_Dl(l, err) {
|
|
197
|
-
if (!this.formTriangle(l, err))
|
|
198
|
-
return null;
|
|
199
|
-
let A = l.intersectionPoint(this.rightArm, 0), B = l.intersectionPoint(this.leftArm, 0), AB = new Line(A, B), Ap = this.leftArm.closestPoint(A), I = A.plus(Ap).over(2), r = A.minus(Ap).norm / 2, t1 = (AB.delta.cross(A.minus(I)) + r * AB.delta.norm) / AB.delta.cross(this.rightArm.delta), t2 = (AB.delta.cross(A.minus(I)) - r * AB.delta.norm) / AB.delta.cross(this.rightArm.delta), o1 = this.rightArm.delta.times(t1).plus(I), o2 = this.rightArm.delta.times(t2).plus(I);
|
|
200
|
-
return [
|
|
201
|
-
{
|
|
202
|
-
circle: { centre: o1, r },
|
|
203
|
-
tangentParameter: l.closestPointParam(o1)
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
circle: { centre: o2, r },
|
|
207
|
-
tangentParameter: l.closestPointParam(o2)
|
|
208
|
-
}
|
|
209
|
-
];
|
|
210
|
-
}
|
|
211
|
-
fit_NDp(p, err) {
|
|
212
|
-
if (!this.strictlyContains(p, err))
|
|
213
|
-
return null;
|
|
214
|
-
let C = this.leftArm.start, A = this.leftArm.end, B = this.rightArm.end, a = C.minus(B).norm, b = C.minus(A).norm, D = A.minus(B).times(a / (a + b)).plus(B), bisector = new Line(C, D), eA = D.minus(C).normSquared - (A.minus(C).cross(D.minus(C)) / b) ** 2, eB = D.minus(C).dot(C.minus(p)) * 2, eC = C.minus(p).normSquared, discriminant = eB * eB - 4 * eA * eC;
|
|
215
|
-
if (discriminant < (-10) ** -5)
|
|
216
|
-
return null;
|
|
217
|
-
let O, r;
|
|
218
|
-
if (Math.abs(discriminant) < 10 ** -5) {
|
|
219
|
-
let t = -eB / (2 * eA);
|
|
220
|
-
O = bisector.evaluate(t), r = O.minus(p).norm;
|
|
221
|
-
} else {
|
|
222
|
-
let t1 = (-eB + Math.sqrt(discriminant)) / (2 * eA), t2 = (-eB - Math.sqrt(discriminant)) / (2 * eA);
|
|
223
|
-
bisector.evaluate(t1).minus(p).normSquared > bisector.evaluate(t2).minus(p).normSquared ? (O = bisector.evaluate(t1), r = bisector.evaluate(t1).minus(p).norm) : (O = bisector.evaluate(t2), r = bisector.evaluate(t2).minus(p).norm);
|
|
224
|
-
}
|
|
225
|
-
return [
|
|
226
|
-
{
|
|
227
|
-
circle: { centre: O, r },
|
|
228
|
-
tangent: new Line(p, p.plus(O.minus(p).normal()))
|
|
229
|
-
}
|
|
230
|
-
];
|
|
231
|
-
}
|
|
232
|
-
fit_NDl(l, err) {
|
|
233
|
-
if (!this.formTriangle(l, err))
|
|
234
|
-
return null;
|
|
235
|
-
let C = this.leftArm.start, A = l.intersectionPoint(this.leftArm, 0), B = l.intersectionPoint(this.rightArm, 0), AC = new Line(A, C), BC = new Line(B, C), AB = new Line(A, B), a = AC.length, b = BC.length, c = AB.length, s = (a + b + c) / 2;
|
|
236
|
-
if (s * (s - a) * (s - b) / (s - c) < 0)
|
|
237
|
-
return null;
|
|
238
|
-
let r = Math.sqrt(s * (s - a) * (s - b) / (s - c)), det = AB.delta.cross(AC.delta), lhsAll = [
|
|
239
|
-
new Vec2(B.cross(A) + r * c, C.cross(A) + r * a),
|
|
240
|
-
new Vec2(B.cross(A) + r * c, C.cross(A) - r * a),
|
|
241
|
-
new Vec2(B.cross(A) - r * c, C.cross(A) + r * a),
|
|
242
|
-
new Vec2(B.cross(A) - r * c, C.cross(A) - r * a)
|
|
243
|
-
], OAll = [];
|
|
244
|
-
lhsAll.forEach((lhs) => {
|
|
245
|
-
OAll.push(
|
|
246
|
-
new Vec2(
|
|
247
|
-
new Vec2(AB.delta.x, AC.delta.x).cross(lhs),
|
|
248
|
-
new Vec2(AB.delta.y, AC.delta.y).cross(lhs)
|
|
249
|
-
).over(-det)
|
|
250
|
-
);
|
|
251
|
-
});
|
|
252
|
-
let o = null, dists = [];
|
|
253
|
-
for (let O of OAll) {
|
|
254
|
-
dists.push({
|
|
255
|
-
raw: Math.abs(BC.distanceToPoint(O) - r),
|
|
256
|
-
norm: Math.abs(BC.distanceToPoint(O) / r - 1)
|
|
257
|
-
});
|
|
258
|
-
let absoluteError = Math.abs(BC.distanceToPoint(O) - r), relativeError = Math.abs(BC.distanceToPoint(O) / r - 1);
|
|
259
|
-
if ((absoluteError < 10 ** -5 || relativeError < 10 ** -5) && AC.pointOnSide(O) !== BC.pointOnSide(O)) {
|
|
260
|
-
o = O;
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
let msg = "";
|
|
265
|
-
if (o === null) {
|
|
266
|
-
msg = "fit_NDl, centre is undefined";
|
|
267
|
-
for (let i = 0; i < OAll.length; i++)
|
|
268
|
-
msg += `centre: (${OAll[i].x}, ${OAll[i].y}), r: ${r}, dist raw: ${dists[i].raw}, dist norm: ${dists[i].norm}
|
|
269
|
-
`;
|
|
270
|
-
}
|
|
271
|
-
if (o === null)
|
|
272
|
-
throw new Error(msg);
|
|
273
|
-
return [
|
|
274
|
-
{
|
|
275
|
-
circle: { centre: o, r },
|
|
276
|
-
tangentParameter: l.closestPointParam(o)
|
|
277
|
-
}
|
|
278
|
-
];
|
|
279
|
-
}
|
|
280
|
-
fitCircles(element, err) {
|
|
281
|
-
return element instanceof Vec2 ? this.isDegenerate ? this.fit_Dp(element, err) : this.fit_NDp(element, err) : element instanceof Line ? this.isDegenerate ? this.fit_Dl((element instanceof Line, element), err) : this.fit_NDl((element instanceof Line, element), err) : null;
|
|
282
|
-
}
|
|
283
|
-
toString() {
|
|
284
|
-
return `LA: ${this.leftArm.start.toString()} --> ${this.leftArm.end.toString()}
|
|
285
|
-
RA: ${this.rightArm.start.toString()} --> ${this.rightArm.end.toString()}`;
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// src/index.ts
|
|
290
|
-
function lineTangentToHull(line, points, halo) {
|
|
291
|
-
let holds = !0, side = 0 /* Top */, k = 0;
|
|
292
|
-
for (; side === 0 /* Top */ && k < points.length; )
|
|
293
|
-
side = line.pointOnSide(points[k], halo), k++;
|
|
294
|
-
for (let i = k; i < points.length; i++) {
|
|
295
|
-
let testSide = line.pointOnSide(points[i], halo);
|
|
296
|
-
if (testSide !== 0 /* Top */ && testSide !== side) {
|
|
297
|
-
holds = !1;
|
|
298
|
-
break;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
return { holds, side };
|
|
302
|
-
}
|
|
303
|
-
function findEnclosingSide(wedge, startVertex, endVertex, points, halo) {
|
|
304
|
-
let side = null, stopVertex = startVertex, vertex = startVertex;
|
|
305
|
-
for (; side === null && vertex > endVertex; ) {
|
|
306
|
-
let p1 = points[vertex], p2 = points[vertex - 1], edge = new Line(p1, p2), circlesEdge = wedge.fitCircles(edge, halo);
|
|
307
|
-
if (circlesEdge !== null) {
|
|
308
|
-
let tangentParameter = 100;
|
|
309
|
-
if (wedge.isDegenerate) {
|
|
310
|
-
let sidedness = 0 /* Top */, k = 0;
|
|
311
|
-
for (; sidedness === 0 /* Top */ && k < points.length; )
|
|
312
|
-
sidedness = edge.pointOnSide(points[k], halo), k++;
|
|
313
|
-
tangentParameter = edge.pointOnSide(circlesEdge[0].circle.centre) !== sidedness ? circlesEdge[0].tangentParameter : circlesEdge[1].tangentParameter;
|
|
314
|
-
} else
|
|
315
|
-
tangentParameter = circlesEdge[0].tangentParameter;
|
|
316
|
-
if (tangentParameter > 0 && tangentParameter < 1) {
|
|
317
|
-
let Y = edge.evaluate(tangentParameter), joint = wedge.leftArm.intersectionPoint(edge, halo);
|
|
318
|
-
side = new Line(joint, Y);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
if (side === null) {
|
|
322
|
-
let circlesPoint = wedge.fitCircles(p2, halo);
|
|
323
|
-
if (circlesPoint !== null) {
|
|
324
|
-
let tangent;
|
|
325
|
-
if (wedge.isDegenerate) {
|
|
326
|
-
let sidedness = 0 /* Top */, k = 0;
|
|
327
|
-
for (; sidedness === 0 /* Top */ && k < points.length; )
|
|
328
|
-
sidedness = circlesPoint[0].tangent.pointOnSide(points[k], halo), k++;
|
|
329
|
-
tangent = circlesPoint[0].tangent.pointOnSide(
|
|
330
|
-
circlesPoint[0].circle.centre,
|
|
331
|
-
halo
|
|
332
|
-
) !== sidedness ? circlesPoint[0].tangent : circlesPoint[1].tangent;
|
|
333
|
-
} else
|
|
334
|
-
tangent = circlesPoint[0].tangent;
|
|
335
|
-
if (lineTangentToHull(tangent, points, halo).holds) {
|
|
336
|
-
let joint = wedge.leftArm.intersectionPoint(tangent, halo);
|
|
337
|
-
side = new Line(joint, p2);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
stopVertex = vertex, vertex--;
|
|
342
|
-
}
|
|
343
|
-
return side === null ? null : { side, stopVertex };
|
|
344
|
-
}
|
|
345
|
-
function findAntipode(points) {
|
|
346
|
-
let farthestIndex = 0, farthestDist = 0;
|
|
347
|
-
for (let i = 0, n = points.length; i < n; i++) {
|
|
348
|
-
let testDist = new Line(points[0], points[n - 1]).distanceToPoint(
|
|
349
|
-
points[i]
|
|
350
|
-
);
|
|
351
|
-
testDist > farthestDist && (farthestDist = testDist, farthestIndex = i);
|
|
352
|
-
}
|
|
353
|
-
return farthestIndex;
|
|
354
|
-
}
|
|
355
|
-
function minTriangleWithBase(convexHull, err, tol) {
|
|
356
|
-
let AB, AC, n = convexHull.length, BC = new Line(convexHull[0], convexHull[n - 1]), antipodIndex = findAntipode(convexHull), baseParallel = new Line(
|
|
357
|
-
convexHull[antipodIndex],
|
|
358
|
-
convexHull[antipodIndex].plus(BC.delta)
|
|
359
|
-
), wedge = Wedge.new(BC, baseParallel, err), Pn = n - 1, Qn = antipodIndex;
|
|
360
|
-
do {
|
|
361
|
-
let CQinfo = findEnclosingSide(wedge, Pn, antipodIndex, convexHull, err);
|
|
362
|
-
if (CQinfo === null)
|
|
363
|
-
return null;
|
|
364
|
-
({ side: AC, stopVertex: Pn } = CQinfo), wedge = Wedge.new(wedge.leftArm, AC, err);
|
|
365
|
-
let BPinfo = findEnclosingSide(wedge, Qn, 0, convexHull, err);
|
|
366
|
-
if (BPinfo === null)
|
|
367
|
-
return null;
|
|
368
|
-
({ side: AB, stopVertex: Qn } = BPinfo), wedge = Wedge.new(wedge.leftArm, AB, err);
|
|
369
|
-
} while (AB.length - AC.length > tol);
|
|
370
|
-
let A = AC.intersectionPoint(AB, 0), B = AB.start, C = AC.start;
|
|
371
|
-
return { A, B, C };
|
|
372
|
-
}
|
|
373
|
-
function minTriangle(convexHull, err, tol) {
|
|
374
|
-
if (convexHull.length < 3)
|
|
375
|
-
return null;
|
|
376
|
-
if (convexHull.length === 3)
|
|
377
|
-
return { A: convexHull[0], B: convexHull[1], C: convexHull[2] };
|
|
378
|
-
let points = convexHull.map((p) => new Vec2(p.x, p.y)), A = null, B = null, C = null, perimeter = -1, rotations = 0;
|
|
379
|
-
for (; rotations < points.length; ) {
|
|
380
|
-
rotations > 0 && points.push(points.shift());
|
|
381
|
-
let triangle = minTriangleWithBase(points, err, tol);
|
|
382
|
-
if (triangle !== null) {
|
|
383
|
-
let { A: A1, B: B1, C: C1 } = triangle, perimeter1 = A1.minus(B1).norm + B1.minus(C1).norm + C1.minus(A1).norm;
|
|
384
|
-
(perimeter1 < perimeter || perimeter === -1) && ([A, B, C] = [A1, B1, C1], perimeter = perimeter1);
|
|
385
|
-
}
|
|
386
|
-
rotations++;
|
|
387
|
-
}
|
|
388
|
-
return perimeter === -1 ? null : {
|
|
389
|
-
A: { x: A.x, y: A.y },
|
|
390
|
-
B: { x: B.x, y: B.y },
|
|
391
|
-
C: { x: C.x, y: C.y }
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
export {
|
|
395
|
-
lineTangentToHull,
|
|
396
|
-
minTriangle,
|
|
397
|
-
minTriangleWithBase
|
|
398
|
-
};
|
|
399
|
-
//# sourceMappingURL=index.mjs.map
|