@jscad/modeling 2.9.2 → 2.9.5
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 +50 -0
- package/README.md +4 -4
- package/dist/jscad-modeling.min.js +435 -444
- package/package.json +3 -2
- package/src/colors/colorize.d.ts +6 -5
- package/src/colors/colorize.test.js +1 -1
- package/src/geometries/geom2/toOutlines.js +66 -52
- package/src/geometries/geom2/type.d.ts +3 -2
- package/src/geometries/geom3/applyTransforms.js +1 -2
- package/src/geometries/geom3/create.js +1 -1
- package/src/geometries/geom3/create.test.js +1 -1
- package/src/geometries/geom3/fromPoints.js +1 -1
- package/src/geometries/geom3/type.d.ts +3 -2
- package/src/geometries/path2/index.d.ts +0 -1
- package/src/geometries/path2/index.js +0 -1
- package/src/geometries/path2/type.d.ts +3 -2
- package/src/geometries/poly3/create.js +1 -1
- package/src/geometries/poly3/measureBoundingSphere.d.ts +2 -2
- package/src/geometries/poly3/measureBoundingSphere.js +46 -8
- package/src/geometries/poly3/measureBoundingSphere.test.js +16 -26
- package/src/geometries/poly3/type.d.ts +3 -2
- package/src/geometries/poly3/validate.js +14 -0
- package/src/geometries/types.d.ts +4 -2
- package/src/maths/constants.d.ts +1 -0
- package/src/maths/constants.js +11 -0
- package/src/maths/mat4/fromRotation.js +9 -7
- package/src/maths/mat4/fromTaitBryanRotation.js +8 -6
- package/src/maths/mat4/fromXRotation.js +4 -2
- package/src/maths/mat4/fromYRotation.js +4 -2
- package/src/maths/mat4/fromZRotation.js +4 -2
- package/src/maths/mat4/isMirroring.js +11 -11
- package/src/maths/mat4/rotate.js +9 -5
- package/src/maths/mat4/rotateX.js +4 -2
- package/src/maths/mat4/rotateY.js +4 -2
- package/src/maths/mat4/rotateZ.js +4 -2
- package/src/maths/mat4/translate.test.js +2 -3
- package/src/maths/utils/aboutEqualNormals.js +1 -5
- package/src/maths/utils/index.d.ts +1 -0
- package/src/maths/utils/index.js +2 -0
- package/src/{utils → maths/utils}/trigonometry.d.ts +0 -0
- package/src/{utils → maths/utils}/trigonometry.js +1 -2
- package/src/{utils → maths/utils}/trigonometry.test.js +0 -0
- package/src/maths/vec2/distance.js +1 -1
- package/src/maths/vec2/fromAngleRadians.js +4 -2
- package/src/maths/vec2/length.js +1 -1
- package/src/maths/vec2/length.test.js +0 -10
- package/src/maths/vec3/angle.js +2 -2
- package/src/maths/vec3/angle.test.js +0 -12
- package/src/maths/vec3/distance.js +1 -1
- package/src/maths/vec3/length.js +1 -1
- package/src/maths/vec3/length.test.js +0 -10
- package/src/operations/booleans/intersectGeom2.test.js +69 -0
- package/src/operations/booleans/intersectGeom3.js +2 -1
- package/src/operations/booleans/{intersect.test.js → intersectGeom3.test.js} +3 -71
- package/src/operations/booleans/subtractGeom2.test.js +72 -0
- package/src/operations/booleans/subtractGeom3.js +2 -1
- package/src/operations/booleans/{subtract.test.js → subtractGeom3.test.js} +3 -74
- package/src/operations/booleans/to3DWalls.js +1 -1
- package/src/operations/booleans/trees/PolygonTreeNode.js +2 -2
- package/src/operations/booleans/unionGeom2.test.js +166 -0
- package/src/operations/booleans/unionGeom3.js +2 -1
- package/src/operations/booleans/{union.test.js → unionGeom3.test.js} +3 -168
- package/src/operations/expansions/expandGeom3.test.js +14 -14
- package/src/operations/expansions/expandShell.js +5 -4
- package/src/operations/expansions/extrudePolygon.js +7 -7
- package/src/operations/extrusions/extrudeFromSlices.js +3 -2
- package/src/operations/extrusions/extrudeFromSlices.test.js +2 -2
- package/src/operations/extrusions/extrudeRotate.js +5 -1
- package/src/operations/extrusions/extrudeRotate.test.js +47 -47
- package/src/operations/extrusions/extrudeWalls.js +2 -2
- package/src/operations/extrusions/project.js +11 -14
- package/src/operations/extrusions/project.test.js +49 -49
- package/src/operations/extrusions/slice/repair.js +62 -0
- package/src/operations/hulls/hullChain.test.js +4 -4
- package/src/operations/hulls/hullGeom2.js +6 -18
- package/src/operations/hulls/hullGeom3.js +5 -18
- package/src/operations/hulls/hullPath2.js +4 -14
- package/src/operations/hulls/hullPoints2.js +43 -92
- package/src/operations/hulls/toUniquePoints.js +34 -0
- package/src/operations/modifiers/generalize.js +2 -13
- package/src/operations/modifiers/generalize.test.js +0 -32
- package/src/operations/modifiers/insertTjunctions.js +1 -1
- package/src/operations/modifiers/insertTjunctions.test.js +21 -21
- package/src/operations/modifiers/mergePolygons.js +11 -14
- package/src/operations/{booleans → modifiers}/reTesselateCoplanarPolygons.js +33 -32
- package/src/operations/{booleans → modifiers}/reTesselateCoplanarPolygons.test.js +5 -5
- package/src/operations/{booleans → modifiers}/retessellate.js +2 -9
- package/src/operations/{booleans → modifiers}/retessellate.test.js +0 -0
- package/src/operations/modifiers/snapPolygons.test.js +12 -12
- package/src/operations/modifiers/triangulatePolygons.js +3 -3
- package/src/operations/transforms/center.js +1 -1
- package/src/primitives/circle.test.js +7 -0
- package/src/primitives/cuboid.js +1 -1
- package/src/primitives/cylinderElliptic.js +5 -3
- package/src/primitives/cylinderElliptic.test.js +7 -1
- package/src/primitives/ellipse.js +1 -1
- package/src/primitives/ellipse.test.js +7 -0
- package/src/primitives/ellipsoid.js +3 -3
- package/src/primitives/geodesicSphere.js +3 -2
- package/src/primitives/polyhedron.js +1 -1
- package/src/primitives/roundedCuboid.js +10 -8
- package/src/primitives/roundedCylinder.js +2 -2
- package/src/primitives/torus.test.js +11 -7
- package/src/primitives/triangle.js +1 -2
- package/src/utils/index.d.ts +0 -1
- package/src/utils/index.js +1 -3
- package/src/geometries/path2/eachPoint.d.ts +0 -9
- package/src/geometries/path2/eachPoint.js +0 -17
- package/src/geometries/path2/eachPoint.test.js +0 -11
- package/src/maths/mat4/constants.d.ts +0 -1
- package/src/maths/mat4/constants.js +0 -5
- package/src/operations/extrusions/slice/repairSlice.js +0 -47
- package/src/operations/modifiers/edges.js +0 -195
- package/src/operations/modifiers/repairTjunctions.js +0 -44
|
@@ -7,49 +7,49 @@ const snapPolygons = require('./snapPolygons')
|
|
|
7
7
|
test('snapPolygons: snap of polygons produces expected results', (t) => {
|
|
8
8
|
const polygons = [
|
|
9
9
|
// valid polygons
|
|
10
|
-
poly3.
|
|
11
|
-
poly3.
|
|
10
|
+
poly3.create([[0, 0, 0], [0, 10, 0], [0, 10, 10]]), // OK
|
|
11
|
+
poly3.create([[0, 0, 0], [0, 10, 0], [0, 10, 10], [0, 0, 10]]), // OK
|
|
12
12
|
// invalid polygons
|
|
13
13
|
poly3.create(),
|
|
14
|
-
poly3.
|
|
15
|
-
poly3.
|
|
14
|
+
poly3.create([[0, 0, 0]]),
|
|
15
|
+
poly3.create([[0, 0, 0], [0, 10, 0]]),
|
|
16
16
|
// duplicated vertices
|
|
17
|
-
poly3.
|
|
17
|
+
poly3.create([
|
|
18
18
|
[-24.445112000000115, 19.346837333333426, 46.47572533333356],
|
|
19
19
|
[-24.44446933333345, 19.346837333333426, 46.47508266666689],
|
|
20
20
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
21
21
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019]
|
|
22
22
|
]), // OK
|
|
23
|
-
poly3.
|
|
23
|
+
poly3.create([
|
|
24
24
|
[-24.445112000000115, 19.346837333333426, 46.47572533333356],
|
|
25
25
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
26
26
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019]
|
|
27
27
|
]),
|
|
28
|
-
poly3.
|
|
28
|
+
poly3.create([
|
|
29
29
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
30
30
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019]
|
|
31
31
|
]),
|
|
32
32
|
// duplicate vertices after snap
|
|
33
|
-
poly3.
|
|
33
|
+
poly3.create([
|
|
34
34
|
[-24.445112000000115, 19.346837333333426, 46.47572533333356],
|
|
35
35
|
[-24.44446933333345, 19.346837333333426, 46.47508266666689],
|
|
36
36
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
37
37
|
[-23.70540266666678 - 0.00001234, 18.79864266666676 + 0.000001234, 39.56448800000019 + 0.00001234]
|
|
38
38
|
]), // OK
|
|
39
|
-
poly3.
|
|
39
|
+
poly3.create([
|
|
40
40
|
[-24.445112000000115, 19.346837333333426, 46.47572533333356],
|
|
41
41
|
[-23.70540266666678 - 0.00001234, 18.79864266666676 + 0.000001234, 39.56448800000019 + 0.00001234],
|
|
42
42
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
43
43
|
[-23.70540266666678 - 0.00001234, 18.79864266666676 + 0.000001234, 39.56448800000019 + 0.00001234]
|
|
44
44
|
]),
|
|
45
|
-
poly3.
|
|
45
|
+
poly3.create([
|
|
46
46
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
47
47
|
[-23.70540266666678 - 0.00001234, 18.79864266666676 + 0.000001234, 39.56448800000019 + 0.00001234],
|
|
48
48
|
[-23.70540266666678, 18.79864266666676, 39.56448800000019],
|
|
49
49
|
[-23.70540266666678 - 0.00001234, 18.79864266666676 + 0.000001234, 39.56448800000019 + 0.00001234]
|
|
50
50
|
]),
|
|
51
51
|
// inverted polygon
|
|
52
|
-
poly3.
|
|
52
|
+
poly3.create([
|
|
53
53
|
[20.109133333333336, -4.894033333333335, -1.0001266666666668],
|
|
54
54
|
[20.021120000000003, -5.1802133333333344, -1.0001266666666668],
|
|
55
55
|
[20.020300000000002, -5.182946666666668, -1.0001266666666668],
|
|
@@ -61,7 +61,7 @@ test('snapPolygons: snap of polygons produces expected results', (t) => {
|
|
|
61
61
|
const results = snapPolygons(0.0001, polygons)
|
|
62
62
|
t.is(results.length, 5)
|
|
63
63
|
|
|
64
|
-
const exp3 = poly3.
|
|
64
|
+
const exp3 = poly3.create([
|
|
65
65
|
[-24.4451, 19.3468, 46.4757],
|
|
66
66
|
[-24.4445, 19.3468, 46.475100000000005],
|
|
67
67
|
[-23.7054, 18.7986, 39.5645]
|
|
@@ -10,15 +10,15 @@ const triangulatePolygon = (epsilon, polygon, triangles) => {
|
|
|
10
10
|
polygon.vertices.forEach((vertice) => vec3.add(midpoint, midpoint, vertice))
|
|
11
11
|
vec3.snap(midpoint, vec3.divide(midpoint, midpoint, [nv, nv, nv]), epsilon)
|
|
12
12
|
for (let i = 0; i < nv; i++) {
|
|
13
|
-
const poly = poly3.
|
|
13
|
+
const poly = poly3.create([midpoint, polygon.vertices[i], polygon.vertices[(i + 1) % nv]])
|
|
14
14
|
if (polygon.color) poly.color = polygon.color
|
|
15
15
|
triangles.push(poly)
|
|
16
16
|
}
|
|
17
17
|
return
|
|
18
18
|
}
|
|
19
19
|
// exactly 4 vertices, use simple triangulation
|
|
20
|
-
const poly0 = poly3.
|
|
21
|
-
const poly1 = poly3.
|
|
20
|
+
const poly0 = poly3.create([polygon.vertices[0], polygon.vertices[1], polygon.vertices[2]])
|
|
21
|
+
const poly1 = poly3.create([polygon.vertices[0], polygon.vertices[2], polygon.vertices[3]])
|
|
22
22
|
if (polygon.color) {
|
|
23
23
|
poly0.color = polygon.color
|
|
24
24
|
poly1.color = polygon.color
|
|
@@ -39,7 +39,7 @@ const center = (options, ...objects) => {
|
|
|
39
39
|
const defaults = {
|
|
40
40
|
axes: [true, true, true],
|
|
41
41
|
relativeTo: [0, 0, 0]
|
|
42
|
-
// TODO
|
|
42
|
+
// TODO: Add additional 'methods' of centering: midpoint, centroid
|
|
43
43
|
}
|
|
44
44
|
const { axes, relativeTo } = Object.assign({}, defaults, options)
|
|
45
45
|
|
|
@@ -123,6 +123,13 @@ test('circle (options)', (t) => {
|
|
|
123
123
|
t.deepEqual(pts.length, 6)
|
|
124
124
|
t.true(comparePoints(pts, exp))
|
|
125
125
|
|
|
126
|
+
// test full rotation with non-zero startAngle
|
|
127
|
+
geometry = circle({ startAngle: 1, endAngle: 1 + 2 * Math.PI })
|
|
128
|
+
pts = geom2.toPoints(geometry)
|
|
129
|
+
|
|
130
|
+
t.notThrows(() => geom2.validate(geometry))
|
|
131
|
+
t.deepEqual(pts.length, 32)
|
|
132
|
+
|
|
126
133
|
// test segments
|
|
127
134
|
geometry = circle({ radius: 3.5, segments: 5 })
|
|
128
135
|
pts = geom2.toPoints(geometry)
|
package/src/primitives/cuboid.js
CHANGED
|
@@ -5,7 +5,7 @@ const vec3 = require('../maths/vec3')
|
|
|
5
5
|
const geom3 = require('../geometries/geom3')
|
|
6
6
|
const poly3 = require('../geometries/poly3')
|
|
7
7
|
|
|
8
|
-
const { sin, cos } = require('../utils/trigonometry')
|
|
8
|
+
const { sin, cos } = require('../maths/utils/trigonometry')
|
|
9
9
|
|
|
10
10
|
const { isGT, isGTE, isNumberArray } = require('./commonChecks')
|
|
11
11
|
|
|
@@ -90,13 +90,15 @@ const cylinderElliptic = (options) => {
|
|
|
90
90
|
// adjust the points to center
|
|
91
91
|
const fromPoints = (...points) => {
|
|
92
92
|
const newpoints = points.map((point) => vec3.add(vec3.create(), point, center))
|
|
93
|
-
return poly3.
|
|
93
|
+
return poly3.create(newpoints)
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
const polygons = []
|
|
97
97
|
for (let i = 0; i < slices; i++) {
|
|
98
98
|
const t0 = i / slices
|
|
99
|
-
|
|
99
|
+
let t1 = (i + 1) / slices
|
|
100
|
+
// fix rounding error when rotating 2 * PI radians
|
|
101
|
+
if (rotation === 2 * Math.PI && i === slices - 1) t1 = 0
|
|
100
102
|
|
|
101
103
|
if (endRadius[0] === startRadius[0] && endRadius[1] === startRadius[1]) {
|
|
102
104
|
polygons.push(fromPoints(start, point(0, t1, endRadius), point(0, t0, endRadius)))
|
|
@@ -137,7 +137,13 @@ test('cylinderElliptic (options)', (t) => {
|
|
|
137
137
|
|
|
138
138
|
t.notThrows(() => geom3.validate(obs))
|
|
139
139
|
t.is(pts.length, 28)
|
|
140
|
-
|
|
140
|
+
|
|
141
|
+
// test startAngle and endAngle
|
|
142
|
+
obs = cylinderElliptic({ startAngle: 1, endAngle: 1 + 2 * Math.PI })
|
|
143
|
+
pts = geom3.toPoints(obs)
|
|
144
|
+
|
|
145
|
+
t.notThrows(() => geom3.validate(obs))
|
|
146
|
+
t.is(pts.length, 96)
|
|
141
147
|
|
|
142
148
|
// test segments
|
|
143
149
|
obs = cylinderElliptic({ segments: 8 })
|
|
@@ -4,7 +4,7 @@ const vec2 = require('../maths/vec2')
|
|
|
4
4
|
|
|
5
5
|
const geom2 = require('../geometries/geom2')
|
|
6
6
|
|
|
7
|
-
const { sin, cos } = require('../utils/trigonometry')
|
|
7
|
+
const { sin, cos } = require('../maths/utils/trigonometry')
|
|
8
8
|
|
|
9
9
|
const { isGTE, isNumberArray } = require('./commonChecks')
|
|
10
10
|
|
|
@@ -123,6 +123,13 @@ test('ellipse (options)', (t) => {
|
|
|
123
123
|
t.deepEqual(obs.length, 6)
|
|
124
124
|
t.true(comparePoints(obs, exp))
|
|
125
125
|
|
|
126
|
+
// test full rotation with non-zero startAngle
|
|
127
|
+
geometry = ellipse({ startAngle: 1, endAngle: 1 + 2 * Math.PI })
|
|
128
|
+
obs = geom2.toPoints(geometry)
|
|
129
|
+
|
|
130
|
+
t.notThrows(() => geom2.validate(geometry))
|
|
131
|
+
t.deepEqual(obs.length, 32)
|
|
132
|
+
|
|
126
133
|
// test segments
|
|
127
134
|
geometry = ellipse({ segments: 72 })
|
|
128
135
|
obs = geom2.toPoints(geometry)
|
|
@@ -3,7 +3,7 @@ const vec3 = require('../maths/vec3')
|
|
|
3
3
|
const geom3 = require('../geometries/geom3')
|
|
4
4
|
const poly3 = require('../geometries/poly3')
|
|
5
5
|
|
|
6
|
-
const { sin, cos } = require('../utils/trigonometry')
|
|
6
|
+
const { sin, cos } = require('../maths/utils/trigonometry')
|
|
7
7
|
|
|
8
8
|
const { isGTE, isNumberArray } = require('./commonChecks')
|
|
9
9
|
|
|
@@ -66,7 +66,7 @@ const ellipsoid = (options) => {
|
|
|
66
66
|
point = vec3.subtract(vec3.create(), vec3.scale(p1, prevcylinderpoint, cospitch), vec3.scale(p2, zvector, sinpitch))
|
|
67
67
|
points.push(vec3.add(point, point, center))
|
|
68
68
|
|
|
69
|
-
polygons.push(poly3.
|
|
69
|
+
polygons.push(poly3.create(points))
|
|
70
70
|
|
|
71
71
|
points = []
|
|
72
72
|
point = vec3.add(vec3.create(), vec3.scale(p1, prevcylinderpoint, prevcospitch), vec3.scale(p2, zvector, prevsinpitch))
|
|
@@ -81,7 +81,7 @@ const ellipsoid = (options) => {
|
|
|
81
81
|
points.push(vec3.add(vec3.create(), center, point))
|
|
82
82
|
points.reverse()
|
|
83
83
|
|
|
84
|
-
polygons.push(poly3.
|
|
84
|
+
polygons.push(poly3.create(points))
|
|
85
85
|
}
|
|
86
86
|
prevcospitch = cospitch
|
|
87
87
|
prevsinpitch = sinpitch
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const mat4 = require('../maths/mat4')
|
|
2
|
+
const vec3 = require('../maths/vec3')
|
|
2
3
|
|
|
3
4
|
const geom3 = require('../geometries/geom3')
|
|
4
5
|
|
|
@@ -79,7 +80,7 @@ const geodesicSphere = (options) => {
|
|
|
79
80
|
|
|
80
81
|
// -- normalize
|
|
81
82
|
for (let k = 0; k < 3; k++) {
|
|
82
|
-
const r =
|
|
83
|
+
const r = vec3.length(q[k])
|
|
83
84
|
for (let l = 0; l < 3; l++) {
|
|
84
85
|
q[k][l] /= r
|
|
85
86
|
}
|
|
@@ -95,7 +96,7 @@ const geodesicSphere = (options) => {
|
|
|
95
96
|
|
|
96
97
|
// -- normalize
|
|
97
98
|
for (let k = 0; k < 3; k++) {
|
|
98
|
-
const r =
|
|
99
|
+
const r = vec3.length(q[k])
|
|
99
100
|
for (let l = 0; l < 3; l++) {
|
|
100
101
|
q[k][l] /= r
|
|
101
102
|
}
|
|
@@ -60,7 +60,7 @@ const polyhedron = (options) => {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
const polygons = faces.map((face, findex) => {
|
|
63
|
-
const polygon = poly3.
|
|
63
|
+
const polygon = poly3.create(face.map((pindex) => points[pindex]))
|
|
64
64
|
if (colors && colors[findex]) polygon.color = colors[findex]
|
|
65
65
|
return polygon
|
|
66
66
|
})
|
|
@@ -6,12 +6,14 @@ const vec3 = require('../maths/vec3')
|
|
|
6
6
|
const geom3 = require('../geometries/geom3')
|
|
7
7
|
const poly3 = require('../geometries/poly3')
|
|
8
8
|
|
|
9
|
+
const { sin, cos } = require('../maths/utils/trigonometry')
|
|
10
|
+
|
|
9
11
|
const { isGT, isGTE, isNumberArray } = require('./commonChecks')
|
|
10
12
|
|
|
11
13
|
const createCorners = (center, size, radius, segments, slice, positive) => {
|
|
12
14
|
const pitch = (Math.PI / 2) * slice / segments
|
|
13
|
-
const cospitch =
|
|
14
|
-
const sinpitch =
|
|
15
|
+
const cospitch = cos(pitch)
|
|
16
|
+
const sinpitch = sin(pitch)
|
|
15
17
|
|
|
16
18
|
const layersegments = segments - slice
|
|
17
19
|
let layerradius = radius * cospitch
|
|
@@ -57,10 +59,10 @@ const stitchCorners = (previousCorners, currentCorners) => {
|
|
|
57
59
|
const previous = previousCorners[i]
|
|
58
60
|
const current = currentCorners[i]
|
|
59
61
|
for (let j = 0; j < (previous.length - 1); j++) {
|
|
60
|
-
polygons.push(poly3.
|
|
62
|
+
polygons.push(poly3.create([previous[j], previous[j + 1], current[j]]))
|
|
61
63
|
|
|
62
64
|
if (j < (current.length - 1)) {
|
|
63
|
-
polygons.push(poly3.
|
|
65
|
+
polygons.push(poly3.create([current[j], previous[j + 1], current[j + 1]]))
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
}
|
|
@@ -81,7 +83,7 @@ const stitchWalls = (previousCorners, currentCorners) => {
|
|
|
81
83
|
const p1 = previous[0]
|
|
82
84
|
const c1 = current[0]
|
|
83
85
|
|
|
84
|
-
polygons.push(poly3.
|
|
86
|
+
polygons.push(poly3.create([p0, p1, c1, c0]))
|
|
85
87
|
}
|
|
86
88
|
return polygons
|
|
87
89
|
}
|
|
@@ -104,7 +106,7 @@ const stitchSides = (bottomCorners, topCorners) => {
|
|
|
104
106
|
const polygons = []
|
|
105
107
|
for (let i = 0; i < topPoints.length; i++) {
|
|
106
108
|
const j = (i + 1) % topPoints.length
|
|
107
|
-
polygons.push(poly3.
|
|
109
|
+
polygons.push(poly3.create([bottomPoints[i], bottomPoints[j], topPoints[j], topPoints[i]]))
|
|
108
110
|
}
|
|
109
111
|
return polygons
|
|
110
112
|
}
|
|
@@ -168,10 +170,10 @@ const roundedCuboid = (options) => {
|
|
|
168
170
|
if (slice === segments) {
|
|
169
171
|
// add the top
|
|
170
172
|
let points = cornersPos.map((corner) => corner[0])
|
|
171
|
-
polygons.push(poly3.
|
|
173
|
+
polygons.push(poly3.create(points))
|
|
172
174
|
// add the bottom
|
|
173
175
|
points = cornersNeg.map((corner) => corner[0])
|
|
174
|
-
polygons.push(poly3.
|
|
176
|
+
polygons.push(poly3.create(points))
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
prevCornersPos = cornersPos
|
|
@@ -5,7 +5,7 @@ const vec3 = require('../maths/vec3')
|
|
|
5
5
|
const geom3 = require('../geometries/geom3')
|
|
6
6
|
const poly3 = require('../geometries/poly3')
|
|
7
7
|
|
|
8
|
-
const { sin, cos } = require('../utils/trigonometry')
|
|
8
|
+
const { sin, cos } = require('../maths/utils/trigonometry')
|
|
9
9
|
|
|
10
10
|
const { isGT, isGTE, isNumberArray } = require('./commonChecks')
|
|
11
11
|
|
|
@@ -66,7 +66,7 @@ const roundedCylinder = (options) => {
|
|
|
66
66
|
const fromPoints = (points) => {
|
|
67
67
|
// adjust the points to center
|
|
68
68
|
const newpoints = points.map((point) => vec3.add(point, point, center))
|
|
69
|
-
return poly3.
|
|
69
|
+
return poly3.create(newpoints)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
const polygons = []
|
|
@@ -10,24 +10,22 @@ test('torus (defaults)', (t) => {
|
|
|
10
10
|
const obs = torus()
|
|
11
11
|
const pts = geom3.toPoints(obs)
|
|
12
12
|
|
|
13
|
-
t.notThrows
|
|
13
|
+
t.notThrows(() => geom3.validate(obs))
|
|
14
14
|
t.is(pts.length, 2048) // 32 * 32 * 2 (polys/segment) = 2048
|
|
15
15
|
|
|
16
16
|
const bounds = measureBoundingBox(obs)
|
|
17
17
|
const expectedBounds = [[-5, -5, -1], [5, 5, 1]]
|
|
18
|
-
t.notThrows.skip(() => geom3.validate(obs))
|
|
19
18
|
t.true(comparePoints(bounds, expectedBounds), 'Bounding box was not as expected: ' + JSON.stringify(bounds))
|
|
20
19
|
})
|
|
21
20
|
|
|
22
|
-
test('torus (
|
|
21
|
+
test('torus (simple options)', (t) => {
|
|
23
22
|
const obs = torus({ innerRadius: 0.5, innerSegments: 4, outerRadius: 5, outerSegments: 8 })
|
|
24
23
|
const pts = geom3.toPoints(obs)
|
|
25
|
-
t.notThrows
|
|
24
|
+
t.notThrows(() => geom3.validate(obs))
|
|
26
25
|
t.is(pts.length, 64) // 4 * 8 * 2 (polys/segment) = 64
|
|
27
26
|
|
|
28
27
|
const bounds = measureBoundingBox(obs)
|
|
29
28
|
const expectedBounds = [[-5.5, -5.5, -0.5], [5.5, 5.5, 0.5]]
|
|
30
|
-
t.notThrows.skip(() => geom3.validate(obs))
|
|
31
29
|
t.true(comparePoints(bounds, expectedBounds), 'Bounding box was not as expected: ' + JSON.stringify(bounds))
|
|
32
30
|
})
|
|
33
31
|
|
|
@@ -39,15 +37,21 @@ test('torus (complex options)', (t) => {
|
|
|
39
37
|
|
|
40
38
|
const bounds = measureBoundingBox(obs)
|
|
41
39
|
const expectedBounds = [[-6, 0, -1], [0, 6, 1]]
|
|
42
|
-
t.notThrows(() => geom3.validate(obs))
|
|
43
40
|
t.true(comparePoints(bounds, expectedBounds), 'Bounding box was not as expected: ' + JSON.stringify(bounds))
|
|
44
41
|
})
|
|
45
42
|
|
|
43
|
+
test('torus (startAngle)', (t) => {
|
|
44
|
+
const obs = torus({ startAngle: 1, endAngle: 1 + 2 * Math.PI })
|
|
45
|
+
const pts = geom3.toPoints(obs)
|
|
46
|
+
t.notThrows(() => geom3.validate(obs))
|
|
47
|
+
t.is(pts.length, 2048)
|
|
48
|
+
})
|
|
49
|
+
|
|
46
50
|
test('torus (square by square)', (t) => {
|
|
47
51
|
const obs = torus({ innerSegments: 4, outerSegments: 4, innerRotation: Math.PI / 2 })
|
|
48
52
|
|
|
49
53
|
const bounds = measureBoundingBox(obs)
|
|
50
54
|
const expectedBounds = [[-5, -5, -1], [5, 5, 1]]
|
|
51
|
-
t.notThrows
|
|
55
|
+
t.notThrows(() => geom3.validate(obs))
|
|
52
56
|
t.true(comparePoints(bounds, expectedBounds), 'Bounding box was not as expected: ' + JSON.stringify(bounds))
|
|
53
57
|
})
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
const { NEPS } = require('../maths/constants')
|
|
1
2
|
const vec2 = require('../maths/vec2')
|
|
2
3
|
|
|
3
4
|
const geom2 = require('../geometries/geom2')
|
|
4
5
|
|
|
5
6
|
const { isNumberArray } = require('./commonChecks')
|
|
6
7
|
|
|
7
|
-
const NEPS = 1e-13
|
|
8
|
-
|
|
9
8
|
// returns angle C
|
|
10
9
|
const solveAngleFromSSS = (a, b, c) => Math.acos(((a * a) + (b * b) - (c * c)) / (2 * a * b))
|
|
11
10
|
|
package/src/utils/index.d.ts
CHANGED
|
@@ -5,6 +5,5 @@ export { default as fnNumberSort } from './fnNumberSort'
|
|
|
5
5
|
export { default as insertSorted } from './insertSorted'
|
|
6
6
|
export { default as radiusToSegments } from './radiusToSegments'
|
|
7
7
|
export { default as radToDeg } from './radToDeg'
|
|
8
|
-
export * from './trigonometry'
|
|
9
8
|
|
|
10
9
|
export as namespace utils
|
package/src/utils/index.js
CHANGED
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
module.exports = {
|
|
8
8
|
areAllShapesTheSameType: require('./areAllShapesTheSameType'),
|
|
9
|
-
cos: require('./trigonometry').cos,
|
|
10
9
|
degToRad: require('./degToRad'),
|
|
11
10
|
flatten: require('./flatten'),
|
|
12
11
|
fnNumberSort: require('./fnNumberSort'),
|
|
13
12
|
insertSorted: require('./insertSorted'),
|
|
14
13
|
radiusToSegments: require('./radiusToSegments'),
|
|
15
|
-
radToDeg: require('./radToDeg')
|
|
16
|
-
sin: require('./trigonometry').sin
|
|
14
|
+
radToDeg: require('./radToDeg')
|
|
17
15
|
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import Path2 from './type'
|
|
2
|
-
import Vec2 from '../../maths/vec2/type'
|
|
3
|
-
|
|
4
|
-
export default eachPoint
|
|
5
|
-
|
|
6
|
-
export interface EachPointOptions {}
|
|
7
|
-
export type EachPointThunk = (value: Vec2, index: number, array: Array<Vec2>) => void
|
|
8
|
-
|
|
9
|
-
declare function eachPoint(options: EachPointOptions, thunk: EachPointThunk, path: Path2): void
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const toPoints = require('./toPoints')
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Calls a function for each point in the path.
|
|
5
|
-
* @param {Object} options - options
|
|
6
|
-
* @param {Function} thunk - the function to call
|
|
7
|
-
* @param {path2} path - the path to traverse
|
|
8
|
-
* @alias module:modeling/geometries/path2.eachPoint
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* eachPoint({}, accumulate, path)
|
|
12
|
-
*/
|
|
13
|
-
const eachPoint = (options, thunk, path) => {
|
|
14
|
-
toPoints(path).forEach(thunk)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = eachPoint
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const test = require('ava')
|
|
2
|
-
|
|
3
|
-
const vec2 = require('../../maths/vec2')
|
|
4
|
-
|
|
5
|
-
const { eachPoint, fromPoints } = require('./index')
|
|
6
|
-
|
|
7
|
-
test('eachPoint: Each point is emitted', (t) => {
|
|
8
|
-
const collector = []
|
|
9
|
-
eachPoint({}, (point) => collector.push(point), fromPoints({}, [[1, 1], [2, 2]]))
|
|
10
|
-
t.deepEqual(collector, [vec2.fromValues(1, 1), vec2.fromValues(2, 2)])
|
|
11
|
-
})
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const EPSILON: number
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
const vec3 = require('../../../maths/vec3')
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Mend gaps in a 2D slice to make it a closed polygon
|
|
5
|
-
*/
|
|
6
|
-
const repairSlice = (slice) => {
|
|
7
|
-
if (!slice.edges) return slice
|
|
8
|
-
const vertexMap = {} // string key to vertex map
|
|
9
|
-
const edgeCount = {} // count of (in - out) edges
|
|
10
|
-
slice.edges.forEach((edge) => {
|
|
11
|
-
const inKey = edge[0].toString()
|
|
12
|
-
const outKey = edge[1].toString()
|
|
13
|
-
vertexMap[inKey] = edge[0]
|
|
14
|
-
vertexMap[outKey] = edge[1]
|
|
15
|
-
edgeCount[inKey] = (edgeCount[inKey] || 0) + 1 // in
|
|
16
|
-
edgeCount[outKey] = (edgeCount[outKey] || 0) - 1 // out
|
|
17
|
-
})
|
|
18
|
-
// find vertices which are missing in or out edges
|
|
19
|
-
const missingIn = Object.keys(edgeCount).filter((e) => edgeCount[e] < 0)
|
|
20
|
-
const missingOut = Object.keys(edgeCount).filter((e) => edgeCount[e] > 0)
|
|
21
|
-
// pairwise distance of bad vertices
|
|
22
|
-
missingIn.forEach((key1) => {
|
|
23
|
-
const v1 = vertexMap[key1]
|
|
24
|
-
// find the closest vertex that is missing an out edge
|
|
25
|
-
let bestDistance = Infinity
|
|
26
|
-
let bestReplacement
|
|
27
|
-
missingOut.forEach((key2) => {
|
|
28
|
-
const v2 = vertexMap[key2]
|
|
29
|
-
const distance = Math.hypot(v1[0] - v2[0], v1[1] - v2[1])
|
|
30
|
-
if (distance < bestDistance) {
|
|
31
|
-
bestDistance = distance
|
|
32
|
-
bestReplacement = v2
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
console.warn(`repairSlice: repairing vertex gap ${v1} to ${bestReplacement} distance ${bestDistance}`)
|
|
36
|
-
// merge broken vertices
|
|
37
|
-
slice.edges.forEach((edge) => {
|
|
38
|
-
if (edge[0].toString() === key1) edge[0] = bestReplacement
|
|
39
|
-
if (edge[1].toString() === key1) edge[1] = bestReplacement
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
// Remove self-edges
|
|
43
|
-
slice.edges = slice.edges.filter((e) => !vec3.equals(e[0], e[1]))
|
|
44
|
-
return slice
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
module.exports = repairSlice
|