@jscad/modeling 3.0.0-alpha.0 → 3.0.2-alpha.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 +49 -0
- package/LICENSE +1 -1
- package/dist/jscad-modeling.es.js +2 -2
- package/dist/jscad-modeling.min.js +2 -2
- package/package.json +2 -2
- package/rollup.config.js +1 -1
- package/src/colors/colorize.js +1 -5
- package/src/colors/colorize.test.js +8 -8
- package/src/geometries/geom2/transform.js +9 -1
- package/src/geometries/geom2/transform.test.js +57 -0
- package/src/geometries/geom3/fromPointsConvex.d.ts +4 -0
- package/src/geometries/geom3/fromPointsConvex.js +25 -0
- package/src/geometries/geom3/fromPointsConvex.test.js +32 -0
- package/src/geometries/geom3/index.d.ts +1 -0
- package/src/geometries/geom3/index.js +1 -0
- package/src/geometries/index.js +3 -4
- package/src/geometries/path2/appendBezier.js +1 -1
- package/src/geometries/poly3/index.js +1 -1
- package/src/geometries/poly3/measureBoundingBox.js +2 -0
- package/src/geometries/poly3/measureBoundingSphere.d.ts +2 -1
- package/src/geometries/poly3/measureBoundingSphere.js +25 -8
- package/src/geometries/poly3/measureBoundingSphere.test.js +12 -8
- package/src/geometries/poly3/type.d.ts +1 -1
- package/src/geometries/slice/validate.js +1 -2
- package/src/index.js +41 -0
- package/src/maths/index.js +1 -0
- package/src/maths/mat4/isOnlyTransformScale.js +1 -1
- package/src/measurements/measureAggregateArea.js +0 -1
- package/src/measurements/measureAggregateBoundingBox.js +0 -1
- package/src/measurements/measureAggregateEpsilon.js +0 -1
- package/src/measurements/measureAggregateVolume.js +0 -1
- package/src/measurements/measureArea.js +0 -1
- package/src/measurements/measureBoundingBox.js +0 -1
- package/src/measurements/measureBoundingSphere.js +2 -6
- package/src/measurements/measureEpsilon.js +0 -1
- package/src/measurements/measureVolume.js +0 -1
- package/src/operations/booleans/index.d.ts +1 -0
- package/src/operations/booleans/intersect.js +5 -5
- package/src/operations/booleans/intersect.test.js +6 -7
- package/src/operations/booleans/intersectGeom2.js +2 -6
- package/src/operations/booleans/intersectGeom2.test.js +25 -1
- package/src/operations/booleans/intersectGeom3.js +2 -6
- package/src/operations/booleans/intersectGeom3.test.js +5 -1
- package/src/operations/booleans/martinez/compareEvents.js +2 -7
- package/src/operations/booleans/martinez/connectEdges.js +30 -41
- package/src/operations/booleans/martinez/contour.js +1 -1
- package/src/operations/booleans/martinez/divideSegment.js +12 -11
- package/src/operations/booleans/martinez/fillQueue.js +24 -28
- package/src/operations/booleans/martinez/index.js +2 -1
- package/src/operations/booleans/martinez/possibleIntersection.js +41 -30
- package/src/operations/booleans/martinez/segmentIntersection.js +7 -9
- package/src/operations/booleans/martinez/splaytree.js +59 -457
- package/src/operations/booleans/martinez/subdivideSegments.js +4 -4
- package/src/operations/booleans/martinez/sweepEvent.js +3 -17
- package/src/operations/booleans/mayOverlap.js +0 -1
- package/src/operations/booleans/scission.d.ts +5 -0
- package/src/operations/booleans/scission.js +3 -5
- package/src/operations/booleans/scission.test.js +6 -0
- package/src/operations/booleans/subtract.js +5 -5
- package/src/operations/booleans/subtract.test.js +6 -7
- package/src/operations/booleans/subtractGeom2.js +2 -6
- package/src/operations/booleans/subtractGeom2.test.js +25 -1
- package/src/operations/booleans/subtractGeom3.js +2 -6
- package/src/operations/booleans/subtractGeom3.test.js +5 -1
- package/src/operations/booleans/trees/Node.js +25 -27
- package/src/operations/booleans/trees/PolygonTreeNode.js +153 -106
- package/src/operations/booleans/trees/Tree.js +9 -4
- package/src/operations/booleans/trees/splitLineSegmentByPlane.js +5 -3
- package/src/operations/booleans/trees/splitPolygonByPlane.d.ts +33 -0
- package/src/operations/booleans/trees/splitPolygonByPlane.js +39 -34
- package/src/operations/booleans/union.js +5 -5
- package/src/operations/booleans/union.test.js +6 -7
- package/src/operations/booleans/unionGeom2.js +2 -6
- package/src/operations/booleans/unionGeom2.test.js +25 -1
- package/src/operations/booleans/unionGeom3.js +2 -6
- package/src/operations/booleans/unionGeom3.test.js +6 -1
- package/src/operations/extrusions/extrudeFromSlices.test.js +8 -1
- package/src/operations/extrusions/extrudeHelical.js +2 -8
- package/src/operations/extrusions/extrudeLinear.js +1 -5
- package/src/operations/extrusions/extrudeLinear.test.js +7 -1
- package/src/operations/extrusions/extrudeRotate.js +3 -2
- package/src/operations/extrusions/extrudeRotate.test.js +13 -1
- package/src/operations/extrusions/extrudeWalls.js +3 -1
- package/src/operations/extrusions/project.js +1 -5
- package/src/operations/hulls/hull.js +6 -5
- package/src/operations/hulls/hull.test.js +56 -3
- package/src/operations/hulls/hullChain.js +11 -6
- package/src/operations/hulls/hullChain.test.js +12 -2
- package/src/operations/hulls/hullGeom2.js +5 -6
- package/src/operations/hulls/hullGeom3.js +9 -18
- package/src/operations/hulls/hullPath2.js +6 -7
- package/src/operations/hulls/hullPath2.test.js +1 -1
- package/src/operations/hulls/hullPoints2.d.ts +3 -0
- package/src/operations/hulls/hullPoints2.js +24 -30
- package/src/operations/hulls/hullPoints3.d.ts +4 -0
- package/src/operations/hulls/hullPoints3.js +21 -0
- package/src/operations/hulls/index.d.ts +2 -0
- package/src/operations/hulls/index.js +3 -1
- package/src/operations/modifiers/generalize.js +2 -6
- package/src/operations/modifiers/index.js +1 -1
- package/src/operations/modifiers/mergePolygons.js +2 -3
- package/src/operations/modifiers/reTesselateCoplanarPolygons.js +7 -7
- package/src/operations/modifiers/snap.js +2 -6
- package/src/operations/offsets/offset.js +1 -5
- package/src/operations/offsets/offsetFromPoints.test.js +0 -1
- package/src/operations/offsets/offsetGeom2.test.js +1 -0
- package/src/operations/offsets/offsetGeom3.js +0 -2
- package/src/operations/offsets/offsetGeom3.test.js +9 -1
- package/src/operations/offsets/offsetPath2.js +3 -3
- package/src/operations/transforms/align.js +8 -7
- package/src/operations/transforms/align.test.js +2 -2
- package/src/operations/transforms/center.js +6 -9
- package/src/operations/transforms/center.test.js +19 -1
- package/src/operations/transforms/mirror.js +5 -8
- package/src/operations/transforms/mirror.test.js +7 -7
- package/src/operations/transforms/rotate.js +5 -8
- package/src/operations/transforms/scale.js +5 -8
- package/src/operations/transforms/transform.js +2 -5
- package/src/operations/transforms/translate.js +5 -8
- package/src/primitives/arc.js +2 -0
- package/src/primitives/arc.test.js +11 -11
- package/src/primitives/circle.test.js +18 -8
- package/src/primitives/cube.test.js +10 -0
- package/src/primitives/cuboid.test.js +10 -0
- package/src/primitives/cylinder.test.js +12 -0
- package/src/primitives/cylinderElliptic.test.js +21 -1
- package/src/primitives/ellipse.test.js +18 -8
- package/src/primitives/ellipsoid.test.js +12 -0
- package/src/primitives/geodesicSphere.test.js +8 -0
- package/src/primitives/line.test.js +1 -1
- package/src/primitives/polygon.d.ts +1 -0
- package/src/primitives/polygon.js +13 -4
- package/src/primitives/polygon.test.js +15 -0
- package/src/primitives/polyhedron.js +1 -0
- package/src/primitives/polyhedron.test.js +8 -2
- package/src/primitives/rectangle.test.js +9 -3
- package/src/primitives/roundedCuboid.js +1 -1
- package/src/primitives/roundedCuboid.test.js +20 -4
- package/src/primitives/roundedCylinder.js +1 -1
- package/src/primitives/roundedCylinder.test.js +20 -0
- package/src/primitives/roundedRectangle.js +1 -1
- package/src/primitives/roundedRectangle.test.js +15 -6
- package/src/primitives/sphere.test.js +12 -0
- package/src/primitives/square.test.js +10 -4
- package/src/primitives/star.test.js +14 -6
- package/src/primitives/torus.js +1 -1
- package/src/primitives/torus.test.js +11 -1
- package/src/primitives/triangle.test.js +17 -9
- package/src/utils/coalesce.d.ts +3 -0
- package/src/utils/coalesce.js +20 -0
- package/src/utils/index.js +2 -2
- package/src/maths/mat4/leftMultiplyVec2.d.ts +0 -4
- package/src/maths/mat4/leftMultiplyVec2.js +0 -26
- package/src/maths/mat4/leftMultiplyVec3.d.ts +0 -4
- package/src/maths/mat4/leftMultiplyVec3.js +0 -27
- package/src/maths/mat4/mirror.d.ts +0 -4
- package/src/maths/mat4/mirror.js +0 -32
- package/src/maths/mat4/rightMultiplyVec2.d.ts +0 -4
- package/src/maths/mat4/rightMultiplyVec2.js +0 -27
- package/src/maths/mat4/rightMultiplyVec3.d.ts +0 -4
- package/src/maths/mat4/rightMultiplyVec3.js +0 -28
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { flatten } from '../../utils/flatten.js'
|
|
2
|
-
|
|
3
1
|
import * as geom2 from '../../geometries/geom2/index.js'
|
|
4
2
|
import * as geom3 from '../../geometries/geom3/index.js'
|
|
5
3
|
import * as path2 from '../../geometries/path2/index.js'
|
|
6
4
|
|
|
7
|
-
import {
|
|
5
|
+
import { measureAggregateBoundingBox } from '../../measurements/measureAggregateBoundingBox.js'
|
|
8
6
|
|
|
9
7
|
import { translate } from './translate.js'
|
|
10
8
|
|
|
@@ -15,7 +13,7 @@ const centerGeometry = (options, object) => {
|
|
|
15
13
|
}
|
|
16
14
|
const { axes, relativeTo } = Object.assign({}, defaults, options)
|
|
17
15
|
|
|
18
|
-
const bounds =
|
|
16
|
+
const bounds = measureAggregateBoundingBox(object)
|
|
19
17
|
const offset = [0, 0, 0]
|
|
20
18
|
if (axes[0]) offset[0] = relativeTo[0] - (bounds[0][0] + ((bounds[1][0] - bounds[0][0]) / 2))
|
|
21
19
|
if (axes[1]) offset[1] = relativeTo[1] - (bounds[0][1] + ((bounds[1][1] - bounds[0][1]) / 2))
|
|
@@ -43,8 +41,6 @@ export const center = (options, ...objects) => {
|
|
|
43
41
|
}
|
|
44
42
|
const { axes, relativeTo } = Object.assign({}, defaults, options)
|
|
45
43
|
|
|
46
|
-
objects = flatten(objects)
|
|
47
|
-
if (objects.length === 0) throw new Error('wrong number of arguments')
|
|
48
44
|
if (relativeTo.length !== 3) throw new Error('relativeTo must be an array of length 3')
|
|
49
45
|
|
|
50
46
|
options = { axes, relativeTo }
|
|
@@ -53,6 +49,7 @@ export const center = (options, ...objects) => {
|
|
|
53
49
|
if (path2.isA(object)) return centerGeometry(options, object)
|
|
54
50
|
if (geom2.isA(object)) return centerGeometry(options, object)
|
|
55
51
|
if (geom3.isA(object)) return centerGeometry(options, object)
|
|
52
|
+
if (Array.isArray(object)) return centerGeometry(options, object)
|
|
56
53
|
return object
|
|
57
54
|
})
|
|
58
55
|
return results.length === 1 ? results[0] : results
|
|
@@ -64,7 +61,7 @@ export const center = (options, ...objects) => {
|
|
|
64
61
|
* @return {Object|Array} the centered object, or a list of centered objects
|
|
65
62
|
* @alias module:modeling/transforms.centerX
|
|
66
63
|
*/
|
|
67
|
-
export const centerX = (...objects) => center({ axes: [true, false, false] }, objects)
|
|
64
|
+
export const centerX = (...objects) => center({ axes: [true, false, false] }, ...objects)
|
|
68
65
|
|
|
69
66
|
/**
|
|
70
67
|
* Center the given objects about the Y axis.
|
|
@@ -72,7 +69,7 @@ export const centerX = (...objects) => center({ axes: [true, false, false] }, ob
|
|
|
72
69
|
* @return {Object|Array} the centered object, or a list of centered objects
|
|
73
70
|
* @alias module:modeling/transforms.centerY
|
|
74
71
|
*/
|
|
75
|
-
export const centerY = (...objects) => center({ axes: [false, true, false] }, objects)
|
|
72
|
+
export const centerY = (...objects) => center({ axes: [false, true, false] }, ...objects)
|
|
76
73
|
|
|
77
74
|
/**
|
|
78
75
|
* Center the given objects about the Z axis.
|
|
@@ -80,4 +77,4 @@ export const centerY = (...objects) => center({ axes: [false, true, false] }, ob
|
|
|
80
77
|
* @return {Object|Array} the centered object, or a list of centered objects
|
|
81
78
|
* @alias module:modeling/transforms.centerZ
|
|
82
79
|
*/
|
|
83
|
-
export const centerZ = (...objects) => center({ axes: [false, false, true] }, objects)
|
|
80
|
+
export const centerZ = (...objects) => center({ axes: [false, false, true] }, ...objects)
|
|
@@ -4,7 +4,9 @@ import { comparePoints, comparePolygonsAsPoints } from '../../../test/helpers/in
|
|
|
4
4
|
|
|
5
5
|
import { geom2, geom3, path2 } from '../../geometries/index.js'
|
|
6
6
|
|
|
7
|
-
import { measureArea, measureVolume } from '../../measurements/index.js'
|
|
7
|
+
import { measureArea, measureAggregateBoundingBox, measureVolume } from '../../measurements/index.js'
|
|
8
|
+
|
|
9
|
+
import { square } from '../../primitives/index.js'
|
|
8
10
|
|
|
9
11
|
import { center, centerX, centerY, centerZ } from './index.js'
|
|
10
12
|
|
|
@@ -136,3 +138,19 @@ test('center: centering of multiple objects produces expected changes', (t) => {
|
|
|
136
138
|
t.notThrows(() => geom2.validate(centered[2]))
|
|
137
139
|
t.true(comparePoints(pts2, exp2))
|
|
138
140
|
})
|
|
141
|
+
|
|
142
|
+
test('center multiple separate', (t) => {
|
|
143
|
+
const square1 = square({ size: 4, center: [10, 10] })
|
|
144
|
+
const square2 = square({ size: 6, center: [-10, -10] })
|
|
145
|
+
const obs = center({}, square1, square2)
|
|
146
|
+
t.notThrows(() => obs.map(geom2.validate))
|
|
147
|
+
t.deepEqual([[-3, -3, 0], [3, 3, 0]], measureAggregateBoundingBox(obs))
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('center multiple grouped', (t) => {
|
|
151
|
+
const square1 = square({ size: 4, center: [10, 10] })
|
|
152
|
+
const square2 = square({ size: 6, center: [-10, -10] })
|
|
153
|
+
const obs = center({}, [square1, square2])
|
|
154
|
+
t.notThrows(() => obs.map(geom2.validate))
|
|
155
|
+
t.deepEqual([[-12.5, -12.5, 0], [12.5, 12.5, 0]], measureAggregateBoundingBox(obs))
|
|
156
|
+
})
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { flatten } from '../../utils/flatten.js'
|
|
2
|
-
|
|
3
1
|
import * as mat4 from '../../maths/mat4/index.js'
|
|
4
2
|
import * as plane from '../../maths/plane/index.js'
|
|
5
3
|
|
|
@@ -26,9 +24,6 @@ export const mirror = (options, ...objects) => {
|
|
|
26
24
|
}
|
|
27
25
|
const { origin, normal } = Object.assign({}, defaults, options)
|
|
28
26
|
|
|
29
|
-
objects = flatten(objects)
|
|
30
|
-
if (objects.length === 0) throw new Error('wrong number of arguments')
|
|
31
|
-
|
|
32
27
|
const planeOfMirror = plane.fromNormalAndPoint(plane.create(), normal, origin)
|
|
33
28
|
// verify the plane, i.e. check that the given normal was valid
|
|
34
29
|
if (Number.isNaN(planeOfMirror[0])) {
|
|
@@ -41,6 +36,8 @@ export const mirror = (options, ...objects) => {
|
|
|
41
36
|
if (path2.isA(object)) return path2.transform(matrix, object)
|
|
42
37
|
if (geom2.isA(object)) return geom2.transform(matrix, object)
|
|
43
38
|
if (geom3.isA(object)) return geom3.transform(matrix, object)
|
|
39
|
+
// handle recursive arrays
|
|
40
|
+
if (Array.isArray(object)) return mirror(options, ...object)
|
|
44
41
|
return object
|
|
45
42
|
})
|
|
46
43
|
return results.length === 1 ? results[0] : results
|
|
@@ -52,7 +49,7 @@ export const mirror = (options, ...objects) => {
|
|
|
52
49
|
* @return {Object|Array} the mirrored object, or a list of mirrored objects
|
|
53
50
|
* @alias module:modeling/transforms.mirrorX
|
|
54
51
|
*/
|
|
55
|
-
export const mirrorX = (...objects) => mirror({ normal: [1, 0, 0] }, objects)
|
|
52
|
+
export const mirrorX = (...objects) => mirror({ normal: [1, 0, 0] }, ...objects)
|
|
56
53
|
|
|
57
54
|
/**
|
|
58
55
|
* Mirror the given objects about the Y axis.
|
|
@@ -60,7 +57,7 @@ export const mirrorX = (...objects) => mirror({ normal: [1, 0, 0] }, objects)
|
|
|
60
57
|
* @return {Object|Array} the mirrored object, or a list of mirrored objects
|
|
61
58
|
* @alias module:modeling/transforms.mirrorY
|
|
62
59
|
*/
|
|
63
|
-
export const mirrorY = (...objects) => mirror({ normal: [0, 1, 0] }, objects)
|
|
60
|
+
export const mirrorY = (...objects) => mirror({ normal: [0, 1, 0] }, ...objects)
|
|
64
61
|
|
|
65
62
|
/**
|
|
66
63
|
* Mirror the given objects about the Z axis.
|
|
@@ -68,4 +65,4 @@ export const mirrorY = (...objects) => mirror({ normal: [0, 1, 0] }, objects)
|
|
|
68
65
|
* @return {Object|Array} the mirrored object, or a list of mirrored objects
|
|
69
66
|
* @alias module:modeling/transforms.mirrorZ
|
|
70
67
|
*/
|
|
71
|
-
export const mirrorZ = (...objects) => mirror({ normal: [0, 0, 1] }, objects)
|
|
68
|
+
export const mirrorZ = (...objects) => mirror({ normal: [0, 0, 1] }, ...objects)
|
|
@@ -42,29 +42,29 @@ test('mirror: mirroring of geom2 about X/Y produces expected changes to points',
|
|
|
42
42
|
// mirror about X
|
|
43
43
|
let mirrored = mirror({ normal: [1, 0, 0] }, geometry)
|
|
44
44
|
let obs = geom2.toPoints(mirrored)
|
|
45
|
-
let exp = [[
|
|
45
|
+
let exp = [[-10, -5], [0, 5], [5, -5]]
|
|
46
46
|
t.notThrows(() => geom2.validate(mirrored))
|
|
47
|
-
t.is(measureArea(mirrored),
|
|
47
|
+
t.is(measureArea(mirrored), measureArea(geometry))
|
|
48
48
|
t.true(comparePoints(obs, exp))
|
|
49
49
|
|
|
50
50
|
mirrored = mirrorX(geometry)
|
|
51
51
|
obs = geom2.toPoints(mirrored)
|
|
52
52
|
t.notThrows(() => geom2.validate(mirrored))
|
|
53
|
-
t.is(measureArea(mirrored),
|
|
53
|
+
t.is(measureArea(mirrored), measureArea(geometry))
|
|
54
54
|
t.true(comparePoints(obs, exp))
|
|
55
55
|
|
|
56
56
|
// mirror about Y
|
|
57
57
|
mirrored = mirror({ normal: [0, 1, 0] }, geometry)
|
|
58
58
|
obs = geom2.toPoints(mirrored)
|
|
59
|
-
exp = [[
|
|
59
|
+
exp = [[10, 5], [0, -5], [-5, 5]]
|
|
60
60
|
t.notThrows(() => geom2.validate(mirrored))
|
|
61
|
-
t.is(measureArea(mirrored),
|
|
61
|
+
t.is(measureArea(mirrored), measureArea(geometry))
|
|
62
62
|
t.true(comparePoints(obs, exp))
|
|
63
63
|
|
|
64
64
|
mirrored = mirrorY(geometry)
|
|
65
65
|
obs = geom2.toPoints(mirrored)
|
|
66
66
|
t.notThrows(() => geom2.validate(mirrored))
|
|
67
|
-
t.is(measureArea(mirrored),
|
|
67
|
+
t.is(measureArea(mirrored), measureArea(geometry))
|
|
68
68
|
t.true(comparePoints(obs, exp))
|
|
69
69
|
})
|
|
70
70
|
|
|
@@ -158,7 +158,7 @@ test('mirror: mirroring of multiple objects produces an array of mirrored object
|
|
|
158
158
|
t.true(comparePoints(obs, exp))
|
|
159
159
|
|
|
160
160
|
obs = geom2.toPoints(mirrored[2])
|
|
161
|
-
exp = [[
|
|
161
|
+
exp = [[10, 5], [0, -5], [-5, 5]]
|
|
162
162
|
t.notThrows(() => geom2.validate(mirrored[2]))
|
|
163
163
|
t.true(comparePoints(obs, exp))
|
|
164
164
|
})
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { flatten } from '../../utils/flatten.js'
|
|
2
|
-
|
|
3
1
|
import * as mat4 from '../../maths/mat4/index.js'
|
|
4
2
|
|
|
5
3
|
import * as geom2 from '../../geometries/geom2/index.js'
|
|
@@ -19,9 +17,6 @@ import * as path2 from '../../geometries/path2/index.js'
|
|
|
19
17
|
export const rotate = (angles, ...objects) => {
|
|
20
18
|
if (!Array.isArray(angles)) throw new Error('angles must be an array')
|
|
21
19
|
|
|
22
|
-
objects = flatten(objects)
|
|
23
|
-
if (objects.length === 0) throw new Error('wrong number of arguments')
|
|
24
|
-
|
|
25
20
|
// adjust the angles if necessary
|
|
26
21
|
angles = angles.slice() // don't modify the original
|
|
27
22
|
while (angles.length < 3) angles.push(0)
|
|
@@ -36,6 +31,8 @@ export const rotate = (angles, ...objects) => {
|
|
|
36
31
|
if (path2.isA(object)) return path2.transform(matrix, object)
|
|
37
32
|
if (geom2.isA(object)) return geom2.transform(matrix, object)
|
|
38
33
|
if (geom3.isA(object)) return geom3.transform(matrix, object)
|
|
34
|
+
// handle recursive arrays
|
|
35
|
+
if (Array.isArray(object)) return rotate(angles, ...object)
|
|
39
36
|
return object
|
|
40
37
|
})
|
|
41
38
|
return results.length === 1 ? results[0] : results
|
|
@@ -48,7 +45,7 @@ export const rotate = (angles, ...objects) => {
|
|
|
48
45
|
* @return {Object|Array} the rotated object, or a list of rotated objects
|
|
49
46
|
* @alias module:modeling/transforms.rotateX
|
|
50
47
|
*/
|
|
51
|
-
export const rotateX = (angle, ...objects) => rotate([angle, 0, 0], objects)
|
|
48
|
+
export const rotateX = (angle, ...objects) => rotate([angle, 0, 0], ...objects)
|
|
52
49
|
|
|
53
50
|
/**
|
|
54
51
|
* Rotate the given objects about the Y axis, using the given options.
|
|
@@ -57,7 +54,7 @@ export const rotateX = (angle, ...objects) => rotate([angle, 0, 0], objects)
|
|
|
57
54
|
* @return {Object|Array} the rotated object, or a list of rotated objects
|
|
58
55
|
* @alias module:modeling/transforms.rotateY
|
|
59
56
|
*/
|
|
60
|
-
export const rotateY = (angle, ...objects) => rotate([0, angle, 0], objects)
|
|
57
|
+
export const rotateY = (angle, ...objects) => rotate([0, angle, 0], ...objects)
|
|
61
58
|
|
|
62
59
|
/**
|
|
63
60
|
* Rotate the given objects about the Z axis, using the given options.
|
|
@@ -66,4 +63,4 @@ export const rotateY = (angle, ...objects) => rotate([0, angle, 0], objects)
|
|
|
66
63
|
* @return {Object|Array} the rotated object, or a list of rotated objects
|
|
67
64
|
* @alias module:modeling/transforms.rotateZ
|
|
68
65
|
*/
|
|
69
|
-
export const rotateZ = (angle, ...objects) => rotate([0, 0, angle], objects)
|
|
66
|
+
export const rotateZ = (angle, ...objects) => rotate([0, 0, angle], ...objects)
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { flatten } from '../../utils/flatten.js'
|
|
2
|
-
|
|
3
1
|
import * as mat4 from '../../maths/mat4/index.js'
|
|
4
2
|
|
|
5
3
|
import * as geom2 from '../../geometries/geom2/index.js'
|
|
@@ -19,9 +17,6 @@ import * as path2 from '../../geometries/path2/index.js'
|
|
|
19
17
|
export const scale = (factors, ...objects) => {
|
|
20
18
|
if (!Array.isArray(factors)) throw new Error('factors must be an array')
|
|
21
19
|
|
|
22
|
-
objects = flatten(objects)
|
|
23
|
-
if (objects.length === 0) throw new Error('wrong number of arguments')
|
|
24
|
-
|
|
25
20
|
// adjust the factors if necessary
|
|
26
21
|
factors = factors.slice() // don't modify the original
|
|
27
22
|
while (factors.length < 3) factors.push(1)
|
|
@@ -34,6 +29,8 @@ export const scale = (factors, ...objects) => {
|
|
|
34
29
|
if (path2.isA(object)) return path2.transform(matrix, object)
|
|
35
30
|
if (geom2.isA(object)) return geom2.transform(matrix, object)
|
|
36
31
|
if (geom3.isA(object)) return geom3.transform(matrix, object)
|
|
32
|
+
// handle recursive arrays
|
|
33
|
+
if (Array.isArray(object)) return scale(factors, ...object)
|
|
37
34
|
return object
|
|
38
35
|
})
|
|
39
36
|
return results.length === 1 ? results[0] : results
|
|
@@ -46,7 +43,7 @@ export const scale = (factors, ...objects) => {
|
|
|
46
43
|
* @return {Object|Array} the scaled object, or a list of scaled objects
|
|
47
44
|
* @alias module:modeling/transforms.scaleX
|
|
48
45
|
*/
|
|
49
|
-
export const scaleX = (factor, ...objects) => scale([factor, 1, 1], objects)
|
|
46
|
+
export const scaleX = (factor, ...objects) => scale([factor, 1, 1], ...objects)
|
|
50
47
|
|
|
51
48
|
/**
|
|
52
49
|
* Scale the given objects about the Y axis using the given options.
|
|
@@ -55,7 +52,7 @@ export const scaleX = (factor, ...objects) => scale([factor, 1, 1], objects)
|
|
|
55
52
|
* @return {Object|Array} the scaled object, or a list of scaled objects
|
|
56
53
|
* @alias module:modeling/transforms.scaleY
|
|
57
54
|
*/
|
|
58
|
-
export const scaleY = (factor, ...objects) => scale([1, factor, 1], objects)
|
|
55
|
+
export const scaleY = (factor, ...objects) => scale([1, factor, 1], ...objects)
|
|
59
56
|
|
|
60
57
|
/**
|
|
61
58
|
* Scale the given objects about the Z axis using the given options.
|
|
@@ -64,4 +61,4 @@ export const scaleY = (factor, ...objects) => scale([1, factor, 1], objects)
|
|
|
64
61
|
* @return {Object|Array} the scaled object, or a list of scaled objects
|
|
65
62
|
* @alias module:modeling/transforms.scaleZ
|
|
66
63
|
*/
|
|
67
|
-
export const scaleZ = (factor, ...objects) => scale([1, 1, factor], objects)
|
|
64
|
+
export const scaleZ = (factor, ...objects) => scale([1, 1, factor], ...objects)
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { flatten } from '../../utils/flatten.js'
|
|
2
|
-
|
|
3
1
|
import * as geom2 from '../../geometries/geom2/index.js'
|
|
4
2
|
import * as geom3 from '../../geometries/geom3/index.js'
|
|
5
3
|
import * as path2 from '../../geometries/path2/index.js'
|
|
@@ -17,13 +15,12 @@ import * as path2 from '../../geometries/path2/index.js'
|
|
|
17
15
|
export const transform = (matrix, ...objects) => {
|
|
18
16
|
// TODO how to check that the matrix is REAL?
|
|
19
17
|
|
|
20
|
-
objects = flatten(objects)
|
|
21
|
-
if (objects.length === 0) throw new Error('wrong number of arguments')
|
|
22
|
-
|
|
23
18
|
const results = objects.map((object) => {
|
|
24
19
|
if (path2.isA(object)) return path2.transform(matrix, object)
|
|
25
20
|
if (geom2.isA(object)) return geom2.transform(matrix, object)
|
|
26
21
|
if (geom3.isA(object)) return geom3.transform(matrix, object)
|
|
22
|
+
// handle recursive arrays
|
|
23
|
+
if (Array.isArray(object)) return transform(matrix, ...object)
|
|
27
24
|
return object
|
|
28
25
|
})
|
|
29
26
|
return results.length === 1 ? results[0] : results
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { flatten } from '../../utils/flatten.js'
|
|
2
|
-
|
|
3
1
|
import * as mat4 from '../../maths/mat4/index.js'
|
|
4
2
|
|
|
5
3
|
import * as geom2 from '../../geometries/geom2/index.js'
|
|
@@ -19,9 +17,6 @@ import * as path2 from '../../geometries/path2/index.js'
|
|
|
19
17
|
export const translate = (offset, ...objects) => {
|
|
20
18
|
if (!Array.isArray(offset)) throw new Error('offset must be an array')
|
|
21
19
|
|
|
22
|
-
objects = flatten(objects)
|
|
23
|
-
if (objects.length === 0) throw new Error('wrong number of arguments')
|
|
24
|
-
|
|
25
20
|
// adjust the offset if necessary
|
|
26
21
|
offset = offset.slice() // don't modify the original
|
|
27
22
|
while (offset.length < 3) offset.push(0)
|
|
@@ -32,6 +27,8 @@ export const translate = (offset, ...objects) => {
|
|
|
32
27
|
if (path2.isA(object)) return path2.transform(matrix, object)
|
|
33
28
|
if (geom2.isA(object)) return geom2.transform(matrix, object)
|
|
34
29
|
if (geom3.isA(object)) return geom3.transform(matrix, object)
|
|
30
|
+
// handle recursive arrays
|
|
31
|
+
if (Array.isArray(object)) return translate(offset, ...object)
|
|
35
32
|
return object
|
|
36
33
|
})
|
|
37
34
|
return results.length === 1 ? results[0] : results
|
|
@@ -44,7 +41,7 @@ export const translate = (offset, ...objects) => {
|
|
|
44
41
|
* @return {Object|Array} the translated object, or a list of translated objects
|
|
45
42
|
* @alias module:modeling/transforms.translateX
|
|
46
43
|
*/
|
|
47
|
-
export const translateX = (offset, ...objects) => translate([offset, 0, 0], objects)
|
|
44
|
+
export const translateX = (offset, ...objects) => translate([offset, 0, 0], ...objects)
|
|
48
45
|
|
|
49
46
|
/**
|
|
50
47
|
* Translate the given objects along the Y axis using the given options.
|
|
@@ -53,7 +50,7 @@ export const translateX = (offset, ...objects) => translate([offset, 0, 0], obje
|
|
|
53
50
|
* @return {Object|Array} the translated object, or a list of translated objects
|
|
54
51
|
* @alias module:modeling/transforms.translateY
|
|
55
52
|
*/
|
|
56
|
-
export const translateY = (offset, ...objects) => translate([0, offset, 0], objects)
|
|
53
|
+
export const translateY = (offset, ...objects) => translate([0, offset, 0], ...objects)
|
|
57
54
|
|
|
58
55
|
/**
|
|
59
56
|
* Translate the given objects along the Z axis using the given options.
|
|
@@ -62,4 +59,4 @@ export const translateY = (offset, ...objects) => translate([0, offset, 0], obje
|
|
|
62
59
|
* @return {Object|Array} the translated object, or a list of translated objects
|
|
63
60
|
* @alias module:modeling/transforms.translateZ
|
|
64
61
|
*/
|
|
65
|
-
export const translateZ = (offset, ...objects) => translate([0, 0, offset], objects)
|
|
62
|
+
export const translateZ = (offset, ...objects) => translate([0, 0, offset], ...objects)
|
package/src/primitives/arc.js
CHANGED
|
@@ -17,6 +17,8 @@ import { isGT, isGTE, isNumberArray } from './commonChecks.js'
|
|
|
17
17
|
* @param {boolean} [options.makeTangent=false] - adds line segments at both ends of the arc to ensure that the gradients at the edges are tangent
|
|
18
18
|
* @returns {Path2} new 2D path
|
|
19
19
|
* @alias module:modeling/primitives.arc
|
|
20
|
+
* @example
|
|
21
|
+
* let myshape = arc({ center: [-1, -1], radius: 2, endAngle: (TAU / 4)})
|
|
20
22
|
*/
|
|
21
23
|
export const arc = (options) => {
|
|
22
24
|
const defaults = {
|
|
@@ -13,7 +13,7 @@ test('arc (defaults)', (t) => {
|
|
|
13
13
|
const obs = path2.toPoints(geometry)
|
|
14
14
|
|
|
15
15
|
t.notThrows(() => path2.validate(geometry))
|
|
16
|
-
t.
|
|
16
|
+
t.is(obs.length, 33)
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
test('arc (options)', (t) => {
|
|
@@ -41,7 +41,7 @@ test('arc (options)', (t) => {
|
|
|
41
41
|
let obs = path2.toPoints(geometry)
|
|
42
42
|
|
|
43
43
|
t.notThrows(() => path2.validate(geometry))
|
|
44
|
-
t.
|
|
44
|
+
t.is(obs.length, 17)
|
|
45
45
|
t.true(comparePoints(obs, exp))
|
|
46
46
|
|
|
47
47
|
// test radius
|
|
@@ -68,7 +68,7 @@ test('arc (options)', (t) => {
|
|
|
68
68
|
obs = path2.toPoints(geometry)
|
|
69
69
|
|
|
70
70
|
t.notThrows(() => path2.validate(geometry))
|
|
71
|
-
t.
|
|
71
|
+
t.is(obs.length, 17)
|
|
72
72
|
t.true(comparePoints(obs, exp))
|
|
73
73
|
|
|
74
74
|
// test startAngle
|
|
@@ -92,7 +92,7 @@ test('arc (options)', (t) => {
|
|
|
92
92
|
obs = path2.toPoints(geometry)
|
|
93
93
|
|
|
94
94
|
t.notThrows(() => path2.validate(geometry))
|
|
95
|
-
t.
|
|
95
|
+
t.is(obs.length, 14)
|
|
96
96
|
t.true(comparePoints(obs, exp))
|
|
97
97
|
|
|
98
98
|
// test endAngle
|
|
@@ -108,7 +108,7 @@ test('arc (options)', (t) => {
|
|
|
108
108
|
obs = path2.toPoints(geometry)
|
|
109
109
|
|
|
110
110
|
t.notThrows(() => path2.validate(geometry))
|
|
111
|
-
t.
|
|
111
|
+
t.is(obs.length, 6)
|
|
112
112
|
t.true(comparePoints(obs, exp))
|
|
113
113
|
|
|
114
114
|
// test makeTangent
|
|
@@ -137,7 +137,7 @@ test('arc (options)', (t) => {
|
|
|
137
137
|
obs = path2.toPoints(geometry)
|
|
138
138
|
|
|
139
139
|
t.notThrows(() => path2.validate(geometry))
|
|
140
|
-
t.
|
|
140
|
+
t.is(obs.length, 19)
|
|
141
141
|
t.true(comparePoints(obs, exp))
|
|
142
142
|
|
|
143
143
|
// test segments
|
|
@@ -156,7 +156,7 @@ test('arc (options)', (t) => {
|
|
|
156
156
|
obs = path2.toPoints(geometry)
|
|
157
157
|
|
|
158
158
|
t.notThrows(() => path2.validate(geometry))
|
|
159
|
-
t.
|
|
159
|
+
t.is(obs.length, 9)
|
|
160
160
|
t.true(comparePoints(obs, exp))
|
|
161
161
|
})
|
|
162
162
|
|
|
@@ -173,7 +173,7 @@ test('arc (rotations)', (t) => {
|
|
|
173
173
|
let obs = path2.toPoints(geometry)
|
|
174
174
|
|
|
175
175
|
t.notThrows(() => path2.validate(geometry))
|
|
176
|
-
t.
|
|
176
|
+
t.is(obs.length, 6)
|
|
177
177
|
t.true(comparePoints(obs, exp))
|
|
178
178
|
|
|
179
179
|
exp = [
|
|
@@ -192,7 +192,7 @@ test('arc (rotations)', (t) => {
|
|
|
192
192
|
obs = path2.toPoints(geometry)
|
|
193
193
|
|
|
194
194
|
t.notThrows(() => path2.validate(geometry))
|
|
195
|
-
t.
|
|
195
|
+
t.is(obs.length, 10)
|
|
196
196
|
t.true(comparePoints(obs, exp))
|
|
197
197
|
|
|
198
198
|
exp = [
|
|
@@ -211,7 +211,7 @@ test('arc (rotations)', (t) => {
|
|
|
211
211
|
obs = path2.toPoints(geometry)
|
|
212
212
|
|
|
213
213
|
t.notThrows(() => path2.validate(geometry))
|
|
214
|
-
t.
|
|
214
|
+
t.is(obs.length, 10)
|
|
215
215
|
t.true(comparePoints(obs, exp))
|
|
216
216
|
|
|
217
217
|
exp = [[-1.8369701987210297e-16, -1]]
|
|
@@ -219,6 +219,6 @@ test('arc (rotations)', (t) => {
|
|
|
219
219
|
obs = path2.toPoints(geometry)
|
|
220
220
|
|
|
221
221
|
t.notThrows(() => path2.validate(geometry))
|
|
222
|
-
t.
|
|
222
|
+
t.is(obs.length, 1)
|
|
223
223
|
t.true(comparePoints(obs, exp))
|
|
224
224
|
})
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
+
import { geom2 } from '../geometries/index.js'
|
|
4
|
+
|
|
3
5
|
import { TAU } from '../maths/constants.js'
|
|
4
6
|
|
|
5
|
-
import {
|
|
7
|
+
import { measureArea } from '../measurements/measureArea.js'
|
|
6
8
|
|
|
7
9
|
import { comparePoints } from '../../test/helpers/index.js'
|
|
8
10
|
|
|
@@ -13,7 +15,8 @@ test('circle (defaults)', (t) => {
|
|
|
13
15
|
const pts = geom2.toPoints(geometry)
|
|
14
16
|
|
|
15
17
|
t.notThrows(() => geom2.validate(geometry))
|
|
16
|
-
t.
|
|
18
|
+
t.is(measureArea(geometry), 3.1214451522580537)
|
|
19
|
+
t.is(pts.length, 32)
|
|
17
20
|
})
|
|
18
21
|
|
|
19
22
|
test('circle (options)', (t) => {
|
|
@@ -56,7 +59,8 @@ test('circle (options)', (t) => {
|
|
|
56
59
|
]
|
|
57
60
|
|
|
58
61
|
t.notThrows(() => geom2.validate(geometry))
|
|
59
|
-
t.
|
|
62
|
+
t.is(measureArea(geometry), 38.23770311516116)
|
|
63
|
+
t.is(pts.length, 32)
|
|
60
64
|
t.true(comparePoints(pts, exp))
|
|
61
65
|
|
|
62
66
|
// test radius
|
|
@@ -82,7 +86,8 @@ test('circle (options)', (t) => {
|
|
|
82
86
|
]
|
|
83
87
|
|
|
84
88
|
t.notThrows(() => geom2.validate(geometry))
|
|
85
|
-
t.
|
|
89
|
+
t.is(measureArea(geometry), 37.5029763717788)
|
|
90
|
+
t.is(pts.length, 16)
|
|
86
91
|
t.true(comparePoints(pts, exp))
|
|
87
92
|
|
|
88
93
|
// test startAngle
|
|
@@ -106,7 +111,8 @@ test('circle (options)', (t) => {
|
|
|
106
111
|
]
|
|
107
112
|
|
|
108
113
|
t.notThrows(() => geom2.validate(geometry))
|
|
109
|
-
t.
|
|
114
|
+
t.is(measureArea(geometry), 28.127232278834093)
|
|
115
|
+
t.is(pts.length, 14)
|
|
110
116
|
t.true(comparePoints(pts, exp))
|
|
111
117
|
|
|
112
118
|
// test endAngle
|
|
@@ -122,7 +128,8 @@ test('circle (options)', (t) => {
|
|
|
122
128
|
]
|
|
123
129
|
|
|
124
130
|
t.notThrows(() => geom2.validate(geometry))
|
|
125
|
-
t.
|
|
131
|
+
t.is(measureArea(geometry), 9.3757440929447)
|
|
132
|
+
t.is(pts.length, 6)
|
|
126
133
|
t.true(comparePoints(pts, exp))
|
|
127
134
|
|
|
128
135
|
// test full rotation with non-zero startAngle
|
|
@@ -130,7 +137,8 @@ test('circle (options)', (t) => {
|
|
|
130
137
|
pts = geom2.toPoints(geometry)
|
|
131
138
|
|
|
132
139
|
t.notThrows(() => geom2.validate(geometry))
|
|
133
|
-
t.
|
|
140
|
+
t.is(measureArea(geometry), 3.1214451522580537)
|
|
141
|
+
t.is(pts.length, 32)
|
|
134
142
|
|
|
135
143
|
// test segments
|
|
136
144
|
geometry = circle({ radius: 3.5, segments: 5 })
|
|
@@ -144,7 +152,8 @@ test('circle (options)', (t) => {
|
|
|
144
152
|
]
|
|
145
153
|
|
|
146
154
|
t.notThrows(() => geom2.validate(geometry))
|
|
147
|
-
t.
|
|
155
|
+
t.is(measureArea(geometry), 29.126105811539073)
|
|
156
|
+
t.is(pts.length, 5)
|
|
148
157
|
t.true(comparePoints(pts, exp))
|
|
149
158
|
})
|
|
150
159
|
|
|
@@ -152,5 +161,6 @@ test('circle (radius zero)', (t) => {
|
|
|
152
161
|
const geometry = circle({ radius: 0 })
|
|
153
162
|
const pts = geom2.toPoints(geometry)
|
|
154
163
|
t.notThrows(() => geom2.validate(geometry))
|
|
164
|
+
t.is(measureArea(geometry), 0)
|
|
155
165
|
t.is(pts.length, 0)
|
|
156
166
|
})
|
|
@@ -2,6 +2,8 @@ import test from 'ava'
|
|
|
2
2
|
|
|
3
3
|
import { geom3 } from '../geometries/index.js'
|
|
4
4
|
|
|
5
|
+
import { measureArea, measureVolume } from '../measurements/index.js'
|
|
6
|
+
|
|
5
7
|
import { cube } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePolygonsAsPoints } from '../../test/helpers/index.js'
|
|
@@ -10,6 +12,8 @@ test('cube (defaults)', (t) => {
|
|
|
10
12
|
const obs = cube()
|
|
11
13
|
const pts = geom3.toPoints(obs)
|
|
12
14
|
t.notThrows(() => geom3.validate(obs))
|
|
15
|
+
t.is(measureArea(obs), 24)
|
|
16
|
+
t.is(measureVolume(obs), 7.999999999999999)
|
|
13
17
|
t.is(pts.length, 6)
|
|
14
18
|
})
|
|
15
19
|
|
|
@@ -27,6 +31,8 @@ test('cube (options)', (t) => {
|
|
|
27
31
|
]
|
|
28
32
|
|
|
29
33
|
t.notThrows(() => geom3.validate(obs))
|
|
34
|
+
t.is(measureArea(obs), 294)
|
|
35
|
+
t.is(measureVolume(obs), 343)
|
|
30
36
|
t.is(pts.length, 6)
|
|
31
37
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
32
38
|
|
|
@@ -43,6 +49,8 @@ test('cube (options)', (t) => {
|
|
|
43
49
|
]
|
|
44
50
|
|
|
45
51
|
t.notThrows(() => geom3.validate(obs))
|
|
52
|
+
t.is(measureArea(obs), 294)
|
|
53
|
+
t.is(measureVolume(obs), 343)
|
|
46
54
|
t.is(pts.length, 6)
|
|
47
55
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
48
56
|
})
|
|
@@ -51,5 +59,7 @@ test('cube (zero size)', (t) => {
|
|
|
51
59
|
const obs = cube({ size: 0 })
|
|
52
60
|
const pts = geom3.toPoints(obs)
|
|
53
61
|
t.notThrows(() => geom3.validate(obs))
|
|
62
|
+
t.is(measureArea(obs), 0)
|
|
63
|
+
t.is(measureVolume(obs), 0)
|
|
54
64
|
t.is(pts.length, 0)
|
|
55
65
|
})
|
|
@@ -2,6 +2,8 @@ import test from 'ava'
|
|
|
2
2
|
|
|
3
3
|
import { geom3 } from '../geometries/index.js'
|
|
4
4
|
|
|
5
|
+
import { measureArea, measureVolume } from '../measurements/index.js'
|
|
6
|
+
|
|
5
7
|
import { cuboid } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePolygonsAsPoints } from '../../test/helpers/index.js'
|
|
@@ -18,6 +20,8 @@ test('cuboid (defaults)', (t) => {
|
|
|
18
20
|
[[-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]]
|
|
19
21
|
]
|
|
20
22
|
t.notThrows(() => geom3.validate(obs))
|
|
23
|
+
t.is(measureArea(obs), 24)
|
|
24
|
+
t.is(measureVolume(obs), 7.999999999999999)
|
|
21
25
|
t.is(pts.length, 6)
|
|
22
26
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
23
27
|
})
|
|
@@ -36,6 +40,8 @@ test('cuboid (options)', (t) => {
|
|
|
36
40
|
]
|
|
37
41
|
|
|
38
42
|
t.notThrows(() => geom3.validate(obs))
|
|
43
|
+
t.is(measureArea(obs), 216)
|
|
44
|
+
t.is(measureVolume(obs), 216)
|
|
39
45
|
t.is(pts.length, 6)
|
|
40
46
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
41
47
|
|
|
@@ -52,6 +58,8 @@ test('cuboid (options)', (t) => {
|
|
|
52
58
|
]
|
|
53
59
|
|
|
54
60
|
t.notThrows(() => geom3.validate(obs))
|
|
61
|
+
t.is(measureArea(obs), 97.5)
|
|
62
|
+
t.is(measureVolume(obs), 47.25)
|
|
55
63
|
t.is(pts.length, 6)
|
|
56
64
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
57
65
|
})
|
|
@@ -60,5 +68,7 @@ test('cuboid (zero size)', (t) => {
|
|
|
60
68
|
const obs = cuboid({ size: [1, 1, 0] })
|
|
61
69
|
const pts = geom3.toPoints(obs)
|
|
62
70
|
t.notThrows(() => geom3.validate(obs))
|
|
71
|
+
t.is(measureArea(obs), 0)
|
|
72
|
+
t.is(measureVolume(obs), 0)
|
|
63
73
|
t.is(pts.length, 0)
|
|
64
74
|
})
|