flo-mat 4.1.4 → 4.1.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/__tests__/cp-node/circle-identity.spec.ts +56 -0
- package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs-same-curve.spec.ts +7 -5
- package/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs.spec.ts +4 -2
- package/browser/index.js +2606 -2161
- package/browser/index.min.js +1 -1
- package/node/add-n-prong.ts/join-spokes.js +3 -2
- package/node/add-n-prong.ts/join-spokes.js.map +1 -1
- package/node/cp-node/fs/enhance-cp-node.d.ts +9 -9
- package/node/cp-node/fs/get-angle-between-mat-curves.d.ts +1 -1
- package/node/cp-node/fs/get-angle-between-mat-curves.js +2 -1
- package/node/cp-node/fs/get-angle-between-mat-curves.js.map +1 -1
- package/node/cp-node/fs/get-edge-direction.js +3 -2
- package/node/cp-node/fs/get-edge-direction.js.map +1 -1
- package/node/cp-node/fs/get-implied-boundary-bezier-between.d.ts +1 -1
- package/node/cp-node/fs/get-implied-boundary-bezier-between.js +3 -2
- package/node/cp-node/fs/get-implied-boundary-bezier-between.js.map +1 -1
- package/node/cp-node/fs/get-mat-curve-between.d.ts +1 -0
- package/node/cp-node/fs/get-mat-curve-between.js +1 -0
- package/node/cp-node/fs/get-mat-curve-between.js.map +1 -1
- package/node/cp-node/fs/is-fully-terminating.d.ts +1 -1
- package/node/cp-node/fs/is-fully-terminating.js +3 -5
- package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
- package/node/cp-node/fs/is-on-same-circle.d.ts +3 -0
- package/node/cp-node/fs/is-on-same-circle.js +4 -4
- package/node/cp-node/fs/is-on-same-circle.js.map +1 -1
- package/node/cp-node/stringification/from-stringifyable.js +16 -0
- package/node/cp-node/stringification/from-stringifyable.js.map +1 -1
- package/node/find-2-prong/add-2-prong.js +6 -2
- package/node/find-2-prong/add-2-prong.js.map +1 -1
- package/node/find-2-prong/calc-seperation-tolerance.js +2 -2
- package/node/find-2-prong/calc-seperation-tolerance.js.map +1 -1
- package/node/find-3-prong/find-3-prong-for-delta3s.js +1 -1
- package/node/find-3-prong/find-3-prong-for-delta3s.js.map +1 -1
- package/node/geometry/get-closest-squared-distance-to-rotated-rect.js +2 -1
- package/node/geometry/get-closest-squared-distance-to-rotated-rect.js.map +1 -1
- package/node/mat/get-closeby-cp-if-exist.js +2 -1
- package/node/mat/get-closeby-cp-if-exist.js.map +1 -1
- package/node/point-on-shape/point-on-shape.d.ts +5 -0
- package/node/reconstruct-from-mat/reconstruct-from-mat.js.map +1 -1
- package/package.json +12 -12
- package/src/add-n-prong.ts/join-spokes.ts +4 -2
- package/src/cp-node/fs/get-angle-between-mat-curves.ts +4 -2
- package/src/cp-node/fs/get-edge-direction.ts +4 -2
- package/src/cp-node/fs/get-implied-boundary-bezier-between.ts +6 -6
- package/src/cp-node/fs/get-mat-curve-between.ts +1 -0
- package/src/cp-node/fs/is-fully-terminating.ts +3 -7
- package/src/cp-node/fs/is-on-same-circle.ts +6 -7
- package/src/cp-node/stringification/from-stringifyable.ts +17 -0
- package/src/find-2-prong/add-2-prong.ts +7 -2
- package/src/find-2-prong/calc-seperation-tolerance.ts +2 -2
- package/src/find-3-prong/find-3-prong-for-delta3s.ts +1 -1
- package/src/geometry/get-closest-squared-distance-to-rotated-rect.ts +4 -4
- package/src/mat/get-closeby-cp-if-exist.ts +3 -1
- package/src/point-on-shape/point-on-shape.ts +5 -0
- package/src/utils/deg-to-rad.ts +4 -2
- package/src/utils/rad-to-deg.ts +4 -1
- package/webpack.config.cjs +7 -2
|
@@ -4,6 +4,8 @@ import { toUnitVector, fromTo, rotate, translate, rotate90Degrees, reverse as re
|
|
|
4
4
|
import { tangent } from 'flo-bezier3';
|
|
5
5
|
import { isPosSharpCorner } from '../../point-on-shape/is-pos-sharp-corner.js';
|
|
6
6
|
|
|
7
|
+
const { sqrt } = Math;
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Returns a line segment of unit length starting in the given Vertex center and
|
|
@@ -54,8 +56,8 @@ function getEdgeDirection(
|
|
|
54
56
|
// Recall the identities sin(acos(x)) = sqrt(1-x^2), etc. Also
|
|
55
57
|
// recall the half angle formulas. Then the rotation matrix, R, can
|
|
56
58
|
// be calculated.
|
|
57
|
-
const cosθ =
|
|
58
|
-
const sinθ =
|
|
59
|
+
const cosθ = sqrt((1 + x)/2);
|
|
60
|
+
const sinθ = sqrt((1 - x)/2);
|
|
59
61
|
|
|
60
62
|
vDir = rotate(sinθ, cosθ, tan2);
|
|
61
63
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { CpNode } from '../cp-node.js';
|
|
1
2
|
import { tangent } from 'flo-bezier3';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
}
|
|
5
|
-
import { CpNode } from '../cp-node.js';
|
|
3
|
+
import { fromTo, dot, cross, translate, lineLineIntersection, toUnitVector } from 'flo-vector2d';
|
|
4
|
+
|
|
5
|
+
const { abs } = Math;
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
/** @internal */
|
|
@@ -56,8 +56,8 @@ function getImpliedBoundaryBezierBetween(
|
|
|
56
56
|
const w1 = fromTo(lA[0], lA[1]); // This is a unit vector
|
|
57
57
|
const w2 = fromTo(lB[0], lB[1]); // This is a unit vector
|
|
58
58
|
|
|
59
|
-
const d1 =
|
|
60
|
-
const d2 =
|
|
59
|
+
const d1 = abs(cross(c, w1)) / (3*3);
|
|
60
|
+
const d2 = abs(cross(c, w2)) / (3*3);
|
|
61
61
|
|
|
62
62
|
if (d1 > TOLERANCE_ADD_2PRONG || d2 > TOLERANCE_ADD_2PRONG) {
|
|
63
63
|
// not within tolerance
|
|
@@ -5,13 +5,10 @@ import { isTrivial } from "./is-trivial.js";
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Like isTerminating
|
|
8
|
+
* Like `isTerminating` but only returns true if all `CpNode`s on the circle
|
|
9
9
|
* (except this.prevOnCircle) is terminating.
|
|
10
10
|
*/
|
|
11
11
|
function isFullyTerminating(cpNode: CpNode) {
|
|
12
|
-
// const otherOnCircle = getAllOnCircle(cpNode.prevOnCircle, true);
|
|
13
|
-
|
|
14
|
-
// return otherOnCircle.every(isTerminating);
|
|
15
12
|
if (!isTerminating(cpNode)) {
|
|
16
13
|
return false;
|
|
17
14
|
}
|
|
@@ -24,9 +21,8 @@ function isFullyTerminating(cpNode: CpNode) {
|
|
|
24
21
|
cpNode = cpNode.prev;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return otherOnCircle.every(isTerminating);
|
|
24
|
+
return getAllOnCircle(cpNode.prevOnCircle, true)
|
|
25
|
+
.every(isTerminating);
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { CpNode } from "../cp-node.js";
|
|
2
|
-
import { getAllOnCircle } from "./get-all-on-circle.js";
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
|
-
* Returns true if the 2 given `CpNode`s are on the same maximal disk
|
|
5
|
+
* Returns true if the 2 given `CpNode`s are on the same maximal disk
|
|
7
6
|
* circle.
|
|
8
|
-
*
|
|
7
|
+
*
|
|
8
|
+
* * O(1): all `CpNode`s on the same on-circle ring share the same `Circle`
|
|
9
|
+
* object, and no other ring does (see `PointOnShape.circle`)
|
|
10
|
+
*
|
|
9
11
|
* @param cpNode1 A `CpNode`.
|
|
10
12
|
* @param cpNode2 Another `CpNode`
|
|
11
13
|
*/
|
|
@@ -13,10 +15,7 @@ function isOnSameCircle(
|
|
|
13
15
|
cpNode1: CpNode,
|
|
14
16
|
cpNode2: CpNode) {
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
const cpNodes = getAllOnCircle(cpNode1);
|
|
18
|
-
|
|
19
|
-
return cpNodes.indexOf(cpNode2) >= 0;
|
|
18
|
+
return cpNode1.pointOnShape.circle === cpNode2.pointOnShape.circle;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { PointOnShape } from "../../point-on-shape/point-on-shape.js";
|
|
2
2
|
import type { CpNode } from "../cp-node";
|
|
3
3
|
import type { CpNodeStringifyable } from "./cp-node-stringifyable";
|
|
4
|
+
import type { Mutable } from "../../utils/mutable.js";
|
|
4
5
|
import { EDGES } from "./cp-node-stringifyable";
|
|
6
|
+
import { getAllOnCircle } from "../fs/get-all-on-circle.js";
|
|
5
7
|
import { loopFromStringifyable } from './loop-from-stringifyable.js';
|
|
6
8
|
|
|
7
9
|
|
|
@@ -51,6 +53,21 @@ function fromStringifyable(
|
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
//--------------------------------------------------------------------------
|
|
57
|
+
// Third pass: one shared `Circle` object per on-circle ring, as when the
|
|
58
|
+
// MAT was built (the JSON gave every contact point its own copy).
|
|
59
|
+
//--------------------------------------------------------------------------
|
|
60
|
+
const done = new Set<CpNode>();
|
|
61
|
+
for (const cpNode of cpNodes) {
|
|
62
|
+
if (done.has(cpNode)) { continue; }
|
|
63
|
+
|
|
64
|
+
const { circle } = cpNode.pointOnShape;
|
|
65
|
+
for (const cp of getAllOnCircle(cpNode)) {
|
|
66
|
+
done.add(cp);
|
|
67
|
+
(cp.pointOnShape as Mutable<PointOnShape>).circle = circle;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
54
71
|
return cpNodes[0];
|
|
55
72
|
}
|
|
56
73
|
|
|
@@ -83,12 +83,17 @@ function closeHole(
|
|
|
83
83
|
|
|
84
84
|
const [cpNodeSource, cpNodeAntipode] = cpNodes as Mutable<CpNode>[];
|
|
85
85
|
|
|
86
|
+
// The twins form their own on-circle ring (a separate MAT vertex - that
|
|
87
|
+
// is what cuts the hole), so they get their own (equal) `Circle` object:
|
|
88
|
+
// one `Circle` object per ring.
|
|
89
|
+
const twinCircle: Circle = { ...cpNodeSource.pointOnShape.circle };
|
|
90
|
+
|
|
86
91
|
// Antipode - create and insert twin
|
|
87
92
|
const posAntipode = cpNodeAntipode.pointOnShape;
|
|
88
93
|
const cpNodeAntipodeTwin = insertCpNode(
|
|
89
94
|
true, true, false,
|
|
90
95
|
cpTrees.get(posAntipode.curve.loop)!,
|
|
91
|
-
{ ...posAntipode, order2: +1 },
|
|
96
|
+
{ ...posAntipode, circle: twinCircle, order2: +1 },
|
|
92
97
|
cpNodeAntipode,
|
|
93
98
|
undefined, // unused
|
|
94
99
|
meta.lastInsertId
|
|
@@ -101,7 +106,7 @@ function closeHole(
|
|
|
101
106
|
const cpNodeSourceTwin = insertCpNode(
|
|
102
107
|
true, true, false,
|
|
103
108
|
cpTrees.get(posSource.curve.loop)!,
|
|
104
|
-
{ ...posSource!, order2: -1 },
|
|
109
|
+
{ ...posSource!, circle: twinCircle, order2: -1 },
|
|
105
110
|
cpNodeSource.prev,
|
|
106
111
|
undefined, // unused
|
|
107
112
|
meta.lastInsertId
|
|
@@ -89,10 +89,10 @@ export { calcSeperationTolerance }
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
// function degToRad(degrees: number) {
|
|
92
|
-
// return degrees/360*2*
|
|
92
|
+
// return degrees/360*2*PI;
|
|
93
93
|
// }
|
|
94
94
|
// function radToDeg(rad: number) {
|
|
95
|
-
// return rad*360/2/
|
|
95
|
+
// return rad*360/2/PI;
|
|
96
96
|
// }
|
|
97
97
|
|
|
98
98
|
|
|
@@ -174,7 +174,7 @@ function find3ProngForDelta3s(
|
|
|
174
174
|
const v2 = toUnitVector( tangent(pos.curve.ps, pos.t) );
|
|
175
175
|
|
|
176
176
|
// Cross is more numerically stable than Vector.dot at angles a
|
|
177
|
-
// multiple of
|
|
177
|
+
// multiple of π **and** is close to the actual angle value
|
|
178
178
|
// and can thus just be added to cone method of looking at
|
|
179
179
|
// tolerance.
|
|
180
180
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
}
|
|
1
|
+
import { squaredDistanceBetweenPointAndLineSegment, squaredDistanceBetween } from 'flo-vector2d';
|
|
2
|
+
|
|
3
|
+
const { min } = Math;
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -23,7 +23,7 @@ function getClosestSquaredDistanceToRotatedRect(ps: number[][], p: number[]) {
|
|
|
23
23
|
return 0; // Inside rotated rect
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
return
|
|
26
|
+
return min(...ds);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
|
|
@@ -5,10 +5,12 @@ import type { MatMeta } from './mat-meta.js';
|
|
|
5
5
|
import { distanceBetween, toUnitVector, fromTo, dot } from 'flo-vector2d';
|
|
6
6
|
import { getCpNodeNeighbors } from './get-cp-node-neighbors.js';
|
|
7
7
|
|
|
8
|
+
const { cos, PI: π } = Math;
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
/** @internal */
|
|
10
12
|
const DEGREES = 1;
|
|
11
|
-
const ANGLE_THRESHOLD =
|
|
13
|
+
const ANGLE_THRESHOLD = cos(DEGREES * (π/180));
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -44,6 +44,11 @@ interface PointOnShape extends PrePointOnShape {
|
|
|
44
44
|
* The (cached) maximal disk circle touching this point.
|
|
45
45
|
* Calculated from `curve` and `t` (if 2-prong source point, else
|
|
46
46
|
* from `curve` and `t` of the antipodal 2-prong point).
|
|
47
|
+
*
|
|
48
|
+
* * the same `Circle` object is shared by all `CpNode`s on the same
|
|
49
|
+
* on-circle ring (`nextOnCircle`), and only by them - so object
|
|
50
|
+
* identity identifies the MAT vertex (hole-closer twins form their own
|
|
51
|
+
* ring, with their own equal circle)
|
|
47
52
|
*/
|
|
48
53
|
readonly circle: Circle;
|
|
49
54
|
/** Internally used to order two points lying at the same planar point. */
|
package/src/utils/deg-to-rad.ts
CHANGED
package/src/utils/rad-to-deg.ts
CHANGED
package/webpack.config.cjs
CHANGED
|
@@ -38,8 +38,13 @@ const config_Basic = (env, argv) => {
|
|
|
38
38
|
rules: [{
|
|
39
39
|
test: /\.tsx?$/,
|
|
40
40
|
use: [{
|
|
41
|
-
loader: '
|
|
42
|
-
options: {
|
|
41
|
+
loader: 'swc-loader',
|
|
42
|
+
options: {
|
|
43
|
+
jsc: {
|
|
44
|
+
parser: { syntax: 'typescript' },
|
|
45
|
+
target: 'esnext'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
43
48
|
}],
|
|
44
49
|
exclude: /node_modules/,
|
|
45
50
|
sideEffects: false
|