flo-mat 3.0.10 → 3.0.12

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.
Files changed (183) hide show
  1. package/__tests__/jsog/check-jsog-eql-calc.spec.ts +81 -0
  2. package/__tests__/jsog/decode-jsog.ts +85 -0
  3. package/__tests__/jsog/get-mats1.ts +41 -0
  4. package/__tests__/{cp-node/fs → jsog}/mat-dummys.ts +51 -564
  5. package/__tests__/jsog/to-jsog-breath-first.ts +107 -0
  6. package/__tests__/jsog/to-jsog-depth-first.ts +55 -0
  7. package/browser/index.js +126 -84
  8. package/browser/index.min.js +1 -1
  9. package/node/add-n-prong.ts/join-spokes.js.map +1 -1
  10. package/node/closest-boundary-point/dd-deflate-with-running-error.js.map +1 -1
  11. package/node/closest-boundary-point/get-close-boundary-points-certified.js.map +1 -1
  12. package/node/contact-point/contact-point.js.map +1 -1
  13. package/node/corner/get-corner.js.map +1 -1
  14. package/node/corner/get-interface-ccw.js.map +1 -1
  15. package/node/cp-node/cp-node-fs.d.ts +2 -1
  16. package/node/cp-node/cp-node-fs.js +1 -2
  17. package/node/cp-node/cp-node-fs.js.map +1 -1
  18. package/node/cp-node/fs/cp-node-comparator.d.ts +3 -0
  19. package/node/cp-node/fs/cp-node-comparator.js +6 -0
  20. package/node/cp-node/fs/cp-node-comparator.js.map +1 -0
  21. package/node/cp-node/fs/find-first.js.map +1 -1
  22. package/node/cp-node/fs/get-all-on-loop.js.map +1 -1
  23. package/node/cp-node/fs/get-branch-beziers.js.map +1 -1
  24. package/node/cp-node/fs/get-branch.js.map +1 -1
  25. package/node/cp-node/fs/get-children.js.map +1 -1
  26. package/node/cp-node/fs/get-first-exit.js.map +1 -1
  27. package/node/cp-node/fs/get-mat-curve-to-next.js.map +1 -1
  28. package/node/cp-node/fs/get-mat-curves-between.js.map +1 -1
  29. package/node/cp-node/fs/get-prong-count.js.map +1 -1
  30. package/node/cp-node/fs/get-real-prong-count.js.map +1 -1
  31. package/node/cp-node/fs/get-vertex-forward-children.js.map +1 -1
  32. package/node/cp-node/fs/is-fully-terminating.d.ts +1 -1
  33. package/node/cp-node/fs/is-fully-terminating.js.map +1 -1
  34. package/node/cp-node/fs/is-one-prong.js.map +1 -1
  35. package/node/cp-node/fs/is-sharp.js.map +1 -1
  36. package/node/cp-node/fs/is-terminating.js.map +1 -1
  37. package/node/cp-node/fs/traverse-cp.js.map +1 -1
  38. package/node/cp-node/fs/traverse-edges.js.map +1 -1
  39. package/node/cp-node/fs/traverse-vertices.js.map +1 -1
  40. package/node/debug/functions/draw-elem/bounding-hull.js.map +1 -1
  41. package/node/debug/functions/draw-elem/draw-cp-node.js +1 -1
  42. package/node/debug/functions/draw-elem/draw-cp-node.js.map +1 -1
  43. package/node/debug/functions/draw-elem/draw-cull.js.map +1 -1
  44. package/node/debug/functions/draw-elem/draw-dull-corner.js.map +1 -1
  45. package/node/debug/functions/draw-elem/draw-elem.js.map +1 -1
  46. package/node/debug/functions/draw-elem/draw-leaves.js.map +1 -1
  47. package/node/debug/functions/draw-elem/draw-loose-bounding-box.js.map +1 -1
  48. package/node/debug/functions/draw-elem/draw-max-vertex.js.map +1 -1
  49. package/node/debug/functions/draw-elem/draw-min-y.js.map +1 -1
  50. package/node/debug/functions/draw-elem/draw-one-prong-at-dull-corner.js.map +1 -1
  51. package/node/debug/functions/draw-elem/draw-one-prong.js.map +1 -1
  52. package/node/debug/functions/draw-elem/draw-sharp-corner.js.map +1 -1
  53. package/node/debug/functions/draw-elem/draw-speed.js.map +1 -1
  54. package/node/debug/functions/draw-elem/draw-three-prong.js.map +1 -1
  55. package/node/debug/functions/draw-elem/draw-tight-bounding-box.js.map +1 -1
  56. package/node/debug/functions/draw-elem/draw-two-prong.js.map +1 -1
  57. package/node/debug/functions/draw-elem/draw-vertex.js.map +1 -1
  58. package/node/debug/functions/general.js.map +1 -1
  59. package/node/find-2-prong/add-1-prong.js.map +1 -1
  60. package/node/find-2-prong/find-2-prong.d.ts +1 -0
  61. package/node/find-2-prong/find-2-prong.js +2 -1
  62. package/node/find-2-prong/find-2-prong.js.map +1 -1
  63. package/node/find-2-prong/find-equidistant-point-on-line-dd.js.map +1 -1
  64. package/node/find-3-prong.ts/find-3-prong.js.map +1 -1
  65. package/node/find-3-prong.ts/find-and-add-3-prong.js.map +1 -1
  66. package/node/find-3-prong.ts/find-and-add-3-prongs.js.map +1 -1
  67. package/node/find-mat/find-mats.js.map +1 -1
  68. package/node/find-mat/mat-options.js +1 -1
  69. package/node/find-mat/mat-options.js.map +1 -1
  70. package/node/geometry/get-closest-square-distance-to-rect.js.map +1 -1
  71. package/node/geometry/get-closest-squared-distance-to-rotated-rect.js.map +1 -1
  72. package/node/index.d.ts +35 -1
  73. package/node/index.js +36 -1
  74. package/node/index.js.map +1 -1
  75. package/node/mat/create-new-cp-tree.js.map +1 -1
  76. package/node/mat/get-largest-vertex.js.map +1 -1
  77. package/node/mat/trim-mat.js.map +1 -1
  78. package/node/memoize-primitive.js.map +1 -1
  79. package/node/sat/add-debug-info.js.map +1 -1
  80. package/node/sat/get-leaves.js.map +1 -1
  81. package/node/svg/get-loop-bounds.js.map +1 -1
  82. package/node/svg/get-min-y-pos.js.map +1 -1
  83. package/node/sweep-line/sweep-line.js.map +1 -1
  84. package/package.json +4 -4
  85. package/src/add-n-prong.ts/join-spokes.ts +11 -11
  86. package/src/closest-boundary-point/dd-deflate-with-running-error.ts +22 -22
  87. package/src/closest-boundary-point/get-close-boundary-points-certified.ts +38 -38
  88. package/src/contact-point/contact-point.ts +13 -13
  89. package/src/corner/get-corner.ts +39 -39
  90. package/src/corner/get-interface-ccw.ts +3 -3
  91. package/src/cp-node/cp-node-fs.ts +132 -135
  92. package/src/cp-node/cp-node.ts +30 -30
  93. package/src/cp-node/fs/clone.ts +4 -4
  94. package/src/cp-node/fs/cp-node-comparator.ts +13 -0
  95. package/src/cp-node/fs/find-first.ts +6 -6
  96. package/src/cp-node/fs/get-all-on-loop.ts +1 -1
  97. package/src/cp-node/fs/get-branch-beziers.ts +1 -1
  98. package/src/cp-node/fs/get-branch.ts +1 -1
  99. package/src/cp-node/fs/get-children.ts +8 -8
  100. package/src/cp-node/fs/get-first-exit.ts +11 -11
  101. package/src/cp-node/fs/get-mat-curve-to-next.ts +1 -1
  102. package/src/cp-node/fs/get-mat-curves-between.ts +1 -1
  103. package/src/cp-node/fs/get-prong-count.ts +8 -8
  104. package/src/cp-node/fs/get-real-prong-count.ts +3 -3
  105. package/src/cp-node/fs/get-vertex-forward-children.ts +10 -10
  106. package/src/cp-node/fs/is-fully-terminating.ts +3 -3
  107. package/src/cp-node/fs/is-one-prong.ts +8 -8
  108. package/src/cp-node/fs/is-sharp.ts +1 -1
  109. package/src/cp-node/fs/is-terminating.ts +1 -1
  110. package/src/cp-node/fs/iterate-all-on-loop.ts +6 -6
  111. package/src/cp-node/fs/traverse-all-forward.ts +11 -11
  112. package/src/cp-node/fs/traverse-cp.ts +19 -17
  113. package/src/cp-node/fs/traverse-edges.ts +10 -10
  114. package/src/cp-node/fs/traverse-vertices.ts +17 -17
  115. package/src/curve/curve.ts +26 -26
  116. package/src/debug/functions/cmp-cp-on-delta.ts +1 -1
  117. package/src/debug/functions/draw-elem/bounding-hull.ts +2 -2
  118. package/src/debug/functions/draw-elem/culls.ts +2 -2
  119. package/src/debug/functions/draw-elem/draw-cp-node.ts +30 -30
  120. package/src/debug/functions/draw-elem/draw-cull.ts +2 -2
  121. package/src/debug/functions/draw-elem/draw-dull-corner.ts +7 -7
  122. package/src/debug/functions/draw-elem/draw-elem.ts +28 -28
  123. package/src/debug/functions/draw-elem/draw-leaves.ts +12 -12
  124. package/src/debug/functions/draw-elem/draw-loose-bounding-box.ts +7 -7
  125. package/src/debug/functions/draw-elem/draw-max-vertex.ts +2 -2
  126. package/src/debug/functions/draw-elem/draw-min-y.ts +2 -2
  127. package/src/debug/functions/draw-elem/draw-one-prong-at-dull-corner.ts +1 -1
  128. package/src/debug/functions/draw-elem/draw-one-prong.ts +1 -1
  129. package/src/debug/functions/draw-elem/draw-sharp-corner.ts +6 -6
  130. package/src/debug/functions/draw-elem/draw-speed.ts +2 -2
  131. package/src/debug/functions/draw-elem/draw-three-prong.ts +28 -28
  132. package/src/debug/functions/draw-elem/draw-tight-bounding-box.ts +4 -4
  133. package/src/debug/functions/draw-elem/draw-two-prong.ts +51 -51
  134. package/src/debug/functions/draw-elem/draw-vertex.ts +12 -12
  135. package/src/debug/functions/draw-elem/dull-corner.ts +7 -7
  136. package/src/debug/functions/draw-elem/leaves.ts +2 -2
  137. package/src/debug/functions/draw-elem/loose-bounding-box.ts +7 -7
  138. package/src/debug/functions/draw-elem/max-vertex.ts +2 -2
  139. package/src/debug/functions/draw-elem/min-y.ts +2 -2
  140. package/src/debug/functions/draw-elem/one-prong-at-dull-corner.ts +1 -1
  141. package/src/debug/functions/draw-elem/one-prong.ts +1 -1
  142. package/src/debug/functions/draw-elem/sharp-corner.ts +6 -6
  143. package/src/debug/functions/draw-elem/three-prong.ts +19 -19
  144. package/src/debug/functions/draw-elem/tight-bounding-box.ts +4 -4
  145. package/src/debug/functions/draw-elem/two-prong.ts +34 -34
  146. package/src/debug/functions/draw-elem/vertex.ts +28 -28
  147. package/src/debug/functions/general.ts +18 -18
  148. package/src/debug/functions/three-prong.ts +184 -184
  149. package/src/debug/functions/two-prong.ts +112 -112
  150. package/src/find-2-prong/add-1-prong.ts +25 -25
  151. package/src/find-2-prong/find-2-prong.ts +158 -157
  152. package/src/find-2-prong/find-equidistant-point-on-line-dd.ts +50 -50
  153. package/src/find-2-prong/find-equidistant-point-on-line.ts +27 -27
  154. package/src/find-3-prong.ts/find-3-prong-for-delta3s.ts +1 -1
  155. package/src/find-3-prong.ts/find-3-prong.ts +23 -23
  156. package/src/find-3-prong.ts/find-and-add-3-prong.ts +37 -37
  157. package/src/find-3-prong.ts/find-and-add-3-prongs.ts +30 -30
  158. package/src/find-mat/add-2-prongs-by-error.ts +1 -1
  159. package/src/find-mat/find-mats.ts +49 -49
  160. package/src/find-mat/fix-ordering.ts +2 -2
  161. package/src/find-mat/get-total-by.ts +12 -12
  162. package/src/find-mat/mat-options.ts +1 -1
  163. package/src/geometry/get-closest-square-distance-to-rect.ts +37 -37
  164. package/src/geometry/get-closest-squared-distance-to-rotated-rect.ts +14 -14
  165. package/src/get-curve/get-curve-between.ts +1 -1
  166. package/src/index.ts +40 -3
  167. package/src/mat/cmp-cp-on-delta.ts +1 -1
  168. package/src/mat/create-new-cp-tree.ts +12 -12
  169. package/src/mat/get-edges-as-array.ts +9 -9
  170. package/src/mat/get-largest-3-prong.ts +8 -8
  171. package/src/mat/get-largest-three-prong.ts +5 -5
  172. package/src/mat/get-largest-vertex.ts +6 -6
  173. package/src/mat/get-two-prong-type.ts +3 -3
  174. package/src/mat/trim-mat.ts +1 -1
  175. package/src/memoize-primitive.ts +14 -14
  176. package/src/sat/add-debug-info.ts +4 -4
  177. package/src/sat/cull-by-salience.ts +1 -1
  178. package/src/sat/get-leaves.ts +0 -1
  179. package/src/svg/get-extreme.ts +8 -8
  180. package/src/svg/get-loop-bounds.ts +84 -84
  181. package/src/svg/get-min-y-pos.ts +1 -1
  182. package/src/sweep-line/sweep-line.ts +23 -23
  183. package/__tests__/cp-node/fs/check-jsog-eql-calc.spec.ts +0 -30
@@ -31,7 +31,8 @@ const { ceil, log2, max, sqrt, abs, sin, cos } = Math;
31
31
  * "The starting point of this algorithm is a choice of a circle Br(x)
32
32
  * centered at an interior point x which contains two boundary portions c and
33
33
  * d of dΩ as in Fig. 19."
34
- * In fact, we (and they) start by fixing one point on the boundary beforehand.
34
+ * In fact, we (and they) start by fixing one point on the boundary beforehand.
35
+ *
35
36
  * @param loops A shape represented by path loops
36
37
  * @param maxCoordinate The extreme coordinate value of the shape
37
38
  * @param squaredDiagonalLength The squared diagonal length of the shape
@@ -41,166 +42,166 @@ const { ceil, log2, max, sqrt, abs, sin, cos } = Math;
41
42
  * @param loopIdx The loop array index
42
43
  */
43
44
  function find2Prong(
44
- meta: MatMeta,
45
- isHoleClosing: boolean,
46
- for1Prong: boolean,
47
- angle: number,
48
- y: PointOnShape): { circle: Circle, zs: PointOnShape[] } | undefined {
49
-
50
- const { loops, maxCoordinate, squaredDiagonalLength } = meta;
51
-
52
- const loop = y.curve.loop;
53
-
54
- const MAX_ITERATIONS = 25;
55
- const minSquaredSeperationTolerance = ((2**-21)*maxCoordinate)**2;
56
- const errorTolerance = (2**-46)*maxCoordinate;
57
- // const errorTolerance = (2**-28)*maxCoordinate;
58
- const maxOsculatingCircleRadius = sqrt(squaredDiagonalLength);
59
- const minCurvature = 1/maxOsculatingCircleRadius;
60
- const oneProngTolerance = (2**-16)*maxCoordinate;
61
-
62
- const [xO,rO] = getO(
63
- angle, isHoleClosing, maxOsculatingCircleRadius, minCurvature, y
64
- );
65
-
66
- const p = y.p;
67
-
68
- // The boundary piece that should contain the other point of
69
- // the 2-prong circle. (Defined by start and end points).
70
- let curvePieces = getInitialCurvePieces(
71
- angle, isHoleClosing, loop, loops, meta, y, { center: xO, radius: rO }
72
- );
73
- // console.log(curvePieces.length);
74
-
75
- /** The center of the two-prong (successively refined) */
76
- let x = xO;
77
-
78
- // The lines below is an optimization.
79
- const r_ = sqrt(reduceRadius(maxCoordinate, curvePieces, p, xO));
80
- if (rO > r_) {
81
- x = interpolate(p, xO, r_/rO);
82
- }
83
-
84
- /** The antipode of the two-prong (successively refined) */
85
- let zs: PointOnShape[] = undefined!;
86
- let z: PointOnShape = undefined!;
87
-
88
- let i = 0;
89
- while (i < MAX_ITERATIONS) {
90
- const xy = squaredDistanceBetweenDd(x, y.p);
91
-
92
- if (i < 2) { curvePieces = cullCurvePieces2(curvePieces, x, xy); }
93
- const pow = max(0,ceil(log2(maxCoordinate/xy))) + 1; // determines accuracy
94
- // console.log(pow);
95
- const _zs = getCloseBoundaryPointsCertified(
96
- pow, curvePieces, x, y.curve, y.t,
97
- for1Prong && i == 0 && rO !== 1/minCurvature,
98
- angle
99
- ).map(info => createPos(info.curve, info.t, false));
100
-
101
- let maxD = Number.NEGATIVE_INFINITY;
102
- let maxPos: PointOnShape = undefined!;
103
- zs = [];
104
- for (const z of _zs) {
105
- if (z === undefined) { continue; }
106
- const _yz = squaredDistanceBetweenDd(y.p, z.p);
107
- if (_yz > maxD) {
108
- maxD = _yz;
109
- maxPos = z;
110
- }
111
- if (_yz !== 0) {
112
- zs.push(z);
113
- }
114
- }
115
- // z = zs[0];
116
- const yz = maxD;
117
- z = maxPos;
118
-
119
- if (z === undefined || yz === 0) {
120
- // addDebugInfo2(isHoleClosing);
121
- return undefined;
122
- }
123
-
124
- const xz = squaredDistanceBetweenDd(x, z.p);
125
-
126
- // if on first try
127
- if (i === 0) {
128
- if (rO < (1 - oneProngTolerance)*sqrt(xz)) {
129
- // console.log('1prong');
130
- add1Prong(meta, rO, xO, y);
131
- return undefined;
132
- }
133
- }
134
-
135
- // if (typeof _debug_ !== 'undefined') { xs.push({ x, y, z: createPos(z.curve, z.t, false), t: y.t }); }
136
-
137
-
138
- if (!isHoleClosing) {
139
- const squaredSeperationTolerance = max(calcSeperationTolerance(
140
- rO, sqrt(xz), 2**2*errorTolerance
141
- ), minSquaredSeperationTolerance);
142
- if (yz <= squaredSeperationTolerance) {
143
- // if (typeof _debug_ !== 'undefined') { console.log(`failed: seperation too small - ${sqrt(yz)}`); }
144
- return undefined;
145
- }
146
- }
147
-
148
- // Find the point on the line connecting y with x that is
149
- // equidistant from y and z. This will be our next x.
150
- const nextX = findEquidistantPointOnLineDd(x, y.p, z.p);
151
- const error = abs(sqrt(xy) - sqrt(xz));
152
- // if (xy < xz) { return undefined; }
153
-
154
- x = nextX;
155
-
156
- if (error < errorTolerance) {
157
- break;
158
- }
159
-
160
- i++;
161
-
162
- if (i === MAX_ITERATIONS) {
163
- // Convergence was too slow.
164
- // if (typeof _debug_ !== 'undefined') { console.log('failed (slow): max iterations reached'); }
165
- return undefined;
166
- }
167
- }
168
-
169
- const circle = { center: x, radius: distanceBetween(x, z.p) };
170
-
171
- // if (typeof _debug_ !== 'undefined') { addDebugInfo(curvePieces, false, x, y, z, circle!, δ!, xs, isHoleClosing); }
172
-
173
- // return { circle, zs };
174
- // zs = zs.filter(z => z !== undefined)
175
- return { circle, zs: [z] };
45
+ meta: MatMeta,
46
+ isHoleClosing: boolean,
47
+ for1Prong: boolean,
48
+ angle: number,
49
+ y: PointOnShape): { circle: Circle, zs: PointOnShape[] } | undefined {
50
+
51
+ const { loops, maxCoordinate, squaredDiagonalLength } = meta;
52
+
53
+ const loop = y.curve.loop;
54
+
55
+ const MAX_ITERATIONS = 25;
56
+ const minSquaredSeperationTolerance = ((2**-21)*maxCoordinate)**2;
57
+ const errorTolerance = (2**-46)*maxCoordinate;
58
+ // const errorTolerance = (2**-28)*maxCoordinate;
59
+ const maxOsculatingCircleRadius = sqrt(squaredDiagonalLength);
60
+ const minCurvature = 1/maxOsculatingCircleRadius;
61
+ const oneProngTolerance = (2**-16)*maxCoordinate;
62
+
63
+ const [xO,rO] = getO(
64
+ angle, isHoleClosing, maxOsculatingCircleRadius, minCurvature, y
65
+ );
66
+
67
+ const p = y.p;
68
+
69
+ // The boundary piece that should contain the other point of
70
+ // the 2-prong circle. (Defined by start and end points).
71
+ let curvePieces = getInitialCurvePieces(
72
+ angle, isHoleClosing, loop, loops, meta, y, { center: xO, radius: rO }
73
+ );
74
+ // console.log(curvePieces.length);
75
+
76
+ /** The center of the two-prong (successively refined) */
77
+ let x = xO;
78
+
79
+ // The lines below is an optimization.
80
+ const r_ = sqrt(reduceRadius(maxCoordinate, curvePieces, p, xO));
81
+ if (rO > r_) {
82
+ x = interpolate(p, xO, r_/rO);
83
+ }
84
+
85
+ /** The antipode of the two-prong (successively refined) */
86
+ let zs: PointOnShape[] = undefined!;
87
+ let z: PointOnShape = undefined!;
88
+
89
+ let i = 0;
90
+ while (i < MAX_ITERATIONS) {
91
+ const xy = squaredDistanceBetweenDd(x, y.p);
92
+
93
+ if (i < 2) { curvePieces = cullCurvePieces2(curvePieces, x, xy); }
94
+ const pow = max(0,ceil(log2(maxCoordinate/xy))) + 1; // determines accuracy
95
+ // console.log(pow);
96
+ const _zs = getCloseBoundaryPointsCertified(
97
+ pow, curvePieces, x, y.curve, y.t,
98
+ for1Prong && i == 0 && rO !== 1/minCurvature,
99
+ angle
100
+ ).map(info => createPos(info.curve, info.t, false));
101
+
102
+ let maxD = Number.NEGATIVE_INFINITY;
103
+ let maxPos: PointOnShape = undefined!;
104
+ zs = [];
105
+ for (const z of _zs) {
106
+ if (z === undefined) { continue; }
107
+ const _yz = squaredDistanceBetweenDd(y.p, z.p);
108
+ if (_yz > maxD) {
109
+ maxD = _yz;
110
+ maxPos = z;
111
+ }
112
+ if (_yz !== 0) {
113
+ zs.push(z);
114
+ }
115
+ }
116
+ // z = zs[0];
117
+ const yz = maxD;
118
+ z = maxPos;
119
+
120
+ if (z === undefined || yz === 0) {
121
+ // addDebugInfo2(isHoleClosing);
122
+ return undefined;
123
+ }
124
+
125
+ const xz = squaredDistanceBetweenDd(x, z.p);
126
+
127
+ // if on first try
128
+ if (i === 0) {
129
+ if (rO < (1 - oneProngTolerance)*sqrt(xz)) {
130
+ // console.log('1prong');
131
+ add1Prong(meta, rO, xO, y);
132
+ return undefined;
133
+ }
134
+ }
135
+
136
+ // if (typeof _debug_ !== 'undefined') { xs.push({ x, y, z: createPos(z.curve, z.t, false), t: y.t }); }
137
+
138
+
139
+ if (!isHoleClosing) {
140
+ const squaredSeperationTolerance = max(calcSeperationTolerance(
141
+ rO, sqrt(xz), 2**2*errorTolerance
142
+ ), minSquaredSeperationTolerance);
143
+ if (yz <= squaredSeperationTolerance) {
144
+ // if (typeof _debug_ !== 'undefined') { console.log(`failed: seperation too small - ${sqrt(yz)}`); }
145
+ return undefined;
146
+ }
147
+ }
148
+
149
+ // Find the point on the line connecting y with x that is
150
+ // equidistant from y and z. This will be our next x.
151
+ const nextX = findEquidistantPointOnLineDd(x, y.p, z.p);
152
+ const error = abs(sqrt(xy) - sqrt(xz));
153
+ // if (xy < xz) { return undefined; }
154
+
155
+ x = nextX;
156
+
157
+ if (error < errorTolerance) {
158
+ break;
159
+ }
160
+
161
+ i++;
162
+
163
+ if (i === MAX_ITERATIONS) {
164
+ // Convergence was too slow.
165
+ // if (typeof _debug_ !== 'undefined') { console.log('failed (slow): max iterations reached'); }
166
+ return undefined;
167
+ }
168
+ }
169
+
170
+ const circle = { center: x, radius: distanceBetween(x, z.p) };
171
+
172
+ // if (typeof _debug_ !== 'undefined') { addDebugInfo(curvePieces, false, x, y, z, circle!, δ!, xs, isHoleClosing); }
173
+
174
+ // return { circle, zs };
175
+ // zs = zs.filter(z => z !== undefined)
176
+ return { circle, zs: [z] };
176
177
  }
177
178
 
178
179
 
179
180
  function getO(
180
- angle: number,
181
- isHoleClosing: boolean,
182
- maxOsculatingCircleRadius: number,
183
- minCurvature: number,
184
- y: PointOnShape) {
185
-
186
- let xO: number[]; // the original x to mitigate drift
187
- const p = y.p;
188
- let rO: number;
189
- if (isHoleClosing) {
190
- xO = [p[0], p[1] - maxOsculatingCircleRadius];
191
- rO = maxOsculatingCircleRadius;
192
- } else {
193
- if (angle === 0) {
194
- ({ center: xO, radius: rO } = getOsculatingCircle(minCurvature, y));
195
- } else {
196
- ({ center: xO, radius: rO } = getOsculatingCircle(minCurvature, y, true));
197
- const v = fromTo(y.p, xO);
198
- const v_ = rotate(sin(angle), cos(angle))(v);
199
- xO = translate(y.p)(v_);
200
- }
201
- }
202
-
203
- return [xO,rO] as [number[],number];
181
+ angle: number,
182
+ isHoleClosing: boolean,
183
+ maxOsculatingCircleRadius: number,
184
+ minCurvature: number,
185
+ y: PointOnShape) {
186
+
187
+ let xO: number[]; // the original x to mitigate drift
188
+ const p = y.p;
189
+ let rO: number;
190
+ if (isHoleClosing) {
191
+ xO = [p[0], p[1] - maxOsculatingCircleRadius];
192
+ rO = maxOsculatingCircleRadius;
193
+ } else {
194
+ if (angle === 0) {
195
+ ({ center: xO, radius: rO } = getOsculatingCircle(minCurvature, y));
196
+ } else {
197
+ ({ center: xO, radius: rO } = getOsculatingCircle(minCurvature, y, true));
198
+ const v = fromTo(y.p, xO);
199
+ const v_ = rotate(sin(angle), cos(angle))(v);
200
+ xO = translate(y.p)(v_);
201
+ }
202
+ }
203
+
204
+ return [xO,rO] as [number[],number];
204
205
  }
205
206
 
206
207
 
@@ -1,6 +1,6 @@
1
1
  import {
2
- twoDiff, twoSum, twoProduct, doubleDivDouble, ddDivDd,
3
- ddAddDd, ddDiffDd, ddMultDd, ddMultBy2, ddMultDouble1
2
+ twoDiff, twoSum, twoProduct, doubleDivDouble, ddDivDd,
3
+ ddAddDd, ddDiffDd, ddMultDd, ddMultBy2, ddMultDouble1
4
4
  } from "double-double";
5
5
 
6
6
 
@@ -20,57 +20,57 @@ const tp = twoProduct;
20
20
  * @param z
21
21
  */
22
22
  function findEquidistantPointOnLineDd(
23
- x: number[],
24
- y: number[],
25
- z: number[]) {
26
- // Some basic algebra (not shown) finds the required point.
27
-
28
- // Swap axes if x and y are more aligned to y-axis than to x-axis.
29
- const swapAxes = abs(x[1] - y[1]) > abs(x[0] - y[0]);
30
-
31
- // Cache
32
- let x1: number;
33
- let x2: number;
34
- let y1: number;
35
- let y2: number;
36
- let z1: number;
37
- let z2: number;
38
-
39
- if (swapAxes) {
40
- x1 = x[1]; x2 = x[0];
41
- y1 = y[1]; y2 = y[0];
42
- z1 = z[1]; z2 = z[0];
43
- } else {
44
- x1 = x[0]; x2 = x[1];
45
- y1 = y[0]; y2 = y[1];
46
- z1 = z[0]; z2 = z[1];
47
- }
48
-
49
- // a <= 1 (due to swapped axes)
50
- // const a = (x2 - y2) / (x1 - y1);
51
- // const b = y2 - a*y1;
52
- // const c = (y1*y1 + y2*y2 - z1*z1 - z2*z2) + 2*b*(z2 - y2);
53
- // const d = y1 - z1 + a*(y2 - z2);
54
- // const t1 = c/(2*d);
55
- // const t2 = a*t1 + b;
23
+ x: number[],
24
+ y: number[],
25
+ z: number[]) {
26
+ // Some basic algebra (not shown) finds the required point.
27
+
28
+ // Swap axes if x and y are more aligned to y-axis than to x-axis.
29
+ const swapAxes = abs(x[1] - y[1]) > abs(x[0] - y[0]);
30
+
31
+ // Cache
32
+ let x1: number;
33
+ let x2: number;
34
+ let y1: number;
35
+ let y2: number;
36
+ let z1: number;
37
+ let z2: number;
38
+
39
+ if (swapAxes) {
40
+ x1 = x[1]; x2 = x[0];
41
+ y1 = y[1]; y2 = y[0];
42
+ z1 = z[1]; z2 = z[0];
43
+ } else {
44
+ x1 = x[0]; x2 = x[1];
45
+ y1 = y[0]; y2 = y[1];
46
+ z1 = z[0]; z2 = z[1];
47
+ }
48
+
49
+ // a <= 1 (due to swapped axes)
50
+ // const a = (x2 - y2) / (x1 - y1);
51
+ // const b = y2 - a*y1;
52
+ // const c = (y1*y1 + y2*y2 - z1*z1 - z2*z2) + 2*b*(z2 - y2);
53
+ // const d = y1 - z1 + a*(y2 - z2);
54
+ // const t1 = c/(2*d);
55
+ // const t2 = a*t1 + b;
56
56
 
57
-
58
- const a = ddDivDd(td(x2,y2),td(x1,y1));
59
- const b = ddDiffDd([0,y2], ddMultDouble1(y1,a));
57
+
58
+ const a = ddDivDd(td(x2,y2),td(x1,y1));
59
+ const b = ddDiffDd([0,y2], ddMultDouble1(y1,a));
60
60
 
61
- const c = ddAddDd(
62
- (ddDiffDd(
63
- ddAddDd(tp(y1,y1), tp(y2,y2)),
64
- ddAddDd(tp(z1,z1), tp(z2,z2))
65
- )),
66
- ddMultBy2(ddMultDd(b,(td(z2,y2))))
67
- );
61
+ const c = ddAddDd(
62
+ (ddDiffDd(
63
+ ddAddDd(tp(y1,y1), tp(y2,y2)),
64
+ ddAddDd(tp(z1,z1), tp(z2,z2))
65
+ )),
66
+ ddMultBy2(ddMultDd(b,(td(z2,y2))))
67
+ );
68
68
 
69
- const d = ddAddDd(td(y1,z1), ddMultDd(a,td(y2,z2)));
70
- const t1 = ddDivDd(c,ddMultBy2(d));
71
- const t2 = ddAddDd(ddMultDd(a,t1), b);
72
-
73
- return swapAxes ? [t2[1],t1[1]] : [t1[1],t2[1]];
69
+ const d = ddAddDd(td(y1,z1), ddMultDd(a,td(y2,z2)));
70
+ const t1 = ddDivDd(c,ddMultBy2(d));
71
+ const t2 = ddAddDd(ddMultDd(a,t1), b);
72
+
73
+ return swapAxes ? [t2[1],t1[1]] : [t1[1],t2[1]];
74
74
  }
75
75
 
76
76
 
@@ -7,33 +7,33 @@
7
7
  * @returns The point on the line from y to x that is equidistant from y and z.
8
8
  */
9
9
  function findEquidistantPointOnLine(x: number[], y: number[], z: number[]) {
10
- // Some basic algebra (not shown) finds the required point.
11
-
12
- // Swap axes if x and y are more aligned to y-axis than to x-axis.
13
- const swapAxes = Math.abs((x[1] - y[1]) / (x[0] - y[0])) > 1;
14
-
15
- // Cache
16
- let x1, x2, y1, y2, z1, z2;
17
-
18
- if (swapAxes) {
19
- x1 = x[1]; x2 = x[0];
20
- y1 = y[1]; y2 = y[0];
21
- z1 = z[1]; z2 = z[0];
22
- } else {
23
- x1 = x[0]; x2 = x[1];
24
- y1 = y[0]; y2 = y[1];
25
- z1 = z[0]; z2 = z[1];
26
- }
27
-
28
- // a <= 1 (due to swapped axes)
29
- const a = (x2 - y2) / (x1 - y1);
30
- const b = y2 - a*y1;
31
- const c = (y1*y1 + y2*y2 - z1*z1 - z2*z2) + 2*b*(z2 - y2);
32
- const d = y1 - z1 + a*(y2 - z2);
33
- const t1 = c/(2*d);
34
- const t2 = a*t1 + b;
35
-
36
- return swapAxes ? [t2,t1] : [t1,t2];
10
+ // Some basic algebra (not shown) finds the required point.
11
+
12
+ // Swap axes if x and y are more aligned to y-axis than to x-axis.
13
+ const swapAxes = Math.abs((x[1] - y[1]) / (x[0] - y[0])) > 1;
14
+
15
+ // Cache
16
+ let x1, x2, y1, y2, z1, z2;
17
+
18
+ if (swapAxes) {
19
+ x1 = x[1]; x2 = x[0];
20
+ y1 = y[1]; y2 = y[0];
21
+ z1 = z[1]; z2 = z[0];
22
+ } else {
23
+ x1 = x[0]; x2 = x[1];
24
+ y1 = y[0]; y2 = y[1];
25
+ z1 = z[0]; z2 = z[1];
26
+ }
27
+
28
+ // a <= 1 (due to swapped axes)
29
+ const a = (x2 - y2) / (x1 - y1);
30
+ const b = y2 - a*y1;
31
+ const c = (y1*y1 + y2*y2 - z1*z1 - z2*z2) + 2*b*(z2 - y2);
32
+ const d = y1 - z1 + a*(y2 - z2);
33
+ const t1 = c/(2*d);
34
+ const t2 = a*t1 + b;
35
+
36
+ return swapAxes ? [t2,t1] : [t1,t2];
37
37
  }
38
38
 
39
39
 
@@ -164,7 +164,7 @@ function find3ProngForDelta3s(
164
164
  const cross_ = Math.abs( Math.asin( cross(v1, v2) ) );
165
165
 
166
166
  totalAngleError += cross_;
167
- }
167
+ }
168
168
  }
169
169
 
170
170
  //-------------------------------------------------------------------------
@@ -13,35 +13,35 @@ import { getBoundaryPieceBeziers } from '../mat/get-boundary-piece-beziers.js';
13
13
  * tolerances.
14
14
  */
15
15
  function find3Prong(
16
- δs: CpNode[][], extreme: number) {
16
+ δs: CpNode[][], extreme: number) {
17
17
 
18
- const curvePiecess = δs.map(getBoundaryPieceBeziers);
18
+ const curvePiecess = δs.map(getBoundaryPieceBeziers);
19
19
 
20
- // The best candidate amongst the different 'permutations' of the given δs.
21
- let threeProng: {
20
+ // The best candidate amongst the different 'permutations' of the given δs.
21
+ let threeProng: {
22
22
  circle: Circle,
23
23
  poss: PointOnShape[],
24
24
  δ3s: CpNode[][]
25
25
  };
26
- let smallestError = Number.POSITIVE_INFINITY;
27
- for (let i=1; i<δs.length-1; i++) {
28
- for (let k=0; k<3; k++) {
29
- const threeProngInfo =
30
- find3ProngForDelta3s(δs, i, k, curvePiecess, extreme);
31
- if (!threeProngInfo) { continue; }
32
-
33
- const { circle, poss: poss, error, δ3s } = threeProngInfo;
34
-
35
- if (error < smallestError) {
36
- smallestError = error;
37
-
38
- threeProng = { circle, poss: poss as PointOnShape[], δ3s };
39
- }
40
- }
41
- }
42
-
43
-
44
- return threeProng!;
26
+ let smallestError = Number.POSITIVE_INFINITY;
27
+ for (let i=1; i<δs.length-1; i++) {
28
+ for (let k=0; k<3; k++) {
29
+ const threeProngInfo =
30
+ find3ProngForDelta3s(δs, i, k, curvePiecess, extreme);
31
+ if (!threeProngInfo) { continue; }
32
+
33
+ const { circle, poss: poss, error, δ3s } = threeProngInfo;
34
+
35
+ if (error < smallestError) {
36
+ smallestError = error;
37
+
38
+ threeProng = { circle, poss: poss as PointOnShape[], δ3s };
39
+ }
40
+ }
41
+ }
42
+
43
+
44
+ return threeProng!;
45
45
  }
46
46
 
47
47
 
@@ -18,43 +18,43 @@ import { getProngCount } from '../cp-node/fs/get-prong-count.js';
18
18
  * tolerances.
19
19
  */
20
20
  function findAndAdd3Prong(
21
- meta: MatMeta,
22
- visitedCps: CpNode[]) {
23
-
24
- const δs: [CpNode, CpNode][] = [];
25
- for (const visitedCp of visitedCps) {
26
- δs.push([visitedCp, visitedCp.next]);
27
- }
28
-
29
- const threeProngInfo = find3Prong(δs, meta.maxCoordinate);
30
-
31
- const { circle, poss, δ3s } = threeProngInfo;
32
-
33
- const orders: number[] = [];
34
- for (let i=0; i<3; i++) {
35
- orders.push(calcPosOrder(circle, poss[i]));
36
- }
37
-
38
- const closeBysFor3Prong: CpNode[] = [];
39
- for (let i=0; i<poss.length; i++) {
40
- const pos = poss[i];
41
- const order = orders[i];
42
- const closeBy = getCloseByCpIfExist(meta, pos, circle, order, 0, 3);
43
- if (closeBy !== undefined) {
44
- const prongCount = getProngCount(closeBy);
45
- if (prongCount <= 2 && !closeBy.isHoleClosing) {
46
- closeBysFor3Prong.push(closeBy);
47
- }
48
- }
49
- }
50
-
51
- const cpNodes = closeBysFor3Prong.length === 0
52
- ? addToCpTree(
53
- true, false, circle, orders, meta, poss, δ3s.map(v => v[0])
54
- ).cpNodes
55
- : [];
56
-
57
- return { closeBysFor3Prong, cpNodes: cpNodes as CpNode[] };
21
+ meta: MatMeta,
22
+ visitedCps: CpNode[]) {
23
+
24
+ const δs: [CpNode, CpNode][] = [];
25
+ for (const visitedCp of visitedCps) {
26
+ δs.push([visitedCp, visitedCp.next]);
27
+ }
28
+
29
+ const threeProngInfo = find3Prong(δs, meta.maxCoordinate);
30
+
31
+ const { circle, poss, δ3s } = threeProngInfo;
32
+
33
+ const orders: number[] = [];
34
+ for (let i=0; i<3; i++) {
35
+ orders.push(calcPosOrder(circle, poss[i]));
36
+ }
37
+
38
+ const closeBysFor3Prong: CpNode[] = [];
39
+ for (let i=0; i<poss.length; i++) {
40
+ const pos = poss[i];
41
+ const order = orders[i];
42
+ const closeBy = getCloseByCpIfExist(meta, pos, circle, order, 0, 3);
43
+ if (closeBy !== undefined) {
44
+ const prongCount = getProngCount(closeBy);
45
+ if (prongCount <= 2 && !closeBy.isHoleClosing) {
46
+ closeBysFor3Prong.push(closeBy);
47
+ }
48
+ }
49
+ }
50
+
51
+ const cpNodes = closeBysFor3Prong.length === 0
52
+ ? addToCpTree(
53
+ true, false, circle, orders, meta, poss, δ3s.map(v => v[0])
54
+ ).cpNodes
55
+ : [];
56
+
57
+ return { closeBysFor3Prong, cpNodes: cpNodes as CpNode[] };
58
58
  }
59
59
 
60
60