@jscad/modeling 3.0.0-alpha.0 → 3.0.1-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 +35 -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/poly3/type.d.ts +1 -1
- package/src/geometries/slice/validate.js +1 -2
- 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/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/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/splitPolygonByPlane.d.ts +33 -0
- 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/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 +4 -2
- 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/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,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
|
})
|
|
@@ -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 { cylinder } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePolygonsAsPoints } from '../../test/helpers/index.js'
|
|
@@ -11,6 +13,8 @@ test('cylinder (defaults)', (t) => {
|
|
|
11
13
|
const pts = geom3.toPoints(obs)
|
|
12
14
|
|
|
13
15
|
t.notThrows(() => geom3.validate(obs))
|
|
16
|
+
t.is(measureArea(obs), 18.789084266699856)
|
|
17
|
+
t.is(measureVolume(obs), 6.2428903045161)
|
|
14
18
|
t.is(pts.length, 96)
|
|
15
19
|
})
|
|
16
20
|
|
|
@@ -18,6 +22,8 @@ test('cylinder (zero height)', (t) => {
|
|
|
18
22
|
const obs = cylinder({ height: 0 })
|
|
19
23
|
const pts = geom3.toPoints(obs)
|
|
20
24
|
t.notThrows(() => geom3.validate(obs))
|
|
25
|
+
t.is(measureArea(obs), 0)
|
|
26
|
+
t.is(measureVolume(obs), 0)
|
|
21
27
|
t.is(pts.length, 0)
|
|
22
28
|
})
|
|
23
29
|
|
|
@@ -25,6 +31,8 @@ test('cylinder (zero radius)', (t) => {
|
|
|
25
31
|
const obs = cylinder({ radius: 0 })
|
|
26
32
|
const pts = geom3.toPoints(obs)
|
|
27
33
|
t.notThrows(() => geom3.validate(obs))
|
|
34
|
+
t.is(measureArea(obs), 0)
|
|
35
|
+
t.is(measureVolume(obs), 0)
|
|
28
36
|
t.is(pts.length, 0)
|
|
29
37
|
})
|
|
30
38
|
|
|
@@ -55,6 +63,8 @@ test('cylinder (options)', (t) => {
|
|
|
55
63
|
]
|
|
56
64
|
|
|
57
65
|
t.notThrows(() => geom3.validate(obs))
|
|
66
|
+
t.is(measureArea(obs), 311.1986222206015)
|
|
67
|
+
t.is(measureVolume(obs), 380.4226065180614)
|
|
58
68
|
t.is(pts.length, 15)
|
|
59
69
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
60
70
|
|
|
@@ -85,6 +95,8 @@ test('cylinder (options)', (t) => {
|
|
|
85
95
|
]
|
|
86
96
|
|
|
87
97
|
t.notThrows(() => geom3.validate(obs))
|
|
98
|
+
t.is(measureArea(obs), 16.51098762732523)
|
|
99
|
+
t.is(measureVolume(obs), 4.755282581475773)
|
|
88
100
|
t.is(pts.length, 15)
|
|
89
101
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
90
102
|
})
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
+
import { geom3 } from '../geometries/index.js'
|
|
4
|
+
|
|
3
5
|
import { TAU } from '../maths/constants.js'
|
|
4
6
|
|
|
5
|
-
import {
|
|
7
|
+
import { measureArea, measureVolume } from '../measurements/index.js'
|
|
6
8
|
|
|
7
9
|
import { cylinderElliptic } from './index.js'
|
|
8
10
|
|
|
@@ -13,6 +15,8 @@ test('cylinderElliptic (defaults)', (t) => {
|
|
|
13
15
|
const pts = geom3.toPoints(obs)
|
|
14
16
|
|
|
15
17
|
t.notThrows(() => geom3.validate(obs))
|
|
18
|
+
t.is(measureArea(obs), 18.789084266699856)
|
|
19
|
+
t.is(measureVolume(obs), 6.2428903045161)
|
|
16
20
|
t.is(pts.length, 96)
|
|
17
21
|
})
|
|
18
22
|
|
|
@@ -72,6 +76,8 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
72
76
|
]
|
|
73
77
|
|
|
74
78
|
t.notThrows(() => geom3.validate(obs))
|
|
79
|
+
t.is(measureArea(obs), 68.11657082460499)
|
|
80
|
+
t.is(measureVolume(obs), 30.00000000000001)
|
|
75
81
|
t.is(pts.length, 36)
|
|
76
82
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
77
83
|
|
|
@@ -130,6 +136,8 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
130
136
|
]
|
|
131
137
|
|
|
132
138
|
t.notThrows(() => geom3.validate(obs))
|
|
139
|
+
t.is(measureArea(obs), 32.34210030145122)
|
|
140
|
+
t.is(measureVolume(obs), 12.999999999999991)
|
|
133
141
|
t.is(pts.length, 48)
|
|
134
142
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
135
143
|
|
|
@@ -138,6 +146,8 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
138
146
|
pts = geom3.toPoints(obs)
|
|
139
147
|
|
|
140
148
|
t.notThrows(() => geom3.validate(obs))
|
|
149
|
+
t.is(measureArea(obs), 22.17105015072561)
|
|
150
|
+
t.is(measureVolume(obs), 6.5)
|
|
141
151
|
t.is(pts.length, 28)
|
|
142
152
|
|
|
143
153
|
// test startAngle and endAngle
|
|
@@ -145,6 +155,8 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
145
155
|
pts = geom3.toPoints(obs)
|
|
146
156
|
|
|
147
157
|
t.notThrows(() => geom3.validate(obs))
|
|
158
|
+
t.is(measureArea(obs), 18.78908426669986)
|
|
159
|
+
t.is(measureVolume(obs), 6.2428903045160995)
|
|
148
160
|
t.is(pts.length, 96)
|
|
149
161
|
|
|
150
162
|
// test segments
|
|
@@ -152,6 +164,8 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
152
164
|
pts = geom3.toPoints(obs)
|
|
153
165
|
|
|
154
166
|
t.notThrows(() => geom3.validate(obs))
|
|
167
|
+
t.is(measureArea(obs), 17.902724085175244)
|
|
168
|
+
t.is(measureVolume(obs), 5.6568542494923815)
|
|
155
169
|
t.is(pts.length, 24)
|
|
156
170
|
|
|
157
171
|
// test center
|
|
@@ -193,6 +207,8 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
193
207
|
]
|
|
194
208
|
|
|
195
209
|
t.notThrows(() => geom3.validate(obs))
|
|
210
|
+
t.is(measureArea(obs), 24.025659003016692)
|
|
211
|
+
t.is(measureVolume(obs), 8.485281374238578)
|
|
196
212
|
t.is(pts.length, 24)
|
|
197
213
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
198
214
|
})
|
|
@@ -202,6 +218,8 @@ test('cylinderElliptic (cone)', (t) => {
|
|
|
202
218
|
const pts = geom3.toPoints(obs)
|
|
203
219
|
|
|
204
220
|
t.notThrows(() => geom3.validate(obs))
|
|
221
|
+
t.is(measureArea(obs), 10.128239395900382)
|
|
222
|
+
t.is(measureVolume(obs), 2.080963434838702)
|
|
205
223
|
t.is(pts.length, 64)
|
|
206
224
|
})
|
|
207
225
|
|
|
@@ -210,5 +228,7 @@ test('cylinderElliptic (squished)', (t) => {
|
|
|
210
228
|
const pts = geom3.toPoints(obs)
|
|
211
229
|
|
|
212
230
|
t.notThrows(() => geom3.validate(obs))
|
|
231
|
+
t.is(measureArea(obs), 8.47213595499958)
|
|
232
|
+
t.is(measureVolume(obs), 0.6666666666666666)
|
|
213
233
|
t.is(pts.length, 8)
|
|
214
234
|
})
|
|
@@ -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/index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePoints } from '../../test/helpers/index.js'
|
|
8
10
|
|
|
@@ -13,7 +15,8 @@ test('ellipse (defaults)', (t) => {
|
|
|
13
15
|
const obs = geom2.toPoints(geometry)
|
|
14
16
|
|
|
15
17
|
t.notThrows(() => geom2.validate(geometry))
|
|
16
|
-
t.
|
|
18
|
+
t.is(measureArea(geometry), 3.1214451522580537)
|
|
19
|
+
t.is(obs.length, 32)
|
|
17
20
|
})
|
|
18
21
|
|
|
19
22
|
test('ellipse (options)', (t) => {
|
|
@@ -56,7 +59,8 @@ test('ellipse (options)', (t) => {
|
|
|
56
59
|
]
|
|
57
60
|
|
|
58
61
|
t.notThrows(() => geom2.validate(geometry))
|
|
59
|
-
t.
|
|
62
|
+
t.is(measureArea(geometry), 3.121445152258051)
|
|
63
|
+
t.is(obs.length, 32)
|
|
60
64
|
t.true(comparePoints(obs, exp))
|
|
61
65
|
|
|
62
66
|
// test radius
|
|
@@ -82,7 +86,8 @@ test('ellipse (options)', (t) => {
|
|
|
82
86
|
]
|
|
83
87
|
|
|
84
88
|
t.notThrows(() => geom2.validate(geometry))
|
|
85
|
-
t.
|
|
89
|
+
t.is(measureArea(geometry), 45.92201188381077)
|
|
90
|
+
t.is(obs.length, 16)
|
|
86
91
|
t.true(comparePoints(obs, exp))
|
|
87
92
|
|
|
88
93
|
// test startAngle
|
|
@@ -106,7 +111,8 @@ test('ellipse (options)', (t) => {
|
|
|
106
111
|
]
|
|
107
112
|
|
|
108
113
|
t.notThrows(() => geom2.validate(geometry))
|
|
109
|
-
t.
|
|
114
|
+
t.is(measureArea(geometry), 34.44150891285808)
|
|
115
|
+
t.is(obs.length, 14)
|
|
110
116
|
t.true(comparePoints(obs, exp))
|
|
111
117
|
|
|
112
118
|
// test endAngle
|
|
@@ -122,7 +128,8 @@ test('ellipse (options)', (t) => {
|
|
|
122
128
|
]
|
|
123
129
|
|
|
124
130
|
t.notThrows(() => geom2.validate(geometry))
|
|
125
|
-
t.
|
|
131
|
+
t.is(measureArea(geometry), 11.480502970952696)
|
|
132
|
+
t.is(obs.length, 6)
|
|
126
133
|
t.true(comparePoints(obs, exp))
|
|
127
134
|
|
|
128
135
|
// test full rotation with non-zero startAngle
|
|
@@ -130,18 +137,21 @@ test('ellipse (options)', (t) => {
|
|
|
130
137
|
obs = geom2.toPoints(geometry)
|
|
131
138
|
|
|
132
139
|
t.notThrows(() => geom2.validate(geometry))
|
|
133
|
-
t.
|
|
140
|
+
t.is(measureArea(geometry), 3.1214451522580537)
|
|
141
|
+
t.is(obs.length, 32)
|
|
134
142
|
|
|
135
143
|
// test segments
|
|
136
144
|
geometry = ellipse({ segments: 72 })
|
|
137
145
|
obs = geom2.toPoints(geometry)
|
|
138
146
|
t.notThrows(() => geom2.validate(geometry))
|
|
139
|
-
t.
|
|
147
|
+
t.is(measureArea(geometry), 3.1376067389156956)
|
|
148
|
+
t.is(obs.length, 72)
|
|
140
149
|
})
|
|
141
150
|
|
|
142
151
|
test('ellipse (zero radius)', (t) => {
|
|
143
152
|
const geometry = ellipse({ radius: [1, 0] })
|
|
144
153
|
const obs = geom2.toPoints(geometry)
|
|
145
154
|
t.notThrows(() => geom2.validate(geometry))
|
|
155
|
+
t.is(measureArea(geometry), 0)
|
|
146
156
|
t.is(obs.length, 0)
|
|
147
157
|
})
|
|
@@ -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 { ellipsoid } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePolygonsAsPoints } from '../../test/helpers/index.js'
|
|
@@ -11,6 +13,8 @@ test('ellipsoid (defaults)', (t) => {
|
|
|
11
13
|
const pts = geom3.toPoints(obs)
|
|
12
14
|
|
|
13
15
|
t.notThrows(() => geom3.validate(obs))
|
|
16
|
+
t.is(measureArea(obs), 12.465694088650583)
|
|
17
|
+
t.is(measureVolume(obs), 4.121941740785839)
|
|
14
18
|
t.is(pts.length, 512)
|
|
15
19
|
})
|
|
16
20
|
|
|
@@ -141,6 +145,8 @@ test('ellipsoid (options)', (t) => {
|
|
|
141
145
|
[[0, 0, 7], [1.5000000000000004, 0, 6.06217782649107], [1.2990381056766578, 1.2500000000000013, 6.06217782649107]]
|
|
142
146
|
]
|
|
143
147
|
t.notThrows(() => geom3.validate(obs))
|
|
148
|
+
t.is(measureArea(obs), 291.2703265603712)
|
|
149
|
+
t.is(measureVolume(obs), 391.86533479473223)
|
|
144
150
|
t.is(pts.length, 72)
|
|
145
151
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
146
152
|
|
|
@@ -148,6 +154,8 @@ test('ellipsoid (options)', (t) => {
|
|
|
148
154
|
obs = ellipsoid({ segments: 8 })
|
|
149
155
|
pts = geom3.toPoints(obs)
|
|
150
156
|
t.notThrows(() => geom3.validate(obs))
|
|
157
|
+
t.is(measureArea(obs), 11.013439076647456)
|
|
158
|
+
t.is(measureVolume(obs), 3.2189514164974597)
|
|
151
159
|
t.is(pts.length, 32)
|
|
152
160
|
|
|
153
161
|
obs = ellipsoid({ center: [-3, 5, 7], segments: 8 })
|
|
@@ -204,6 +212,8 @@ test('ellipsoid (options)', (t) => {
|
|
|
204
212
|
]
|
|
205
213
|
|
|
206
214
|
t.notThrows(() => geom3.validate(obs))
|
|
215
|
+
t.is(measureArea(obs), 11.013439076647467)
|
|
216
|
+
t.is(measureVolume(obs), 3.218951416497485)
|
|
207
217
|
t.is(pts.length, 32)
|
|
208
218
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
209
219
|
})
|
|
@@ -212,5 +222,7 @@ test('ellipsoid (zero radius)', (t) => {
|
|
|
212
222
|
const obs = ellipsoid({ radius: [1, 1, 0] })
|
|
213
223
|
const pts = geom3.toPoints(obs)
|
|
214
224
|
t.notThrows(() => geom3.validate(obs))
|
|
225
|
+
t.is(measureArea(obs), 0)
|
|
226
|
+
t.is(measureVolume(obs), 0)
|
|
215
227
|
t.is(pts.length, 0)
|
|
216
228
|
})
|
|
@@ -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 { geodesicSphere } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePolygonsAsPoints } from '../../test/helpers/index.js'
|
|
@@ -41,6 +43,8 @@ test('geodesicSphere (options)', (t) => {
|
|
|
41
43
|
]
|
|
42
44
|
|
|
43
45
|
t.notThrows(() => geom3.validate(obs))
|
|
46
|
+
t.is(measureArea(obs), 239.3635345818432)
|
|
47
|
+
t.is(measureVolume(obs), 317.0188387650327)
|
|
44
48
|
t.is(pts.length, 20)
|
|
45
49
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
46
50
|
|
|
@@ -49,6 +53,8 @@ test('geodesicSphere (options)', (t) => {
|
|
|
49
53
|
pts = geom3.toPoints(obs)
|
|
50
54
|
|
|
51
55
|
t.notThrows.skip(() => geom3.validate(obs))
|
|
56
|
+
t.is(measureArea(obs), 303.76605423529395)
|
|
57
|
+
t.is(measureVolume(obs), 492.6739732379337)
|
|
52
58
|
t.is(pts.length, 180)
|
|
53
59
|
})
|
|
54
60
|
|
|
@@ -56,5 +62,7 @@ test('geodesicSphere (zero radius)', (t) => {
|
|
|
56
62
|
const obs = geodesicSphere({ radius: 0 })
|
|
57
63
|
const pts = geom3.toPoints(obs)
|
|
58
64
|
t.notThrows(() => geom3.validate(obs))
|
|
65
|
+
t.is(measureArea(obs), 0)
|
|
66
|
+
t.is(measureVolume(obs), 0)
|
|
59
67
|
t.is(pts.length, 0)
|
|
60
68
|
})
|
|
@@ -4,6 +4,7 @@ import type { Geom2 } from '../geometries/geom2/type.d.ts'
|
|
|
4
4
|
export interface PolygonOptions {
|
|
5
5
|
points: Array<Vec2> | Array<Array<Vec2>>
|
|
6
6
|
paths?: Array<number> | Array<Array<number>>
|
|
7
|
+
orientation?: 'counterclockwise' | 'clockwise'
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export function polygon(options: PolygonOptions): Geom2
|
|
@@ -2,10 +2,13 @@ import * as geom2 from '../geometries/geom2/index.js'
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Construct a polygon in two dimensional space from a list of points, or a list of points and paths.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
|
+
* NOTE: The ordering of points is important, and must define a counter clockwise rotation of points.
|
|
7
|
+
*
|
|
6
8
|
* @param {object} options - options for construction
|
|
7
9
|
* @param {Array} options.points - points of the polygon : either flat or nested array of 2D points
|
|
8
10
|
* @param {Array} [options.paths] - paths of the polygon : either flat or nested array of point indexes
|
|
11
|
+
* @param {String} [options.orientation='counterclockwise'] - orientation of points
|
|
9
12
|
* @returns {Geom2} new 2D geometry
|
|
10
13
|
* @alias module:modeling/primitives.polygon
|
|
11
14
|
*
|
|
@@ -24,9 +27,10 @@ import * as geom2 from '../geometries/geom2/index.js'
|
|
|
24
27
|
export const polygon = (options) => {
|
|
25
28
|
const defaults = {
|
|
26
29
|
points: [],
|
|
27
|
-
paths: []
|
|
30
|
+
paths: [],
|
|
31
|
+
orientation: 'counterclockwise'
|
|
28
32
|
}
|
|
29
|
-
const { points, paths } = Object.assign({}, defaults, options)
|
|
33
|
+
const { points, paths, orientation } = Object.assign({}, defaults, options)
|
|
30
34
|
|
|
31
35
|
if (!(Array.isArray(points) && Array.isArray(paths))) throw new Error('points and paths must be arrays')
|
|
32
36
|
|
|
@@ -63,5 +67,10 @@ export const polygon = (options) => {
|
|
|
63
67
|
const setOfPoints = path.map((index) => allPoints[index])
|
|
64
68
|
outlines.push(setOfPoints)
|
|
65
69
|
})
|
|
66
|
-
|
|
70
|
+
|
|
71
|
+
let geometry = geom2.create(outlines)
|
|
72
|
+
if (orientation === 'clockwise') {
|
|
73
|
+
geometry = geom2.reverse(geometry)
|
|
74
|
+
}
|
|
75
|
+
return geometry
|
|
67
76
|
}
|
|
@@ -2,6 +2,8 @@ import test from 'ava'
|
|
|
2
2
|
|
|
3
3
|
import { geom2 } from '../geometries/index.js'
|
|
4
4
|
|
|
5
|
+
import { measureArea } from '../measurements/index.js'
|
|
6
|
+
|
|
5
7
|
import { polygon } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePoints } from '../../test/helpers/index.js'
|
|
@@ -13,6 +15,7 @@ test('polygon: providing only object.points creates expected geometry', (t) => {
|
|
|
13
15
|
let exp = [[0, 0], [100, 0], [130, 50], [30, 50]]
|
|
14
16
|
|
|
15
17
|
t.notThrows(() => geom2.validate(geometry))
|
|
18
|
+
t.is(measureArea(geometry), 5000)
|
|
16
19
|
t.true(comparePoints(obs, exp))
|
|
17
20
|
|
|
18
21
|
geometry = polygon({ points: [[[0, 0], [100, 0], [0, 100]], [[10, 10], [80, 10], [10, 80]]] })
|
|
@@ -21,6 +24,7 @@ test('polygon: providing only object.points creates expected geometry', (t) => {
|
|
|
21
24
|
exp = [[0, 0], [100, 0], [0, 100], [10, 10], [80, 10], [10, 80]]
|
|
22
25
|
|
|
23
26
|
t.notThrows(() => geom2.validate(geometry))
|
|
27
|
+
t.is(measureArea(geometry), 7450)
|
|
24
28
|
t.true(comparePoints(obs, exp))
|
|
25
29
|
})
|
|
26
30
|
|
|
@@ -31,6 +35,7 @@ test('polygon: providing object.points (array) and object.path (array) creates e
|
|
|
31
35
|
let exp = [[30, 50], [130, 50], [100, 0], [0, 0]]
|
|
32
36
|
|
|
33
37
|
t.notThrows(() => geom2.validate(geometry))
|
|
38
|
+
t.is(measureArea(geometry), -5000)
|
|
34
39
|
t.true(comparePoints(obs, exp))
|
|
35
40
|
|
|
36
41
|
// multiple paths
|
|
@@ -40,6 +45,7 @@ test('polygon: providing object.points (array) and object.path (array) creates e
|
|
|
40
45
|
exp = [[0, 0], [100, 0], [0, 100], [10, 10], [80, 10], [10, 80]]
|
|
41
46
|
|
|
42
47
|
t.notThrows(() => geom2.validate(geometry))
|
|
48
|
+
t.is(measureArea(geometry), 7450)
|
|
43
49
|
t.true(comparePoints(obs, exp))
|
|
44
50
|
|
|
45
51
|
// multiple points and paths
|
|
@@ -49,5 +55,14 @@ test('polygon: providing object.points (array) and object.path (array) creates e
|
|
|
49
55
|
exp = [[0, 0], [100, 0], [0, 100], [10, 10], [80, 10], [10, 80]]
|
|
50
56
|
|
|
51
57
|
t.notThrows(() => geom2.validate(geometry))
|
|
58
|
+
t.is(measureArea(geometry), 7450)
|
|
52
59
|
t.true(comparePoints(obs, exp))
|
|
53
60
|
})
|
|
61
|
+
|
|
62
|
+
test('polygon: clockwise points', (t) => {
|
|
63
|
+
const poly = polygon({
|
|
64
|
+
points: [[-10, -0], [-10, -10], [-15, -5]],
|
|
65
|
+
orientation: 'clockwise'
|
|
66
|
+
})
|
|
67
|
+
t.is(measureArea(poly), 25)
|
|
68
|
+
})
|
|
@@ -5,6 +5,7 @@ import { isNumberArray } from './commonChecks.js'
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Construct a polyhedron in three dimensional space from the given set of 3D vertices and faces.
|
|
8
|
+
*
|
|
8
9
|
* The faces can define outward or inward facing polygons (orientation).
|
|
9
10
|
* However, each face must define a counterclockwise rotation of vertices which follows the right hand rule.
|
|
10
11
|
* @param {object} options - options for construction
|
|
@@ -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 { polyhedron } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePolygonsAsPoints } from '../../test/helpers/index.js'
|
|
@@ -22,7 +24,9 @@ test('polyhedron (points and faces)', (t) => {
|
|
|
22
24
|
[[-1, -1, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]]
|
|
23
25
|
]
|
|
24
26
|
t.notThrows(() => geom3.validate(obs))
|
|
25
|
-
t.
|
|
27
|
+
t.is(measureArea(obs), 24)
|
|
28
|
+
t.is(measureVolume(obs), 7.999999999999999)
|
|
29
|
+
t.is(pts.length, 6)
|
|
26
30
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
27
31
|
|
|
28
32
|
// test orientation
|
|
@@ -39,6 +43,8 @@ test('polyhedron (points and faces)', (t) => {
|
|
|
39
43
|
[[-10, 10, 0], [10, -10, 0], [-10, -10, 0]]
|
|
40
44
|
]
|
|
41
45
|
t.notThrows(() => geom3.validate(obs))
|
|
42
|
-
t.
|
|
46
|
+
t.is(measureArea(obs), 965.6854249492379)
|
|
47
|
+
t.is(measureVolume(obs), 1333.3333333333333)
|
|
48
|
+
t.is(pts.length, 6)
|
|
43
49
|
t.true(comparePolygonsAsPoints(pts, exp))
|
|
44
50
|
})
|
|
@@ -2,6 +2,8 @@ import test from 'ava'
|
|
|
2
2
|
|
|
3
3
|
import { geom2 } from '../geometries/index.js'
|
|
4
4
|
|
|
5
|
+
import { measureArea } from '../measurements/index.js'
|
|
6
|
+
|
|
5
7
|
import { rectangle } from './index.js'
|
|
6
8
|
|
|
7
9
|
import { comparePoints } from '../../test/helpers/index.js'
|
|
@@ -17,7 +19,8 @@ test('rectangle (defaults)', (t) => {
|
|
|
17
19
|
]
|
|
18
20
|
|
|
19
21
|
t.notThrows(() => geom2.validate(geometry))
|
|
20
|
-
t.
|
|
22
|
+
t.is(measureArea(geometry), 4)
|
|
23
|
+
t.is(obs.length, 4)
|
|
21
24
|
t.true(comparePoints(obs, exp))
|
|
22
25
|
})
|
|
23
26
|
|
|
@@ -33,7 +36,8 @@ test('rectangle (options)', (t) => {
|
|
|
33
36
|
]
|
|
34
37
|
|
|
35
38
|
t.notThrows(() => geom2.validate(geometry))
|
|
36
|
-
t.
|
|
39
|
+
t.is(measureArea(geometry), 4)
|
|
40
|
+
t.is(obs.length, 4)
|
|
37
41
|
t.true(comparePoints(obs, exp))
|
|
38
42
|
|
|
39
43
|
// test size
|
|
@@ -47,7 +51,8 @@ test('rectangle (options)', (t) => {
|
|
|
47
51
|
]
|
|
48
52
|
|
|
49
53
|
t.notThrows(() => geom2.validate(geometry))
|
|
50
|
-
t.
|
|
54
|
+
t.is(measureArea(geometry), 60)
|
|
55
|
+
t.is(obs.length, 4)
|
|
51
56
|
t.true(comparePoints(obs, exp))
|
|
52
57
|
})
|
|
53
58
|
|
|
@@ -55,5 +60,6 @@ test('rectangle (zero size)', (t) => {
|
|
|
55
60
|
const geometry = rectangle({ size: [1, 0] })
|
|
56
61
|
const obs = geom2.toPoints(geometry)
|
|
57
62
|
t.notThrows(() => geom2.validate(geometry))
|
|
63
|
+
t.is(measureArea(geometry), 0)
|
|
58
64
|
t.is(obs.length, 0)
|
|
59
65
|
})
|