@jscad/modeling 2.7.1 → 2.9.0

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 (194) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/jscad-modeling.min.js +174 -144
  3. package/package.json +2 -2
  4. package/src/colors/hslToRgb.js +1 -1
  5. package/src/colors/hueToColorComponent.js +1 -0
  6. package/src/curves/bezier/tangentAt.js +2 -2
  7. package/src/curves/bezier/tangentAt.test.js +1 -1
  8. package/src/curves/bezier/valueAt.test.js +1 -1
  9. package/src/geometries/geom2/index.js +10 -0
  10. package/src/geometries/geom2/isA.js +2 -2
  11. package/src/geometries/geom2/toCompactBinary.js +4 -4
  12. package/src/geometries/geom2/toOutlines.js +6 -11
  13. package/src/geometries/geom2/toString.js +1 -1
  14. package/src/geometries/geom2/transform.test.js +1 -1
  15. package/src/geometries/geom3/fromCompactBinary.js +1 -1
  16. package/src/geometries/geom3/index.js +17 -0
  17. package/src/geometries/geom3/invert.js +2 -2
  18. package/src/geometries/geom3/isA.js +2 -2
  19. package/src/geometries/geom3/toCompactBinary.js +4 -4
  20. package/src/geometries/geom3/toPoints.js +1 -0
  21. package/src/geometries/geom3/toString.js +1 -1
  22. package/src/geometries/geom3/transform.test.js +1 -1
  23. package/src/geometries/index.js +8 -1
  24. package/src/geometries/path2/eachPoint.js +3 -3
  25. package/src/geometries/path2/index.js +11 -0
  26. package/src/geometries/path2/isA.js +2 -2
  27. package/src/geometries/path2/reverse.js +4 -4
  28. package/src/geometries/path2/toCompactBinary.js +6 -6
  29. package/src/geometries/path2/toString.js +1 -1
  30. package/src/geometries/path2/transform.test.js +1 -1
  31. package/src/geometries/poly2/arePointsInside.test.js +1 -1
  32. package/src/geometries/poly2/index.js +6 -0
  33. package/src/geometries/poly3/index.js +7 -1
  34. package/src/geometries/poly3/invert.js +7 -1
  35. package/src/geometries/poly3/isA.js +2 -2
  36. package/src/geometries/poly3/isConvex.js +2 -2
  37. package/src/geometries/poly3/measureArea.js +4 -4
  38. package/src/geometries/poly3/measureBoundingBox.js +2 -2
  39. package/src/geometries/poly3/measureBoundingSphere.js +2 -2
  40. package/src/geometries/poly3/measureSignedVolume.js +4 -4
  41. package/src/geometries/poly3/toPoints.js +2 -2
  42. package/src/geometries/poly3/toString.js +2 -2
  43. package/src/geometries/poly3/transform.js +2 -2
  44. package/src/maths/index.js +1 -1
  45. package/src/maths/line2/equals.js +2 -2
  46. package/src/maths/line2/fromValues.js +2 -2
  47. package/src/maths/line2/intersectPointOfLines.js +1 -1
  48. package/src/maths/line2/intersectPointOfLines.test.js +1 -1
  49. package/src/maths/line2/reverse.test.js +1 -1
  50. package/src/maths/line2/transform.test.js +1 -1
  51. package/src/maths/line3/equals.js +2 -2
  52. package/src/maths/line3/reverse.test.js +1 -1
  53. package/src/maths/line3/transform.test.js +1 -1
  54. package/src/maths/mat4/fromRotation.js +1 -1
  55. package/src/maths/mat4/fromVectorRotation.js +1 -1
  56. package/src/maths/mat4/fromVectorRotation.test.js +1 -1
  57. package/src/maths/mat4/identity.test.js +1 -1
  58. package/src/maths/mat4/invert.js +18 -18
  59. package/src/maths/mat4/isIdentity.js +1 -1
  60. package/src/maths/mat4/isIdentity.test.js +0 -2
  61. package/src/maths/mat4/isMirroring.js +4 -4
  62. package/src/maths/mat4/isMirroring.test.js +1 -1
  63. package/src/maths/mat4/leftMultiplyVec3.js +2 -2
  64. package/src/maths/mat4/rotate.js +1 -1
  65. package/src/maths/mat4/toString.js +2 -2
  66. package/src/maths/mat4/translate.test.js +1 -1
  67. package/src/maths/plane/flip.test.js +1 -1
  68. package/src/maths/plane/fromPoints.d.ts +1 -1
  69. package/src/maths/plane/fromPoints.js +1 -3
  70. package/src/maths/plane/signedDistanceToPoint.js +1 -1
  71. package/src/maths/plane/transform.test.js +1 -1
  72. package/src/maths/utils/aboutEqualNormals.js +2 -2
  73. package/src/maths/vec2/abs.d.ts +1 -1
  74. package/src/maths/vec2/add.test.js +1 -1
  75. package/src/maths/vec2/angleDegrees.d.ts +1 -1
  76. package/src/maths/vec2/angleRadians.d.ts +1 -1
  77. package/src/maths/vec2/create.js +1 -1
  78. package/src/maths/vec2/cross.test.js +1 -1
  79. package/src/maths/vec2/divide.test.js +1 -1
  80. package/src/maths/vec2/fromAngleDegrees.js +1 -1
  81. package/src/maths/vec2/fromScalar.js +1 -1
  82. package/src/maths/vec2/length.d.ts +1 -1
  83. package/src/maths/vec2/length.js +1 -1
  84. package/src/maths/vec2/length.test.js +10 -0
  85. package/src/maths/vec2/lerp.test.js +1 -1
  86. package/src/maths/vec2/multiply.test.js +1 -1
  87. package/src/maths/vec2/negate.test.js +1 -1
  88. package/src/maths/vec2/normal.js +1 -1
  89. package/src/maths/vec2/normalize.d.ts +1 -1
  90. package/src/maths/vec2/normalize.test.js +1 -1
  91. package/src/maths/vec2/rotate.test.js +1 -1
  92. package/src/maths/vec2/squaredLength.d.ts +1 -1
  93. package/src/maths/vec2/squaredLength.js +3 -3
  94. package/src/maths/vec2/subtract.test.js +1 -1
  95. package/src/maths/vec2/toString.js +1 -1
  96. package/src/maths/vec2/transform.test.js +1 -1
  97. package/src/maths/vec3/abs.d.ts +1 -1
  98. package/src/maths/vec3/add.test.js +1 -1
  99. package/src/maths/vec3/angle.js +2 -2
  100. package/src/maths/vec3/angle.test.js +17 -0
  101. package/src/maths/vec3/cross.test.js +1 -1
  102. package/src/maths/vec3/divide.test.js +1 -1
  103. package/src/maths/vec3/fromScalar.js +1 -1
  104. package/src/maths/vec3/fromVec2.d.ts +1 -1
  105. package/src/maths/vec3/fromVec2.js +3 -3
  106. package/src/maths/vec3/length.d.ts +1 -1
  107. package/src/maths/vec3/length.js +4 -4
  108. package/src/maths/vec3/length.test.js +10 -0
  109. package/src/maths/vec3/lerp.test.js +1 -1
  110. package/src/maths/vec3/multiply.test.js +1 -1
  111. package/src/maths/vec3/negate.d.ts +1 -1
  112. package/src/maths/vec3/negate.test.js +1 -1
  113. package/src/maths/vec3/normalize.d.ts +1 -1
  114. package/src/maths/vec3/normalize.test.js +1 -1
  115. package/src/maths/vec3/rotateX.test.js +1 -1
  116. package/src/maths/vec3/rotateY.test.js +1 -1
  117. package/src/maths/vec3/rotateZ.test.js +1 -1
  118. package/src/maths/vec3/scale.test.js +1 -1
  119. package/src/maths/vec3/squaredLength.d.ts +1 -1
  120. package/src/maths/vec3/squaredLength.js +4 -4
  121. package/src/maths/vec3/subtract.test.js +1 -1
  122. package/src/maths/vec3/toString.js +1 -1
  123. package/src/maths/vec3/transform.test.js +1 -1
  124. package/src/maths/vec4/toString.js +1 -1
  125. package/src/maths/vec4/transform.test.js +1 -1
  126. package/src/measurements/measureBoundingSphere.js +4 -4
  127. package/src/measurements/measureCenterOfMass.js +1 -1
  128. package/src/operations/booleans/mayOverlap.js +3 -3
  129. package/src/operations/booleans/retessellate.js +3 -5
  130. package/src/operations/booleans/scission.js +1 -1
  131. package/src/operations/booleans/subtract.js +1 -1
  132. package/src/operations/booleans/union.test.js +1 -1
  133. package/src/operations/booleans/unionGeom3Sub.js +1 -1
  134. package/src/operations/expansions/expand.js +2 -2
  135. package/src/operations/expansions/expand.test.js +3 -35
  136. package/src/operations/expansions/expandShell.js +24 -18
  137. package/src/operations/expansions/offset.js +1 -1
  138. package/src/operations/expansions/offset.test.js +25 -89
  139. package/src/operations/expansions/offsetFromPoints.js +11 -6
  140. package/src/operations/extrusions/earcut/assignHoles.js +87 -0
  141. package/src/operations/extrusions/earcut/assignHoles.test.js +28 -0
  142. package/src/operations/extrusions/earcut/eliminateHoles.js +131 -0
  143. package/src/operations/extrusions/earcut/index.js +252 -0
  144. package/src/operations/extrusions/earcut/linkedList.js +58 -0
  145. package/src/operations/extrusions/earcut/linkedListSort.js +54 -0
  146. package/src/operations/extrusions/earcut/linkedPolygon.js +197 -0
  147. package/src/operations/extrusions/earcut/polygonHierarchy.js +64 -0
  148. package/src/operations/extrusions/earcut/triangle.js +16 -0
  149. package/src/operations/extrusions/extrudeFromSlices.js +10 -3
  150. package/src/operations/extrusions/extrudeFromSlices.test.js +33 -23
  151. package/src/operations/extrusions/extrudeLinear.js +11 -6
  152. package/src/operations/extrusions/extrudeLinear.test.js +77 -27
  153. package/src/operations/extrusions/extrudeLinearGeom2.js +5 -2
  154. package/src/operations/extrusions/extrudeLinearPath2.js +24 -0
  155. package/src/operations/extrusions/extrudeRectangular.js +1 -1
  156. package/src/operations/extrusions/extrudeRectangular.test.js +7 -7
  157. package/src/operations/extrusions/extrudeRotate.test.js +19 -27
  158. package/src/operations/extrusions/project.js +1 -1
  159. package/src/operations/extrusions/slice/calculatePlane.js +7 -4
  160. package/src/operations/extrusions/slice/isA.js +2 -2
  161. package/src/operations/extrusions/slice/repairSlice.js +47 -0
  162. package/src/operations/extrusions/slice/toPolygons.js +24 -60
  163. package/src/operations/hulls/hull.test.js +1 -1
  164. package/src/operations/hulls/hullChain.js +1 -1
  165. package/src/operations/hulls/hullGeom2.js +1 -1
  166. package/src/operations/hulls/hullPath2.js +6 -4
  167. package/src/operations/hulls/hullPath2.test.js +16 -0
  168. package/src/operations/hulls/hullPoints2.test.js +1 -1
  169. package/src/operations/hulls/quickhull/QuickHull.js +2 -2
  170. package/src/operations/modifiers/edges.js +2 -4
  171. package/src/operations/modifiers/generalize.js +4 -7
  172. package/src/operations/modifiers/snap.test.js +3 -3
  173. package/src/operations/transforms/align.d.ts +1 -1
  174. package/src/operations/transforms/center.js +17 -17
  175. package/src/operations/transforms/mirror.js +11 -11
  176. package/src/operations/transforms/rotate.js +12 -12
  177. package/src/operations/transforms/scale.js +19 -19
  178. package/src/operations/transforms/transform.js +3 -3
  179. package/src/operations/transforms/translate.js +14 -14
  180. package/src/primitives/arc.js +1 -1
  181. package/src/primitives/cylinderElliptic.test.js +0 -2
  182. package/src/primitives/ellipsoid.js +1 -1
  183. package/src/primitives/ellipsoid.test.js +0 -2
  184. package/src/primitives/geodesicSphere.d.ts +0 -1
  185. package/src/primitives/geodesicSphere.js +2 -2
  186. package/src/primitives/polyhedron.js +1 -1
  187. package/src/primitives/roundedCylinder.js +1 -1
  188. package/src/primitives/torus.d.ts +0 -1
  189. package/src/primitives/torus.test.js +1 -1
  190. package/src/primitives/triangle.js +1 -1
  191. package/src/text/vectorText.js +2 -2
  192. package/src/utils/padArrayToLength.js +1 -1
  193. package/test/helpers/comparePolygons.js +1 -3
  194. package/test/helpers/nearlyEqual.js +2 -6
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * @param {vec3} out - receiving vector
6
6
  * @param {Number} scalar
7
- * @returns {Vec3} out
7
+ * @returns {vec3} out
8
8
  * @alias module:modeling/maths/vec3.fromScalar
9
9
  */
10
10
  const fromScalar = (out, scalar) => {
@@ -3,4 +3,4 @@ import Vec2 from '../vec2/type'
3
3
 
4
4
  export default fromVector2
5
5
 
6
- declare function fromVector2(out: Vec3, vec2: Vec2, z?: number): Vec3
6
+ declare function fromVector2(out: Vec3, vector: Vec2, z?: number): Vec3
@@ -7,9 +7,9 @@
7
7
  * @returns {vec3} out
8
8
  * @alias module:modeling/maths/vec3.fromVec2
9
9
  */
10
- const fromVector2 = (out, vec2, z = 0) => {
11
- out[0] = vec2[0]
12
- out[1] = vec2[1]
10
+ const fromVector2 = (out, vector, z = 0) => {
11
+ out[0] = vector[0]
12
+ out[1] = vector[1]
13
13
  out[2] = z
14
14
  return out
15
15
  }
@@ -2,4 +2,4 @@ import Vec3 from './type'
2
2
 
3
3
  export default length
4
4
 
5
- declare function length(a: Vec3): number
5
+ declare function length(vector: Vec3): number
@@ -5,10 +5,10 @@
5
5
  * @returns {Number} length
6
6
  * @alias module:modeling/maths/vec3.length
7
7
  */
8
- const length = (a) => {
9
- const x = a[0]
10
- const y = a[1]
11
- const z = a[2]
8
+ const length = (vector) => {
9
+ const x = vector[0]
10
+ const y = vector[1]
11
+ const z = vector[2]
12
12
  return Math.hypot(x, y, z)
13
13
  }
14
14
 
@@ -41,5 +41,15 @@ test('vec3: length() should return correct values', (t) => {
41
41
  const length9 = length(vec9)
42
42
  nearlyEqual(t, length9, 3.74165, EPS)
43
43
 
44
+ // huge vector
45
+ const vec10 = fromValues(1e200, 0, 1e200)
46
+ const length10 = length(vec10)
47
+ nearlyEqual(t, length10, Math.SQRT2 * 1e200, EPS)
48
+
49
+ // tiny vector
50
+ const vec11 = fromValues(1e-200, 0, 1e-200)
51
+ const length11 = length(vec11)
52
+ nearlyEqual(t, length11, Math.SQRT2 * 1e-200, EPS)
53
+
44
54
  t.true(true)
45
55
  })
@@ -3,7 +3,7 @@ const { lerp, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: lerp() called with three paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: lerp() called with three parameters should update a vec3 with correct values', (t) => {
7
7
  const obs1 = fromValues(0, 0, 0)
8
8
  const ret1 = lerp(obs1, [0, 0, 0], [0, 0, 0], 0)
9
9
  t.true(compareVectors(obs1, [0, 0, 0]))
@@ -3,7 +3,7 @@ const { multiply, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: multiply() called with three paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: multiply() called with three parameters should update a vec3 with correct values', (t) => {
7
7
  const obs1 = fromValues(0, 0, 0)
8
8
  const ret1 = multiply(obs1, [0, 0, 0], [0, 0, 0])
9
9
  t.true(compareVectors(obs1, [0, 0, 0]))
@@ -2,4 +2,4 @@ import Vec3 from './type'
2
2
 
3
3
  export default negate
4
4
 
5
- declare function negate(out: Vec3, vec: Vec3): Vec3
5
+ declare function negate(out: Vec3, vector: Vec3): Vec3
@@ -3,7 +3,7 @@ const { negate, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: negate() called with two paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: negate() called with two parameters should update a vec3 with correct values', (t) => {
7
7
  const obs1 = fromValues(0, 0, 0)
8
8
  const ret1 = negate(obs1, [0, 0, 0])
9
9
  t.true(compareVectors(obs1, [-0, -0, -0]))
@@ -2,4 +2,4 @@ import Vec3 from './type'
2
2
 
3
3
  export default normalize
4
4
 
5
- declare function normalize(out: Vec3, vec: Vec3): Vec3
5
+ declare function normalize(out: Vec3, vector: Vec3): Vec3
@@ -3,7 +3,7 @@ const { normalize, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: normalize() called with two paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: normalize() called with two parameters should update a vec3 with correct values', (t) => {
7
7
  const obs1 = fromValues(0, 0, 0)
8
8
  const ret1 = normalize(obs1, [0, 0, 0])
9
9
  t.true(compareVectors(obs1, [0, 0, 0]))
@@ -3,7 +3,7 @@ const { rotateX, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: rotateX() called with four paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: rotateX() called with four parameters should update a vec3 with correct values', (t) => {
7
7
  const radians = 90 * Math.PI / 180
8
8
 
9
9
  const obs1 = fromValues(0, 0, 0)
@@ -3,7 +3,7 @@ const { rotateY, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: rotateY() called with three paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: rotateY() called with three parameters should update a vec3 with correct values', (t) => {
7
7
  const radians = 90 * Math.PI / 180
8
8
 
9
9
  const obs1 = fromValues(0, 0, 0)
@@ -3,7 +3,7 @@ const { rotateZ, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: rotateZ() called with four paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: rotateZ() called with four parameters should update a vec3 with correct values', (t) => {
7
7
  const radians = 90 * Math.PI / 180
8
8
 
9
9
  const obs1 = fromValues(0, 0, 0)
@@ -3,7 +3,7 @@ const { scale, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: scale() called with three paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: scale() called with three parameters should update a vec3 with correct values', (t) => {
7
7
  const obs1 = fromValues(0, 0, 0)
8
8
  const ret1 = scale(obs1, [0, 0, 0], 0)
9
9
  t.true(compareVectors(obs1, [0, 0, 0]))
@@ -2,4 +2,4 @@ import Vec3 from './type'
2
2
 
3
3
  export default squaredLength
4
4
 
5
- declare function squaredLength(vec: Vec3): number
5
+ declare function squaredLength(vector: Vec3): number
@@ -5,10 +5,10 @@
5
5
  * @returns {Number} squared length
6
6
  * @alias module:modeling/maths/vec3.squaredLength
7
7
  */
8
- const squaredLength = (a) => {
9
- const x = a[0]
10
- const y = a[1]
11
- const z = a[2]
8
+ const squaredLength = (vector) => {
9
+ const x = vector[0]
10
+ const y = vector[1]
11
+ const z = vector[2]
12
12
  return x * x + y * y + z * z
13
13
  }
14
14
 
@@ -3,7 +3,7 @@ const { subtract, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: subtract() called with three paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: subtract() called with three parameters should update a vec3 with correct values', (t) => {
7
7
  const obs1 = fromValues(0, 0, 0)
8
8
  const ret1 = subtract(obs1, [0, 0, 0], [0, 0, 0])
9
9
  t.true(compareVectors(obs1, [0, 0, 0]))
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Convert the given vector to a representative string.
3
- * @param {vec3} vector - vector of reference
3
+ * @param {vec3} vec - vector of reference
4
4
  * @returns {String} string representation
5
5
  * @alias module:modeling/maths/vec3.toString
6
6
  */
@@ -3,7 +3,7 @@ const { transform, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec3: transform() called with three paramerters should update a vec3 with correct values', (t) => {
6
+ test('vec3: transform() called with three parameters should update a vec3 with correct values', (t) => {
7
7
  const identityMatrix = [
8
8
  1, 0, 0, 0,
9
9
  0, 1, 0, 0,
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Convert the given vector to a representative string.
3
3
  *
4
- * @param {vec4} vector - vector to convert
4
+ * @param {vec4} vec - vector to convert
5
5
  * @returns {String} representative string
6
6
  * @alias module:modeling/maths/vec4.toString
7
7
  */
@@ -3,7 +3,7 @@ const { transform, fromValues } = require('./index')
3
3
 
4
4
  const { compareVectors } = require('../../../test/helpers/index')
5
5
 
6
- test('vec4: transform() called with three paramerters should update a vec4 with correct values', (t) => {
6
+ test('vec4: transform() called with three parameters should update a vec4 with correct values', (t) => {
7
7
  const identityMatrix = [
8
8
  1, 0, 0, 0,
9
9
  0, 1, 0, 0,
@@ -24,7 +24,7 @@ const measureBoundingSphereOfPath2 = (geometry) => {
24
24
  const points = path2.toPoints(geometry)
25
25
 
26
26
  if (points.length > 0) {
27
- // calculate the centriod of the geometry
27
+ // calculate the centroid of the geometry
28
28
  let numPoints = 0
29
29
  const temp = vec3.create()
30
30
  points.forEach((point) => {
@@ -60,7 +60,7 @@ const measureBoundingSphereOfGeom2 = (geometry) => {
60
60
  const sides = geom2.toSides(geometry)
61
61
 
62
62
  if (sides.length > 0) {
63
- // calculate the centriod of the geometry
63
+ // calculate the centroid of the geometry
64
64
  let numPoints = 0
65
65
  const temp = vec3.create()
66
66
  sides.forEach((side) => {
@@ -96,7 +96,7 @@ const measureBoundingSphereOfGeom3 = (geometry) => {
96
96
  const polygons = geom3.toPolygons(geometry)
97
97
 
98
98
  if (polygons.length > 0) {
99
- // calculate the centriod of the geometry
99
+ // calculate the centroid of the geometry
100
100
  let numPoints = 0
101
101
  polygons.forEach((polygon) => {
102
102
  poly3.toPoints(polygon).forEach((point) => {
@@ -122,7 +122,7 @@ const measureBoundingSphereOfGeom3 = (geometry) => {
122
122
  }
123
123
 
124
124
  /**
125
- * Measure the (aproximate) bounding sphere of the given geometries.
125
+ * Measure the (approximate) bounding sphere of the given geometries.
126
126
  * @see https://en.wikipedia.org/wiki/Bounding_sphere
127
127
  * @param {...Object} geometries - the geometries to measure
128
128
  * @return {Array} the bounding sphere for each geometry, i.e. [centroid, radius]
@@ -61,7 +61,7 @@ const measureCenterOfMassGeom3 = (geometry) => {
61
61
  let totalVolume = 0
62
62
  const vector = vec3.create() // for speed
63
63
  polygons.forEach((polygon) => {
64
- // calculate volume and center of each tetrahedon
64
+ // calculate volume and center of each tetrahedron
65
65
  const vertices = polygon.vertices
66
66
  for (let i = 0; i < vertices.length - 2; i++) {
67
67
  vec3.cross(vector, vertices[i + 1], vertices[i + 2])
@@ -4,9 +4,9 @@ const measureBoundingBox = require('../../measurements/measureBoundingBox')
4
4
 
5
5
  /*
6
6
  * Determine if the given geometries overlap by comparing min and max bounds.
7
- * NOTE: This is used in union for performace gains.
8
- * @param {geom3} geometry1 - geometry for comparision
9
- * @param {geom3} geometry2 - geometry for comparision
7
+ * NOTE: This is used in union for performance gains.
8
+ * @param {geom3} geometry1 - geometry for comparison
9
+ * @param {geom3} geometry2 - geometry for comparison
10
10
  * @returns {boolean} true if the geometries overlap
11
11
  */
12
12
  const mayOverlap = (geometry1, geometry2) => {
@@ -3,16 +3,14 @@ const poly3 = require('../../geometries/poly3')
3
3
 
4
4
  const reTesselateCoplanarPolygons = require('./reTesselateCoplanarPolygons')
5
5
 
6
- // Normals are directional vectors with component values from 0 to 1.0, requiring specialized comparision
7
- // This EPS is derived from a serieas of tests to determine the optimal precision for comparing coplanar polygons,
6
+ // Normals are directional vectors with component values from 0 to 1.0, requiring specialized comparison
7
+ // This EPS is derived from a series of tests to determine the optimal precision for comparing coplanar polygons,
8
8
  // as provided by the sphere primitive at high segmentation
9
9
  // This EPS is for 64 bit Number values
10
10
  const NEPS = 1e-13
11
11
 
12
12
  // Compare two normals (unit vectors) for equality.
13
- const aboutEqualNormals = (a, b) => {
14
- return (Math.abs(a[0] - b[0]) <= NEPS && Math.abs(a[1] - b[1]) <= NEPS && Math.abs(a[2] - b[2]) <= NEPS)
15
- }
13
+ const aboutEqualNormals = (a, b) => (Math.abs(a[0] - b[0]) <= NEPS && Math.abs(a[1] - b[1]) <= NEPS && Math.abs(a[2] - b[2]) <= NEPS)
16
14
 
17
15
  const coplanar = (plane1, plane2) => {
18
16
  // expect the same distance from the origin, within tolerance
@@ -9,7 +9,7 @@ const scissionGeom3 = require('./scissionGeom3')
9
9
  /**
10
10
  * Scission (divide) the given geometry into the component pieces.
11
11
  *
12
- * @param {...Object} geometries - list of geometries
12
+ * @param {...Object} objects - list of geometries
13
13
  * @returns {Array} list of pieces from each geometry
14
14
  * @alias module:modeling/booleans.scission
15
15
  *
@@ -17,7 +17,7 @@ const subtractGeom3 = require('./subtractGeom3')
17
17
  * @alias module:modeling/booleans.subtract
18
18
  *
19
19
  * @example
20
- * let myshape = subtract(cubiod({size: [5,5,5]}), cubiod({size: [5,5,5], center: [5,5,5]}))
20
+ * let myshape = subtract(cuboid({size: [5,5,5]}), cuboid({size: [5,5,5], center: [5,5,5]}))
21
21
  *
22
22
  * @example
23
23
  * +-------+ +-------+
@@ -198,7 +198,7 @@ test('union of one or more geom3 objects produces expected geometry', (t) => {
198
198
 
199
199
  test('union of geom3 with rounding issues #137', (t) => {
200
200
  const geometry1 = center({ relativeTo: [0, 0, -1] }, cuboid({ size: [44, 26, 5] }))
201
- const geometry2 = center({ relativeTo: [0, 0, -4.400001] }, cuboid({ size: [44, 26, 1.8] })) // introduce percision error
201
+ const geometry2 = center({ relativeTo: [0, 0, -4.400001] }, cuboid({ size: [44, 26, 1.8] })) // introduce precision error
202
202
 
203
203
  const obs = union(geometry1, geometry2)
204
204
  const pts = geom3.toPoints(obs)
@@ -7,7 +7,7 @@ const { Tree } = require('./trees')
7
7
  * Return a new 3D geometry representing the space in the given geometries.
8
8
  * @param {geom3} geometry1 - geometry to union
9
9
  * @param {geom3} geometry2 - geometry to union
10
- * @returns {goem3} new 3D geometry
10
+ * @returns {geom3} new 3D geometry
11
11
  */
12
12
  const unionSub = (geometry1, geometry2) => {
13
13
  if (!mayOverlap(geometry1, geometry2)) {
@@ -10,14 +10,14 @@ const expandPath2 = require('./expandPath2')
10
10
 
11
11
  /**
12
12
  * Expand the given geometry using the given options.
13
- * Both interal and external space is expanded for 2D and 3D shapes.
13
+ * Both internal and external space is expanded for 2D and 3D shapes.
14
14
  *
15
15
  * Note: Contract is expand using a negative delta.
16
16
  * @param {Object} options - options for expand
17
17
  * @param {Number} [options.delta=1] - delta (+/-) of expansion
18
18
  * @param {String} [options.corners='edge'] - type of corner to create after expanding; edge, chamfer, round
19
19
  * @param {Integer} [options.segments=16] - number of segments when creating round corners
20
- * @param {...Objects} geometry - the list of geometry to expand
20
+ * @param {...Objects} objects - the geometries to expand
21
21
  * @return {Object|Array} new geometry, or list of new geometries
22
22
  * @alias module:modeling/expansions.expand
23
23
  *
@@ -120,7 +120,7 @@ test('expand: expanding of a geom3 produces expected changes to polygons', (t) =
120
120
  const geometry2 = sphere({ radius: 5, segments: 8 })
121
121
  const obs2 = expand({ delta: 5 }, geometry2)
122
122
  const pts2 = geom3.toPoints(obs2)
123
- t.is(pts2.length, 2065)
123
+ t.is(pts2.length, 1588)
124
124
  })
125
125
 
126
126
  test('expand (options): offsetting of a complex geom2 produces expected offset geom2', (t) => {
@@ -151,59 +151,27 @@ test('expand (options): offsetting of a complex geom2 produces expected offset g
151
151
  const obs = expand({ delta: 2, corners: 'edge' }, geometry)
152
152
  const pts = geom2.toPoints(obs)
153
153
  const exp = [
154
- [-77, -77],
155
- [-75, -77],
156
- [75, -77],
157
154
  [77, -77],
158
- [77, -75],
159
- [77, 75],
160
155
  [77, 77],
161
- [75, 77],
162
- [40, 77],
163
156
  [38, 77],
164
- [38, 75],
165
157
  [38, 2],
166
158
  [-38, 2],
167
- [-38, 75],
168
159
  [-37.99999999999999, 77],
169
- [-40, 77],
170
- [-75, 77],
171
160
  [-77, 77],
172
- [-77, 75],
173
- [17, -40],
174
161
  [16.999999999999996, -42],
175
- [15, -42],
176
- [8, -42],
177
162
  [6, -42],
178
- [6, -40],
179
163
  [6, -27],
180
164
  [-6, -27],
181
- [-6, -40],
182
165
  [-6.000000000000001, -42],
183
- [-8, -42],
184
- [-15, -42],
185
166
  [-17, -42],
186
- [-17, -40],
187
- [-17, -10],
188
167
  [-16.999999999999996, -8],
189
- [-15, -8],
190
- [15, -8],
191
168
  [17, -8.000000000000004],
192
- [17, -10],
193
- [-4, -19],
194
169
  [-4, -21],
195
- [-2, -21],
196
- [1.9999999999999998, -21],
197
170
  [3.9999999999999996, -21],
198
- [4, -19],
199
- [4, -15],
200
171
  [4, -13],
201
- [2, -13],
202
- [-1.9999999999999998, -13],
203
172
  [-4, -13],
204
- [-4, -15],
205
- [-77, -75]
173
+ [-77, -77]
206
174
  ]
207
- t.is(pts.length, 52)
175
+ t.is(pts.length, 20)
208
176
  t.true(comparePoints(pts, exp))
209
177
  })
@@ -15,37 +15,43 @@ const unionGeom3Sub = require('../booleans/unionGeom3Sub')
15
15
 
16
16
  const extrudePolygon = require('./extrudePolygon')
17
17
 
18
+ /*
19
+ * Collect all planes adjacent to each vertex
20
+ */
18
21
  const mapPlaneToVertex = (map, vertex, plane) => {
19
- const i = map.findIndex((item) => vec3.equals(item[0], vertex))
20
- if (i < 0) {
22
+ const key = vertex.toString()
23
+ if (!map.has(key)) {
21
24
  const entry = [vertex, [plane]]
22
- map.push(entry)
23
- return map.length
25
+ map.set(key, entry)
26
+ } else {
27
+ const planes = map.get(key)[1]
28
+ planes.push(plane)
24
29
  }
25
- const planes = map[i][1]
26
- planes.push(plane)
27
- return i
28
30
  }
29
31
 
32
+ /*
33
+ * Collect all planes adjacent to each edge.
34
+ * Combine undirected edges, no need for duplicate cylinders.
35
+ */
30
36
  const mapPlaneToEdge = (map, edge, plane) => {
31
- const i = map.findIndex((item) => (vec3.equals(item[0], edge[0]) && vec3.equals(item[1], edge[1])) || (vec3.equals(item[0], edge[1]) && vec3.equals(item[1], edge[0])))
32
- if (i < 0) {
37
+ const key0 = edge[0].toString()
38
+ const key1 = edge[1].toString()
39
+ // Sort keys to make edges undirected
40
+ const key = key0 < key1 ? `${key0},${key1}` : `${key1},${key0}`
41
+ if (!map.has(key)) {
33
42
  const entry = [edge, [plane]]
34
- map.push(entry)
35
- return map.length
43
+ map.set(key, entry)
44
+ } else {
45
+ const planes = map.get(key)[1]
46
+ planes.push(plane)
36
47
  }
37
- const planes = map[i][1]
38
- planes.push(plane)
39
- return i
40
48
  }
41
49
 
42
50
  const addUniqueAngle = (map, angle) => {
43
51
  const i = map.findIndex((item) => item === angle)
44
52
  if (i < 0) {
45
53
  map.push(angle)
46
- return map.length
47
54
  }
48
- return i
49
55
  }
50
56
 
51
57
  /*
@@ -65,8 +71,8 @@ const expandShell = (options, geometry) => {
65
71
  const { delta, segments } = Object.assign({ }, defaults, options)
66
72
 
67
73
  let result = geom3.create()
68
- const vertices2planes = [] // contents: [vertex, [plane, ...]]
69
- const edges2planes = [] // contents: [[vertex, vertex], [plane, ...]]
74
+ const vertices2planes = new Map() // {vertex: [vertex, [plane, ...]]}
75
+ const edges2planes = new Map() // {edge: [[vertex, vertex], [plane, ...]]}
70
76
 
71
77
  const v1 = vec3.create()
72
78
  const v2 = vec3.create()
@@ -13,7 +13,7 @@ const offsetPath2 = require('./offsetPath2')
13
13
  * @param {Float} [options.delta=1] - delta of offset (+ to exterior, - from interior)
14
14
  * @param {String} [options.corners='edge'] - type of corner to create after offseting; edge, chamfer, round
15
15
  * @param {Integer} [options.segments=16] - number of segments when creating round corners
16
- * @param {...Object} geometry - the list of geometry to offset
16
+ * @param {...Object} objects - the geometries to offset
17
17
  * @return {Object|Array} new geometry, or list of new geometries
18
18
  * @alias module:modeling/expansions.offset
19
19
  *