@jscad/modeling 2.7.0 → 2.8.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.
- package/CHANGELOG.md +46 -0
- package/dist/jscad-modeling.min.js +142 -139
- package/package.json +2 -2
- package/src/colors/hslToRgb.js +1 -1
- package/src/colors/hueToColorComponent.js +1 -0
- package/src/curves/bezier/create.js +3 -8
- package/src/curves/bezier/tangentAt.js +2 -2
- package/src/curves/bezier/tangentAt.test.js +1 -1
- package/src/curves/bezier/valueAt.test.js +1 -1
- package/src/curves/index.js +1 -1
- package/src/geometries/geom2/index.js +10 -0
- package/src/geometries/geom2/isA.js +2 -2
- package/src/geometries/geom2/toCompactBinary.js +4 -4
- package/src/geometries/geom2/toOutlines.js +6 -11
- package/src/geometries/geom2/toString.js +1 -1
- package/src/geometries/geom2/transform.test.js +1 -1
- package/src/geometries/geom3/create.js +1 -1
- package/src/geometries/geom3/fromCompactBinary.js +1 -1
- package/src/geometries/geom3/index.js +17 -0
- package/src/geometries/geom3/invert.js +2 -2
- package/src/geometries/geom3/isA.js +2 -2
- package/src/geometries/geom3/toCompactBinary.js +4 -4
- package/src/geometries/geom3/toPoints.js +1 -0
- package/src/geometries/geom3/toString.js +1 -1
- package/src/geometries/geom3/transform.test.js +1 -1
- package/src/geometries/index.js +8 -1
- package/src/geometries/path2/eachPoint.js +3 -3
- package/src/geometries/path2/index.js +11 -0
- package/src/geometries/path2/isA.js +2 -2
- package/src/geometries/path2/reverse.js +4 -4
- package/src/geometries/path2/toCompactBinary.js +6 -6
- package/src/geometries/path2/toString.js +1 -1
- package/src/geometries/path2/transform.test.js +1 -1
- package/src/geometries/poly2/arePointsInside.test.js +1 -1
- package/src/geometries/poly2/index.js +6 -0
- package/src/geometries/poly3/index.js +7 -1
- package/src/geometries/poly3/isA.js +2 -2
- package/src/geometries/poly3/isConvex.js +2 -2
- package/src/geometries/poly3/measureArea.js +4 -4
- package/src/geometries/poly3/measureBoundingBox.js +2 -2
- package/src/geometries/poly3/measureBoundingSphere.js +2 -2
- package/src/geometries/poly3/measureSignedVolume.js +4 -4
- package/src/geometries/poly3/toPoints.js +2 -2
- package/src/geometries/poly3/toString.js +2 -2
- package/src/geometries/poly3/transform.js +2 -2
- package/src/maths/index.js +1 -1
- package/src/maths/line2/equals.js +2 -2
- package/src/maths/line2/fromValues.js +2 -2
- package/src/maths/line2/intersectPointOfLines.js +1 -1
- package/src/maths/line2/intersectPointOfLines.test.js +1 -1
- package/src/maths/line2/reverse.test.js +1 -1
- package/src/maths/line2/transform.test.js +1 -1
- package/src/maths/line3/create.js +2 -1
- package/src/maths/line3/equals.js +2 -2
- package/src/maths/line3/reverse.test.js +1 -1
- package/src/maths/line3/transform.test.js +1 -1
- package/src/maths/mat4/fromRotation.js +1 -1
- package/src/maths/mat4/fromVectorRotation.js +1 -1
- package/src/maths/mat4/fromVectorRotation.test.js +1 -1
- package/src/maths/mat4/identity.test.js +1 -1
- package/src/maths/mat4/invert.js +18 -18
- package/src/maths/mat4/isIdentity.js +1 -1
- package/src/maths/mat4/isIdentity.test.js +0 -2
- package/src/maths/mat4/isMirroring.js +4 -4
- package/src/maths/mat4/isMirroring.test.js +1 -1
- package/src/maths/mat4/isOnlyTransformScale.js +5 -4
- package/src/maths/mat4/leftMultiplyVec3.js +2 -2
- package/src/maths/mat4/rotate.js +1 -1
- package/src/maths/mat4/toString.js +2 -2
- package/src/maths/mat4/translate.test.js +1 -1
- package/src/maths/plane/flip.test.js +1 -1
- package/src/maths/plane/fromPoints.d.ts +1 -1
- package/src/maths/plane/fromPoints.js +1 -3
- package/src/maths/plane/signedDistanceToPoint.js +1 -1
- package/src/maths/plane/transform.test.js +1 -1
- package/src/maths/utils/aboutEqualNormals.js +2 -2
- package/src/maths/vec2/abs.d.ts +1 -1
- package/src/maths/vec2/add.test.js +1 -1
- package/src/maths/vec2/angleDegrees.d.ts +1 -1
- package/src/maths/vec2/angleRadians.d.ts +1 -1
- package/src/maths/vec2/create.js +1 -1
- package/src/maths/vec2/cross.test.js +1 -1
- package/src/maths/vec2/divide.test.js +1 -1
- package/src/maths/vec2/fromAngleDegrees.js +1 -1
- package/src/maths/vec2/fromScalar.js +1 -1
- package/src/maths/vec2/length.d.ts +1 -1
- package/src/maths/vec2/length.js +1 -1
- package/src/maths/vec2/length.test.js +10 -0
- package/src/maths/vec2/lerp.test.js +1 -1
- package/src/maths/vec2/multiply.test.js +1 -1
- package/src/maths/vec2/negate.test.js +1 -1
- package/src/maths/vec2/normal.js +1 -1
- package/src/maths/vec2/normalize.d.ts +1 -1
- package/src/maths/vec2/normalize.test.js +1 -1
- package/src/maths/vec2/rotate.test.js +1 -1
- package/src/maths/vec2/squaredLength.d.ts +1 -1
- package/src/maths/vec2/squaredLength.js +3 -3
- package/src/maths/vec2/subtract.test.js +1 -1
- package/src/maths/vec2/toString.js +1 -1
- package/src/maths/vec2/transform.test.js +1 -1
- package/src/maths/vec3/abs.d.ts +1 -1
- package/src/maths/vec3/add.test.js +1 -1
- package/src/maths/vec3/angle.js +2 -2
- package/src/maths/vec3/angle.test.js +17 -0
- package/src/maths/vec3/cross.test.js +1 -1
- package/src/maths/vec3/divide.test.js +1 -1
- package/src/maths/vec3/fromScalar.js +1 -1
- package/src/maths/vec3/fromVec2.d.ts +1 -1
- package/src/maths/vec3/fromVec2.js +3 -3
- package/src/maths/vec3/length.d.ts +1 -1
- package/src/maths/vec3/length.js +4 -4
- package/src/maths/vec3/length.test.js +10 -0
- package/src/maths/vec3/lerp.test.js +1 -1
- package/src/maths/vec3/multiply.test.js +1 -1
- package/src/maths/vec3/negate.d.ts +1 -1
- package/src/maths/vec3/negate.test.js +1 -1
- package/src/maths/vec3/normalize.d.ts +1 -1
- package/src/maths/vec3/normalize.test.js +1 -1
- package/src/maths/vec3/rotateX.test.js +1 -1
- package/src/maths/vec3/rotateY.test.js +1 -1
- package/src/maths/vec3/rotateZ.test.js +1 -1
- package/src/maths/vec3/scale.test.js +1 -1
- package/src/maths/vec3/squaredLength.d.ts +1 -1
- package/src/maths/vec3/squaredLength.js +4 -4
- package/src/maths/vec3/subtract.test.js +1 -1
- package/src/maths/vec3/toString.js +1 -1
- package/src/maths/vec3/transform.test.js +1 -1
- package/src/maths/vec4/toString.js +1 -1
- package/src/maths/vec4/transform.test.js +1 -1
- package/src/measurements/measureBoundingBox.js +38 -128
- package/src/measurements/measureBoundingSphere.js +4 -4
- package/src/measurements/measureCenterOfMass.js +1 -1
- package/src/operations/booleans/mayOverlap.js +3 -3
- package/src/operations/booleans/retessellate.js +3 -5
- package/src/operations/booleans/scission.js +1 -1
- package/src/operations/booleans/subtract.js +1 -1
- package/src/operations/booleans/union.test.js +1 -1
- package/src/operations/booleans/unionGeom3Sub.js +1 -1
- package/src/operations/expansions/expand.js +3 -1
- package/src/operations/expansions/expand.test.js +3 -35
- package/src/operations/expansions/expandShell.js +24 -18
- package/src/operations/expansions/offset.js +2 -1
- package/src/operations/expansions/offset.test.js +25 -89
- package/src/operations/expansions/offsetFromPoints.js +11 -6
- package/src/operations/extrusions/extrudeLinear.js +7 -3
- package/src/operations/extrusions/extrudeLinear.test.js +25 -1
- package/src/operations/extrusions/extrudeLinearPath2.js +24 -0
- package/src/operations/extrusions/extrudeRectangular.js +3 -2
- package/src/operations/extrusions/extrudeRectangular.test.js +2 -2
- package/src/operations/extrusions/project.js +1 -1
- package/src/operations/extrusions/slice/isA.js +2 -2
- package/src/operations/extrusions/slice/toPolygons.js +1 -1
- package/src/operations/hulls/hull.test.js +1 -1
- package/src/operations/hulls/hullChain.js +1 -1
- package/src/operations/hulls/hullGeom2.js +1 -1
- package/src/operations/hulls/hullPath2.js +6 -4
- package/src/operations/hulls/hullPath2.test.js +16 -0
- package/src/operations/hulls/hullPoints2.test.js +1 -1
- package/src/operations/hulls/quickhull/QuickHull.js +2 -2
- package/src/operations/modifiers/edges.js +2 -4
- package/src/operations/modifiers/generalize.js +4 -7
- package/src/operations/modifiers/snap.test.js +3 -3
- package/src/operations/transforms/align.d.ts +1 -1
- package/src/operations/transforms/center.js +17 -17
- package/src/operations/transforms/mirror.js +11 -11
- package/src/operations/transforms/rotate.js +12 -12
- package/src/operations/transforms/scale.js +19 -19
- package/src/operations/transforms/transform.js +3 -3
- package/src/operations/transforms/translate.js +14 -14
- package/src/primitives/arc.js +1 -1
- package/src/primitives/cylinderElliptic.test.js +0 -2
- package/src/primitives/ellipse.js +1 -1
- package/src/primitives/ellipsoid.js +1 -1
- package/src/primitives/ellipsoid.test.js +0 -2
- package/src/primitives/geodesicSphere.d.ts +0 -1
- package/src/primitives/geodesicSphere.js +2 -2
- package/src/primitives/polyhedron.js +1 -1
- package/src/primitives/roundedCylinder.js +1 -1
- package/src/primitives/torus.d.ts +0 -1
- package/src/primitives/triangle.js +2 -2
- package/src/text/vectorText.js +2 -2
- package/src/utils/insertSorted.js +1 -0
- package/src/utils/padArrayToLength.js +1 -1
- package/test/helpers/comparePolygons.js +1 -3
- package/test/helpers/nearlyEqual.js +2 -6
package/src/maths/vec3/angle.js
CHANGED
|
@@ -15,8 +15,8 @@ const angle = (a, b) => {
|
|
|
15
15
|
const bx = b[0]
|
|
16
16
|
const by = b[1]
|
|
17
17
|
const bz = b[2]
|
|
18
|
-
const mag1 = Math.
|
|
19
|
-
const mag2 = Math.
|
|
18
|
+
const mag1 = Math.hypot(ax, ay, az)
|
|
19
|
+
const mag2 = Math.hypot(bx, by, bz)
|
|
20
20
|
const mag = mag1 * mag2
|
|
21
21
|
const cosine = mag && dot(a, b) / mag
|
|
22
22
|
return Math.acos(Math.min(Math.max(cosine, -1), 1))
|
|
@@ -25,5 +25,22 @@ test('vec3: angle() should return correct values', (t) => {
|
|
|
25
25
|
const angle4 = angle(veca4, vec4)
|
|
26
26
|
nearlyEqual(t, angle4, 3.14159, EPS)
|
|
27
27
|
|
|
28
|
+
const vec5a = fromValues(1, 0, 0)
|
|
29
|
+
const vec5b = fromValues(1, 1, 0)
|
|
30
|
+
const angle5 = angle(vec5a, vec5b)
|
|
31
|
+
nearlyEqual(t, angle5, 0.785398, EPS)
|
|
32
|
+
|
|
33
|
+
// tiny values
|
|
34
|
+
const vec6a = fromValues(1, 0, 0)
|
|
35
|
+
const vec6b = fromValues(1e-200, 1e-200, 0)
|
|
36
|
+
const angle6 = angle(vec6a, vec6b)
|
|
37
|
+
nearlyEqual(t, angle6, 0.785398, EPS)
|
|
38
|
+
|
|
39
|
+
// huge values
|
|
40
|
+
const vec7a = fromValues(1, 0, 0)
|
|
41
|
+
const vec7b = fromValues(1e200, 1e200, 0)
|
|
42
|
+
const angle7 = angle(vec7a, vec7b)
|
|
43
|
+
nearlyEqual(t, angle7, 0.785398, EPS)
|
|
44
|
+
|
|
28
45
|
t.true(true)
|
|
29
46
|
})
|
|
@@ -3,7 +3,7 @@ const { cross, fromValues } = require('./index')
|
|
|
3
3
|
|
|
4
4
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
5
|
|
|
6
|
-
test('vec3: cross() called with three
|
|
6
|
+
test('vec3: cross() called with three parameters should update a vec3 with correct values', (t) => {
|
|
7
7
|
const obs1 = fromValues(0, 0, 0)
|
|
8
8
|
const ret1 = cross(obs1, [0, 0, 0], [0, 0, 0])
|
|
9
9
|
t.true(compareVectors(obs1, [0, 0, 0]))
|
|
@@ -3,7 +3,7 @@ const { divide, fromValues } = require('./index')
|
|
|
3
3
|
|
|
4
4
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
5
|
|
|
6
|
-
test('vec3: divide() called with three
|
|
6
|
+
test('vec3: divide() called with three parameters should update a vec3 with correct values', (t) => {
|
|
7
7
|
const obs1 = fromValues(0, 0, 0)
|
|
8
8
|
const ret1 = divide(obs1, [0, 0, 0], [0, 0, 0])
|
|
9
9
|
t.true(compareVectors(obs1, [0 / 0, 0 / 0, 0 / 0]))
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* @returns {vec3} out
|
|
8
8
|
* @alias module:modeling/maths/vec3.fromVec2
|
|
9
9
|
*/
|
|
10
|
-
const fromVector2 = (out,
|
|
11
|
-
out[0] =
|
|
12
|
-
out[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
|
}
|
package/src/maths/vec3/length.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* @returns {Number} length
|
|
6
6
|
* @alias module:modeling/maths/vec3.length
|
|
7
7
|
*/
|
|
8
|
-
const length = (
|
|
9
|
-
const x =
|
|
10
|
-
const y =
|
|
11
|
-
const z =
|
|
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
|
|
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
|
|
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]))
|
|
@@ -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
|
|
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]))
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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]))
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* @returns {Number} squared length
|
|
6
6
|
* @alias module:modeling/maths/vec3.squaredLength
|
|
7
7
|
*/
|
|
8
|
-
const squaredLength = (
|
|
9
|
-
const x =
|
|
10
|
-
const y =
|
|
11
|
-
const z =
|
|
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
|
|
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]))
|
|
@@ -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
|
|
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,
|
|
@@ -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
|
|
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,
|
|
@@ -2,7 +2,6 @@ const flatten = require('../utils/flatten')
|
|
|
2
2
|
|
|
3
3
|
const vec2 = require('../maths/vec2')
|
|
4
4
|
const vec3 = require('../maths/vec3')
|
|
5
|
-
const mat4 = require('../maths/mat4')
|
|
6
5
|
|
|
7
6
|
const geom2 = require('../geometries/geom2')
|
|
8
7
|
const geom3 = require('../geometries/geom3')
|
|
@@ -12,129 +11,86 @@ const poly3 = require('../geometries/poly3')
|
|
|
12
11
|
const cache = new WeakMap()
|
|
13
12
|
|
|
14
13
|
/*
|
|
15
|
-
* Measure the min and max bounds of the given (path2) geometry.
|
|
16
|
-
* @return {Array[]} the min and max bounds for the geometry
|
|
14
|
+
* Measure the min and max bounds of the given (path2) geometry.
|
|
15
|
+
* @return {Array[]} the min and max bounds for the geometry
|
|
17
16
|
*/
|
|
18
|
-
const
|
|
19
|
-
let boundingBox = cache.get(
|
|
17
|
+
const measureBoundingBoxOfPath2 = (geometry) => {
|
|
18
|
+
let boundingBox = cache.get(geometry)
|
|
20
19
|
if (boundingBox) return boundingBox
|
|
21
20
|
|
|
21
|
+
const points = path2.toPoints(geometry)
|
|
22
|
+
|
|
22
23
|
let minpoint
|
|
23
24
|
if (points.length === 0) {
|
|
24
25
|
minpoint = vec2.create()
|
|
25
26
|
} else {
|
|
26
27
|
minpoint = vec2.clone(points[0])
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
+
let maxpoint = vec2.clone(minpoint)
|
|
29
30
|
|
|
30
31
|
points.forEach((point) => {
|
|
31
32
|
vec2.min(minpoint, minpoint, point)
|
|
32
33
|
vec2.max(maxpoint, maxpoint, point)
|
|
33
34
|
})
|
|
34
|
-
|
|
35
|
+
minpoint = [minpoint[0], minpoint[1], 0]
|
|
36
|
+
maxpoint = [maxpoint[0], maxpoint[1], 0]
|
|
37
|
+
|
|
38
|
+
boundingBox = [minpoint, maxpoint]
|
|
39
|
+
|
|
40
|
+
cache.set(geometry, boundingBox)
|
|
35
41
|
|
|
36
|
-
cache.set(points, boundingBox)
|
|
37
42
|
return boundingBox
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
/*
|
|
41
|
-
* Measure the min and max bounds of the given (
|
|
46
|
+
* Measure the min and max bounds of the given (geom2) geometry.
|
|
42
47
|
* @return {Array[]} the min and max bounds for the geometry
|
|
43
48
|
*/
|
|
44
|
-
const
|
|
49
|
+
const measureBoundingBoxOfGeom2 = (geometry) => {
|
|
45
50
|
let boundingBox = cache.get(geometry)
|
|
46
51
|
if (boundingBox) return boundingBox
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
const points = geom2.toPoints(geometry)
|
|
54
|
+
|
|
55
|
+
let minpoint
|
|
56
|
+
if (points.length === 0) {
|
|
57
|
+
minpoint = vec2.create()
|
|
51
58
|
} else {
|
|
52
|
-
|
|
53
|
-
boundingBox = measureBoundingBoxOfPath2Points(path2.toPoints(geometry))
|
|
59
|
+
minpoint = vec2.clone(points[0])
|
|
54
60
|
}
|
|
61
|
+
let maxpoint = vec2.clone(minpoint)
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
/*
|
|
61
|
-
* Measure the min and max bounds of the given (geom2) geometry.points/sides.
|
|
62
|
-
* @return {Array[]} the min and max bounds for the geometr.points/sidesy
|
|
63
|
-
*/
|
|
64
|
-
const measureBoundingBoxOfGeom2Points = ({ points, sides }) => {
|
|
65
|
-
const cacheKey = points || sides
|
|
66
|
-
|
|
67
|
-
let boundingBox = cache.get(cacheKey)
|
|
68
|
-
if (boundingBox) return boundingBox
|
|
63
|
+
points.forEach((point) => {
|
|
64
|
+
vec2.min(minpoint, minpoint, point)
|
|
65
|
+
vec2.max(maxpoint, maxpoint, point)
|
|
66
|
+
})
|
|
69
67
|
|
|
70
|
-
|
|
68
|
+
minpoint = [minpoint[0], minpoint[1], 0]
|
|
69
|
+
maxpoint = [maxpoint[0], maxpoint[1], 0]
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
if (points.length === 0) {
|
|
74
|
-
minpoint = vec2.create()
|
|
75
|
-
} else {
|
|
76
|
-
minpoint = vec2.clone(points[0])
|
|
77
|
-
}
|
|
78
|
-
maxpoint = vec2.clone(minpoint)
|
|
71
|
+
boundingBox = [minpoint, maxpoint]
|
|
79
72
|
|
|
80
|
-
|
|
81
|
-
vec2.min(minpoint, minpoint, point)
|
|
82
|
-
vec2.max(maxpoint, maxpoint, point)
|
|
83
|
-
})
|
|
84
|
-
} else { // sides
|
|
85
|
-
// to avoid calling costly toPoints, we take advantage of the knowlege how the toPoints works
|
|
86
|
-
if (sides.length === 0) {
|
|
87
|
-
minpoint = vec2.create()
|
|
88
|
-
} else {
|
|
89
|
-
minpoint = vec2.clone(sides[0][0])
|
|
90
|
-
}
|
|
91
|
-
maxpoint = vec2.clone(minpoint)
|
|
92
|
-
|
|
93
|
-
sides.forEach((side) => {
|
|
94
|
-
vec2.min(minpoint, minpoint, side[0])
|
|
95
|
-
vec2.max(maxpoint, maxpoint, side[0])
|
|
96
|
-
})
|
|
97
|
-
}
|
|
98
|
-
boundingBox = [[minpoint[0], minpoint[1], 0], [maxpoint[0], maxpoint[1], 0]]
|
|
73
|
+
cache.set(geometry, boundingBox)
|
|
99
74
|
|
|
100
|
-
cache.set(cacheKey, boundingBox)
|
|
101
75
|
return boundingBox
|
|
102
76
|
}
|
|
103
77
|
|
|
104
78
|
/*
|
|
105
|
-
* Measure the min and max bounds of the given (
|
|
79
|
+
* Measure the min and max bounds of the given (geom3) geometry.
|
|
106
80
|
* @return {Array[]} the min and max bounds for the geometry
|
|
107
81
|
*/
|
|
108
|
-
const
|
|
82
|
+
const measureBoundingBoxOfGeom3 = (geometry) => {
|
|
109
83
|
let boundingBox = cache.get(geometry)
|
|
110
84
|
if (boundingBox) return boundingBox
|
|
111
85
|
|
|
112
|
-
|
|
113
|
-
// get boundingBox of original points and transform it
|
|
114
|
-
boundingBox = transformBoundingBox(measureBoundingBoxOfGeom2Points(geometry), geometry.transforms)
|
|
115
|
-
} else {
|
|
116
|
-
// transform the points and then caclulate the boundingBox
|
|
117
|
-
boundingBox = measureBoundingBoxOfGeom2Points({ points: geom2.toPoints(geometry) })
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
cache.set(geometry, boundingBox)
|
|
121
|
-
return boundingBox
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/*
|
|
125
|
-
* Measure the min and max bounds of the given (geom3) geometry.polygons.
|
|
126
|
-
* @return {Array[]} the min and max bounds for the geometry.polygons
|
|
127
|
-
*/
|
|
128
|
-
const measureBoundingBoxOfGeom3Polygons = (polygons) => {
|
|
129
|
-
let boundingBox = cache.get(polygons)
|
|
130
|
-
if (boundingBox) return boundingBox
|
|
86
|
+
const polygons = geom3.toPolygons(geometry)
|
|
131
87
|
|
|
132
|
-
|
|
88
|
+
let minpoint = vec3.create()
|
|
133
89
|
if (polygons.length > 0) {
|
|
134
90
|
const points = poly3.toPoints(polygons[0])
|
|
135
91
|
vec3.copy(minpoint, points[0])
|
|
136
92
|
}
|
|
137
|
-
|
|
93
|
+
let maxpoint = vec3.clone(minpoint)
|
|
138
94
|
|
|
139
95
|
polygons.forEach((polygon) => {
|
|
140
96
|
poly3.toPoints(polygon).forEach((point) => {
|
|
@@ -143,59 +99,13 @@ const measureBoundingBoxOfGeom3Polygons = (polygons) => {
|
|
|
143
99
|
})
|
|
144
100
|
})
|
|
145
101
|
|
|
146
|
-
|
|
102
|
+
minpoint = [minpoint[0], minpoint[1], minpoint[2]]
|
|
103
|
+
maxpoint = [maxpoint[0], maxpoint[1], maxpoint[2]]
|
|
147
104
|
|
|
148
|
-
|
|
149
|
-
return boundingBox
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/*
|
|
153
|
-
* Measure the min and max bounds of the given (geom3) geometry.
|
|
154
|
-
* @return {Array[]} the min and max bounds for the geometry
|
|
155
|
-
*/
|
|
156
|
-
const measureBoundingBoxOfGeom3 = (geometry) => {
|
|
157
|
-
let boundingBox = cache.get(geometry)
|
|
158
|
-
if (boundingBox) return boundingBox
|
|
159
|
-
|
|
160
|
-
if (mat4.isOnlyTransformScale(geometry.transforms)) {
|
|
161
|
-
// get boundingBox of original points and transform it
|
|
162
|
-
boundingBox = transformBoundingBox(measureBoundingBoxOfGeom3Polygons(geometry.polygons), geometry.transforms)
|
|
163
|
-
} else {
|
|
164
|
-
// transform the points and then caclulate the boundingBox
|
|
165
|
-
boundingBox = measureBoundingBoxOfGeom3Polygons(geom3.toPolygons(geometry))
|
|
166
|
-
}
|
|
105
|
+
boundingBox = [minpoint, maxpoint]
|
|
167
106
|
|
|
168
107
|
cache.set(geometry, boundingBox)
|
|
169
|
-
return boundingBox
|
|
170
|
-
}
|
|
171
108
|
|
|
172
|
-
/*
|
|
173
|
-
* swap values if specific axis value in the second vector has lower value than the axis value in first vector
|
|
174
|
-
*/
|
|
175
|
-
const fixBound = (i, v1, v2) => {
|
|
176
|
-
if (v1[i] > v2[i]) {
|
|
177
|
-
const tmp = v1[i]
|
|
178
|
-
v1[i] = v2[i]
|
|
179
|
-
v2[i] = tmp
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/*
|
|
184
|
-
* Transform the given bounding box
|
|
185
|
-
*/
|
|
186
|
-
const transformBoundingBox = (boundingBox, transforms) => {
|
|
187
|
-
if (!mat4.isIdentity(transforms)) {
|
|
188
|
-
vec3.transform(boundingBox[0], boundingBox[0], transforms)
|
|
189
|
-
vec3.transform(boundingBox[1], boundingBox[1], transforms)
|
|
190
|
-
|
|
191
|
-
// we now have a new 2 vectors: [v1,v2] => [ [x1,y1,z1], [x2,y2,z2] ]
|
|
192
|
-
// transform can move bounding box corner in such way that it is no longer true that
|
|
193
|
-
// - v1 = [min(x1,x2),min(y1,y2),min(z1,z2)]
|
|
194
|
-
// - v2 = [max(x1,x2),max(y1,y2),max(z1,z2)]
|
|
195
|
-
fixBound(0, ...boundingBox) // swap x, if higher value is in first vector
|
|
196
|
-
fixBound(1, ...boundingBox) // swap y, if higher value is in first vector
|
|
197
|
-
fixBound(2, ...boundingBox) // swap z, if higher value is in first vector
|
|
198
|
-
}
|
|
199
109
|
return boundingBox
|
|
200
110
|
}
|
|
201
111
|
|
|
@@ -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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
|
8
|
-
* @param {geom3} geometry1 - geometry for
|
|
9
|
-
* @param {geom3} geometry2 - geometry for
|
|
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
|
|
7
|
-
// This EPS is derived from a
|
|
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}
|
|
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(
|
|
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
|
|
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)
|