@jscad/modeling 3.0.3-alpha.0 → 3.0.5-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 +23 -0
- package/dist/jscad-modeling.es.js +2 -7
- package/dist/jscad-modeling.min.js +2 -7
- package/package.json +8 -9
- package/rollup.config.js +8 -4
- package/src/colors/colorize.js +17 -1
- package/src/curves/bezier/arcLengthToT.js +1 -1
- package/src/curves/bezier/create.js +1 -1
- package/src/curves/bezier/index.js +7 -7
- package/src/curves/bezier/length.js +1 -1
- package/src/curves/bezier/lengths.js +2 -1
- package/src/curves/bezier/tangentAt.js +1 -1
- package/src/curves/bezier/valueAt.js +1 -1
- package/src/curves/index.js +3 -3
- package/src/geometries/geom2/applyTransforms.js +3 -1
- package/src/geometries/geom2/clone.js +5 -1
- package/src/geometries/geom2/create.js +4 -14
- package/src/geometries/geom2/fromPoints.d.ts +4 -0
- package/src/geometries/geom2/fromPoints.js +28 -0
- package/src/geometries/geom2/fromPoints.test.js +22 -0
- package/src/geometries/geom2/fromSides.js +4 -2
- package/src/geometries/geom2/index.d.ts +1 -0
- package/src/geometries/geom2/index.js +22 -5
- package/src/geometries/geom2/isA.js +5 -1
- package/src/geometries/geom2/reverse.js +4 -2
- package/src/geometries/geom2/toOutlines.js +2 -1
- package/src/geometries/geom2/toPoints.js +5 -2
- package/src/geometries/geom2/toSides.js +4 -3
- package/src/geometries/geom2/toString.js +3 -2
- package/src/geometries/geom2/transform.js +4 -2
- package/src/geometries/geom2/validate.js +6 -2
- package/src/geometries/geom3/clone.js +5 -1
- package/src/geometries/geom3/create.js +5 -19
- package/src/geometries/geom3/fromVertices.js +13 -1
- package/src/geometries/geom3/fromVerticesConvex.js +1 -1
- package/src/geometries/geom3/index.d.ts +1 -0
- package/src/geometries/geom3/index.js +26 -4
- package/src/geometries/geom3/invert.js +5 -1
- package/src/geometries/geom3/isA.js +5 -1
- package/src/geometries/geom3/isConvex.d.ts +3 -0
- package/src/geometries/geom3/isConvex.js +65 -0
- package/src/geometries/geom3/isConvex.test.js +44 -0
- package/src/geometries/geom3/toPolygons.js +4 -2
- package/src/geometries/geom3/toString.js +3 -2
- package/src/geometries/geom3/toVertices.js +8 -4
- package/src/geometries/geom3/transform.js +5 -2
- package/src/geometries/geom3/validate.js +6 -2
- package/src/geometries/index.js +9 -7
- package/src/geometries/path2/appendArc.js +7 -5
- package/src/geometries/path2/appendArc.test.js +11 -15
- package/src/geometries/path2/appendBezier.js +6 -4
- package/src/geometries/path2/appendPoints.js +4 -2
- package/src/geometries/path2/applyTransforms.js +3 -0
- package/src/geometries/path2/clone.js +5 -1
- package/src/geometries/path2/close.js +5 -1
- package/src/geometries/path2/concat.js +3 -2
- package/src/geometries/path2/create.js +4 -15
- package/src/geometries/path2/equals.js +12 -7
- package/src/geometries/path2/fromPoints.js +5 -3
- package/src/geometries/path2/index.js +21 -4
- package/src/geometries/path2/isA.js +5 -1
- package/src/geometries/path2/reverse.js +4 -2
- package/src/geometries/path2/toPoints.js +5 -3
- package/src/geometries/path2/toString.js +3 -2
- package/src/geometries/path2/transform.js +4 -2
- package/src/geometries/path2/validate.js +5 -1
- package/src/geometries/path3/applyTransforms.js +1 -1
- package/src/geometries/path3/clone.d.ts +3 -0
- package/src/geometries/path3/clone.js +11 -0
- package/src/geometries/path3/close.js +4 -2
- package/src/geometries/path3/concat.js +2 -3
- package/src/geometries/path3/create.js +4 -20
- package/src/geometries/path3/equals.js +4 -2
- package/src/geometries/path3/fromVertices.js +2 -3
- package/src/geometries/path3/index.d.ts +1 -0
- package/src/geometries/path3/index.js +18 -1
- package/src/geometries/path3/isA.js +4 -2
- package/src/geometries/path3/reverse.js +2 -3
- package/src/geometries/path3/toString.js +2 -3
- package/src/geometries/path3/toVertices.js +2 -3
- package/src/geometries/path3/transform.js +2 -3
- package/src/geometries/path3/validate.js +6 -3
- package/src/geometries/poly2/arePointsInside.js +4 -1
- package/src/geometries/poly2/clone.js +4 -1
- package/src/geometries/poly2/create.js +2 -9
- package/src/geometries/poly2/index.js +16 -4
- package/src/geometries/poly2/isA.js +5 -1
- package/src/geometries/poly2/isConvex.js +5 -1
- package/src/geometries/poly2/isSimple.js +5 -1
- package/src/geometries/poly2/measureArea.js +4 -1
- package/src/geometries/poly2/measureBoundingBox.js +6 -1
- package/src/geometries/poly2/reverse.js +4 -1
- package/src/geometries/poly2/toPoints.js +6 -1
- package/src/geometries/poly2/toString.js +5 -1
- package/src/geometries/poly2/transform.js +5 -1
- package/src/geometries/poly2/type.d.ts +1 -5
- package/src/geometries/poly2/validate.js +6 -2
- package/src/geometries/poly3/clone.js +4 -1
- package/src/geometries/poly3/create.js +3 -11
- package/src/geometries/poly3/fromVerticesAndPlane.js +3 -1
- package/src/geometries/poly3/index.js +19 -4
- package/src/geometries/poly3/invert.js +4 -1
- package/src/geometries/poly3/isA.js +5 -1
- package/src/geometries/poly3/isConvex.js +5 -1
- package/src/geometries/poly3/measureArea.js +5 -1
- package/src/geometries/poly3/measureBoundingBox.js +4 -1
- package/src/geometries/poly3/measureBoundingSphere.js +4 -3
- package/src/geometries/poly3/measureSignedVolume.js +6 -1
- package/src/geometries/poly3/plane.js +6 -0
- package/src/geometries/poly3/toString.js +5 -1
- package/src/geometries/poly3/toVertices.js +6 -1
- package/src/geometries/poly3/transform.js +5 -1
- package/src/geometries/poly3/validate.js +6 -2
- package/src/geometries/slice/calculatePlane.js +3 -3
- package/src/geometries/slice/clone.js +4 -1
- package/src/geometries/slice/create.js +5 -10
- package/src/geometries/slice/equals.js +5 -1
- package/src/geometries/slice/fromOutlines.d.ts +5 -0
- package/src/geometries/slice/fromOutlines.js +16 -0
- package/src/geometries/slice/fromOutlines.test.js +17 -0
- package/src/geometries/slice/fromVertices.js +3 -3
- package/src/geometries/slice/index.d.ts +1 -1
- package/src/geometries/slice/index.js +20 -5
- package/src/geometries/slice/isA.js +5 -1
- package/src/geometries/slice/reverse.js +5 -2
- package/src/geometries/slice/toEdges.js +5 -3
- package/src/geometries/slice/toPolygons.js +5 -1
- package/src/geometries/slice/toString.js +5 -1
- package/src/geometries/slice/toVertices.js +5 -3
- package/src/geometries/slice/transform.js +4 -3
- package/src/geometries/slice/validate.js +3 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +4 -0
- package/src/maths/constants.js +11 -7
- package/src/maths/index.js +2 -1
- package/src/maths/mat4/isOnlyTransformScale.js +1 -1
- package/src/maths/plane/fromNormalAndPoint.js +4 -6
- package/src/maths/plane/fromPoints.js +8 -7
- package/src/maths/plane/fromPointsRandom.js +13 -13
- package/src/measurements/measureAggregateEpsilon.js +3 -1
- package/src/measurements/measureAggregateEpsilon.test.js +1 -1
- package/src/measurements/measureArea.js +6 -4
- package/src/measurements/measureArea.test.js +4 -1
- package/src/measurements/measureBoundingBox.js +16 -2
- package/src/measurements/measureBoundingBox.test.js +4 -1
- package/src/measurements/measureBoundingSphere.js +38 -29
- package/src/measurements/measureBoundingSphere.test.js +4 -1
- package/src/measurements/measureCenterOfMass.js +3 -2
- package/src/measurements/measureEpsilon.js +4 -2
- package/src/operations/booleans/index.js +2 -0
- package/src/operations/booleans/intersect.js +0 -1
- package/src/operations/booleans/scission.js +0 -1
- package/src/operations/booleans/trees/splitLineSegmentByPlane.js +1 -4
- package/src/operations/booleans/trees/splitPolygonByPlane.d.ts +1 -3
- package/src/operations/booleans/trees/splitPolygonByPlane.test.js +138 -0
- package/src/operations/booleans/union.js +1 -1
- package/src/operations/booleans/unionGeom3.test.js +35 -0
- package/src/operations/extrusions/extrudeFromSlices.js +16 -6
- package/src/operations/extrusions/extrudeFromSlices.test.js +1 -1
- package/src/operations/extrusions/extrudeHelical.js +2 -1
- package/src/operations/extrusions/extrudeLinear.js +1 -1
- package/src/operations/extrusions/extrudeLinearGeom2.js +2 -1
- package/src/operations/extrusions/extrudeRotate.js +3 -2
- package/src/operations/extrusions/extrudeRotate.test.js +34 -0
- package/src/operations/extrusions/extrudeWalls.test.js +60 -0
- package/src/operations/hulls/hull.js +3 -2
- package/src/operations/hulls/toUniquePoints.js +3 -0
- package/src/operations/minkowski/index.d.ts +1 -0
- package/src/operations/minkowski/index.js +15 -0
- package/src/operations/minkowski/minkowskiSum.d.ts +4 -0
- package/src/operations/minkowski/minkowskiSum.js +223 -0
- package/src/operations/minkowski/minkowskiSum.test.js +199 -0
- package/src/operations/modifiers/generalize.js +9 -2
- package/src/operations/modifiers/reTesselateCoplanarPolygons.js +10 -3
- package/src/operations/modifiers/reTesselateCoplanarPolygons.test.js +36 -1
- package/src/operations/modifiers/retessellate.js +4 -2
- package/src/operations/modifiers/snap.js +22 -3
- package/src/operations/modifiers/snap.test.js +24 -15
- package/src/operations/offsets/offsetGeom3.test.js +5 -7
- package/src/operations/transforms/align.js +2 -1
- package/src/operations/transforms/align.test.js +1 -1
- package/src/operations/transforms/mirror.js +6 -2
- package/src/operations/transforms/rotate.js +6 -2
- package/src/operations/transforms/scale.js +6 -2
- package/src/operations/transforms/transform.js +6 -2
- package/src/operations/transforms/transform.test.js +16 -5
- package/src/operations/transforms/translate.js +6 -2
- package/src/primitives/arc.js +13 -12
- package/src/primitives/arc.test.js +104 -113
- package/src/primitives/circle.js +10 -9
- package/src/primitives/cube.js +5 -6
- package/src/primitives/cuboid.js +6 -6
- package/src/primitives/cylinder.js +8 -8
- package/src/primitives/cylinderElliptic.js +11 -11
- package/src/primitives/ellipse.js +10 -9
- package/src/primitives/ellipsoid.js +8 -8
- package/src/primitives/geodesicSphere.js +6 -6
- package/src/primitives/line.js +2 -0
- package/src/primitives/polygon.js +6 -7
- package/src/primitives/polyhedron.js +7 -8
- package/src/primitives/rectangle.js +6 -6
- package/src/primitives/roundedCuboid.js +8 -8
- package/src/primitives/roundedCylinder.js +9 -9
- package/src/primitives/roundedRectangle.js +8 -8
- package/src/primitives/sphere.js +7 -8
- package/src/primitives/square.js +6 -6
- package/src/primitives/star.js +10 -10
- package/src/primitives/torus.js +11 -11
- package/src/primitives/triangle.js +7 -6
- package/src/utils/areAllShapesTheSameType.js +4 -0
- package/src/utils/flatten.js +1 -1
- package/src/utils/flatten.test.js +94 -0
- package/src/geometries/slice/fromGeom2.d.ts +0 -5
- package/src/geometries/slice/fromGeom2.js +0 -17
package/src/primitives/arc.js
CHANGED
|
@@ -8,6 +8,7 @@ import { isGT, isGTE, isNumberArray } from './commonChecks.js'
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Construct an arc in two dimensional space where all points are at the same distance from the center.
|
|
11
|
+
*
|
|
11
12
|
* @param {object} [options] - options for construction
|
|
12
13
|
* @param {Array} [options.center=[0,0]] - center of arc
|
|
13
14
|
* @param {number} [options.radius=1] - radius of arc
|
|
@@ -17,19 +18,19 @@ import { isGT, isGTE, isNumberArray } from './commonChecks.js'
|
|
|
17
18
|
* @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
19
|
* @returns {Path2} new 2D path
|
|
19
20
|
* @alias module:modeling/primitives.arc
|
|
21
|
+
*
|
|
20
22
|
* @example
|
|
21
23
|
* let myshape = arc({ center: [-1, -1], radius: 2, endAngle: (TAU / 4)})
|
|
22
24
|
*/
|
|
23
|
-
export const arc = (options) => {
|
|
24
|
-
|
|
25
|
-
center
|
|
26
|
-
radius
|
|
27
|
-
startAngle
|
|
28
|
-
endAngle
|
|
29
|
-
makeTangent
|
|
30
|
-
segments
|
|
31
|
-
}
|
|
32
|
-
let { center, radius, startAngle, endAngle, makeTangent, segments } = Object.assign({}, defaults, options)
|
|
25
|
+
export const arc = (options = {}) => {
|
|
26
|
+
let {
|
|
27
|
+
center = [0, 0],
|
|
28
|
+
radius = 1,
|
|
29
|
+
startAngle = 0,
|
|
30
|
+
endAngle = TAU,
|
|
31
|
+
makeTangent = false,
|
|
32
|
+
segments = 32
|
|
33
|
+
} = options
|
|
33
34
|
|
|
34
35
|
if (!isNumberArray(center, 2)) throw new Error('center must be an array of X and Y values')
|
|
35
36
|
if (!isGT(radius, 0)) throw new Error('radius must be greater than zero')
|
|
@@ -60,8 +61,8 @@ export const arc = (options) => {
|
|
|
60
61
|
vec2.add(point, point, centerV)
|
|
61
62
|
pointArray.push(point)
|
|
62
63
|
} else {
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
const numSteps = Math.floor(segments * (Math.abs(rotation) / TAU))
|
|
65
|
+
|
|
65
66
|
let edgeStepSize = numSteps * 0.5 / rotation // step size for half a degree
|
|
66
67
|
if (edgeStepSize > 0.25) edgeStepSize = 0.25
|
|
67
68
|
|
|
@@ -13,205 +13,196 @@ test('arc (defaults)', (t) => {
|
|
|
13
13
|
const obs = path2.toPoints(geometry)
|
|
14
14
|
|
|
15
15
|
t.notThrows(() => path2.validate(geometry))
|
|
16
|
-
t.is(obs.length,
|
|
16
|
+
t.is(obs.length, 32)
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
test('arc (options)', (t) => {
|
|
20
20
|
// test center
|
|
21
21
|
let exp = [
|
|
22
22
|
[3, 2],
|
|
23
|
-
[2.
|
|
24
|
-
[2.
|
|
25
|
-
[2.
|
|
26
|
-
[2
|
|
27
|
-
[1.
|
|
28
|
-
[1.
|
|
29
|
-
[1.
|
|
30
|
-
[1
|
|
31
|
-
[1.
|
|
32
|
-
[1.
|
|
33
|
-
[1.
|
|
34
|
-
[
|
|
35
|
-
[2.
|
|
36
|
-
[2.
|
|
37
|
-
[2.
|
|
38
|
-
[2.9324722294043557, 1.6387583338128469]
|
|
23
|
+
[2.923879532511287, 2.3826834323650896],
|
|
24
|
+
[2.7071067811865475, 2.7071067811865475],
|
|
25
|
+
[2.3826834323650896, 2.923879532511287],
|
|
26
|
+
[2, 3],
|
|
27
|
+
[1.6173165676349104, 2.923879532511287],
|
|
28
|
+
[1.2928932188134525, 2.7071067811865475],
|
|
29
|
+
[1.0761204674887133, 2.38268343236509],
|
|
30
|
+
[1, 2],
|
|
31
|
+
[1.076120467488713, 1.6173165676349104],
|
|
32
|
+
[1.2928932188134523, 1.2928932188134525],
|
|
33
|
+
[1.6173165676349097, 1.0761204674887135],
|
|
34
|
+
[2, 1],
|
|
35
|
+
[2.38268343236509, 1.0761204674887135],
|
|
36
|
+
[2.7071067811865475, 1.2928932188134523],
|
|
37
|
+
[2.9238795325112865, 1.6173165676349095]
|
|
39
38
|
]
|
|
40
39
|
let geometry = arc({ center: [2, 2], segments: 16 })
|
|
41
40
|
let obs = path2.toPoints(geometry)
|
|
42
41
|
|
|
43
42
|
t.notThrows(() => path2.validate(geometry))
|
|
44
|
-
t.is(obs.length,
|
|
43
|
+
t.is(obs.length, 16)
|
|
45
44
|
t.true(comparePoints(obs, exp))
|
|
46
45
|
|
|
47
46
|
// test radius
|
|
48
47
|
exp = [
|
|
49
48
|
[2, 0],
|
|
50
|
-
[1.
|
|
51
|
-
[1.
|
|
52
|
-
[0.
|
|
53
|
-
[0
|
|
54
|
-
[-0.
|
|
55
|
-
[-1.
|
|
56
|
-
[-1.
|
|
57
|
-
[-
|
|
58
|
-
[-1.
|
|
59
|
-
[-1.
|
|
60
|
-
[-
|
|
61
|
-
[
|
|
62
|
-
[0.
|
|
63
|
-
[
|
|
64
|
-
[1.
|
|
65
|
-
[1.8649444588087116, -0.7224833323743061]
|
|
49
|
+
[1.8477590650225735, 0.7653668647301796],
|
|
50
|
+
[1.4142135623730951, 1.414213562373095],
|
|
51
|
+
[0.7653668647301797, 1.8477590650225735],
|
|
52
|
+
[0, 2],
|
|
53
|
+
[-0.7653668647301795, 1.8477590650225735],
|
|
54
|
+
[-1.414213562373095, 1.4142135623730951],
|
|
55
|
+
[-1.8477590650225735, 0.7653668647301798],
|
|
56
|
+
[-2, 0],
|
|
57
|
+
[-1.8477590650225737, -0.7653668647301793],
|
|
58
|
+
[-1.4142135623730954, -1.414213562373095],
|
|
59
|
+
[-0.7653668647301807, -1.847759065022573],
|
|
60
|
+
[0, -2],
|
|
61
|
+
[0.76536686473018, -1.8477590650225733],
|
|
62
|
+
[1.4142135623730947, -1.4142135623730954],
|
|
63
|
+
[1.847759065022573, -0.7653668647301808]
|
|
66
64
|
]
|
|
67
65
|
geometry = arc({ radius: 2, segments: 16 })
|
|
68
66
|
obs = path2.toPoints(geometry)
|
|
69
67
|
|
|
70
68
|
t.notThrows(() => path2.validate(geometry))
|
|
71
|
-
t.is(obs.length,
|
|
69
|
+
t.is(obs.length, 16)
|
|
72
70
|
t.true(comparePoints(obs, exp))
|
|
73
71
|
|
|
74
72
|
// test startAngle
|
|
75
73
|
exp = [
|
|
76
|
-
[
|
|
77
|
-
[-0.
|
|
78
|
-
[-0.
|
|
79
|
-
[-0.
|
|
80
|
-
[-
|
|
81
|
-
[-0.
|
|
82
|
-
[-0.
|
|
83
|
-
[-0.
|
|
84
|
-
[
|
|
85
|
-
[0.
|
|
86
|
-
[0.
|
|
87
|
-
[0.
|
|
88
|
-
[
|
|
89
|
-
[1, -2.4492935982947064e-16]
|
|
74
|
+
[0, 1],
|
|
75
|
+
[-0.3826834323650897, 0.9238795325112867],
|
|
76
|
+
[-0.7071067811865475, 0.7071067811865476],
|
|
77
|
+
[-0.9238795325112867, 0.3826834323650899],
|
|
78
|
+
[-1, 0],
|
|
79
|
+
[-0.9238795325112868, -0.38268343236508967],
|
|
80
|
+
[-0.7071067811865477, -0.7071067811865475],
|
|
81
|
+
[-0.38268343236509034, -0.9238795325112865],
|
|
82
|
+
[0, -1],
|
|
83
|
+
[0.38268343236509, -0.9238795325112866],
|
|
84
|
+
[0.7071067811865474, -0.7071067811865477],
|
|
85
|
+
[0.9238795325112865, -0.3826834323650904],
|
|
86
|
+
[1, 0]
|
|
90
87
|
]
|
|
91
88
|
geometry = arc({ startAngle: TAU / 4, segments: 16 })
|
|
92
89
|
obs = path2.toPoints(geometry)
|
|
93
90
|
|
|
94
91
|
t.notThrows(() => path2.validate(geometry))
|
|
95
|
-
t.is(obs.length,
|
|
92
|
+
t.is(obs.length, 13)
|
|
96
93
|
t.true(comparePoints(obs, exp))
|
|
97
94
|
|
|
98
95
|
// test endAngle
|
|
99
96
|
exp = [
|
|
100
97
|
[1, 0],
|
|
101
|
-
[0.
|
|
102
|
-
[0.
|
|
103
|
-
[0.
|
|
104
|
-
[0
|
|
105
|
-
[6.123233995736766e-17, 1]
|
|
98
|
+
[0.9238795325112867, 0.3826834323650898],
|
|
99
|
+
[0.7071067811865476, 0.7071067811865475],
|
|
100
|
+
[0.38268343236508984, 0.9238795325112867],
|
|
101
|
+
[0, 1]
|
|
106
102
|
]
|
|
107
103
|
geometry = arc({ endAngle: TAU / 4, segments: 16 })
|
|
108
104
|
obs = path2.toPoints(geometry)
|
|
109
105
|
|
|
110
106
|
t.notThrows(() => path2.validate(geometry))
|
|
111
|
-
t.is(obs.length,
|
|
107
|
+
t.is(obs.length, 5)
|
|
112
108
|
t.true(comparePoints(obs, exp))
|
|
113
109
|
|
|
114
110
|
// test makeTangent
|
|
115
111
|
exp = [
|
|
116
112
|
[1, 0],
|
|
117
|
-
[0.
|
|
118
|
-
[0.
|
|
119
|
-
[0.
|
|
120
|
-
[0.
|
|
121
|
-
[0.
|
|
122
|
-
[-0.
|
|
123
|
-
[-0.
|
|
124
|
-
[-0.
|
|
125
|
-
[-
|
|
126
|
-
[-0.
|
|
127
|
-
[-0.
|
|
128
|
-
[-0.
|
|
129
|
-
[-0.
|
|
130
|
-
[0.
|
|
131
|
-
[0.
|
|
132
|
-
[0.
|
|
133
|
-
[0.
|
|
134
|
-
[0.9957341762950345, -0.09226835946330197]
|
|
113
|
+
[0.9951847266721969, 0.0980171403295606],
|
|
114
|
+
[0.8876396204028539, 0.46053871095824],
|
|
115
|
+
[0.6531728429537769, 0.7572088465064846],
|
|
116
|
+
[0.325310292162263, 0.9456073253805213],
|
|
117
|
+
[-0.04906767432741801, 0.9987954562051724],
|
|
118
|
+
[-0.416429560097637, 0.9091679830905225],
|
|
119
|
+
[-0.7242470829514668, 0.689540544737067],
|
|
120
|
+
[-0.9285060804732155, 0.3713171939518377],
|
|
121
|
+
[-1, 0],
|
|
122
|
+
[-0.9285060804732156, -0.37131719395183743],
|
|
123
|
+
[-0.724247082951467, -0.6895405447370668],
|
|
124
|
+
[-0.4164295600976372, -0.9091679830905224],
|
|
125
|
+
[-0.04906767432741803, -0.9987954562051724],
|
|
126
|
+
[0.3253102921622629, -0.9456073253805213],
|
|
127
|
+
[0.6531728429537768, -0.7572088465064846],
|
|
128
|
+
[0.8876396204028539, -0.46053871095823995],
|
|
129
|
+
[0.9951847266721969, -0.0980171403295605]
|
|
135
130
|
]
|
|
136
131
|
geometry = arc({ makeTangent: true, segments: 16 })
|
|
137
132
|
obs = path2.toPoints(geometry)
|
|
138
133
|
|
|
139
134
|
t.notThrows(() => path2.validate(geometry))
|
|
140
|
-
t.is(obs.length,
|
|
135
|
+
t.is(obs.length, 18)
|
|
141
136
|
t.true(comparePoints(obs, exp))
|
|
142
137
|
|
|
143
138
|
// test segments
|
|
144
139
|
exp = [
|
|
145
140
|
[1, 0],
|
|
146
|
-
[0.
|
|
147
|
-
[0
|
|
148
|
-
[-0.
|
|
149
|
-
[-
|
|
150
|
-
[-0.
|
|
151
|
-
[
|
|
152
|
-
[0.
|
|
153
|
-
[0.7660444431189778, -0.6427876096865396]
|
|
141
|
+
[0.7071067811865476, 0.7071067811865475],
|
|
142
|
+
[0, 1],
|
|
143
|
+
[-0.7071067811865475, 0.7071067811865476],
|
|
144
|
+
[-1, 0],
|
|
145
|
+
[-0.7071067811865477, -0.7071067811865475],
|
|
146
|
+
[0, -1],
|
|
147
|
+
[0.7071067811865474, -0.7071067811865477]
|
|
154
148
|
]
|
|
155
149
|
geometry = arc({ segments: 8 })
|
|
156
150
|
obs = path2.toPoints(geometry)
|
|
157
151
|
|
|
158
152
|
t.notThrows(() => path2.validate(geometry))
|
|
159
|
-
t.is(obs.length,
|
|
153
|
+
t.is(obs.length, 8)
|
|
160
154
|
t.true(comparePoints(obs, exp))
|
|
161
155
|
})
|
|
162
156
|
|
|
163
157
|
test('arc (rotations)', (t) => {
|
|
164
158
|
let exp = [
|
|
165
|
-
[
|
|
166
|
-
[-0.
|
|
167
|
-
[-0.
|
|
168
|
-
[-0.
|
|
169
|
-
[-
|
|
170
|
-
[-1, 1.2246467991473532e-16]
|
|
159
|
+
[0, 1],
|
|
160
|
+
[-0.3826834323650897, 0.9238795325112867],
|
|
161
|
+
[-0.7071067811865475, 0.7071067811865476],
|
|
162
|
+
[-0.9238795325112867, 0.3826834323650899],
|
|
163
|
+
[-1, 0]
|
|
171
164
|
]
|
|
172
165
|
let geometry = arc({ startAngle: TAU / 4, endAngle: TAU / 2, segments: 16 })
|
|
173
166
|
let obs = path2.toPoints(geometry)
|
|
174
167
|
|
|
175
168
|
t.notThrows(() => path2.validate(geometry))
|
|
176
|
-
t.is(obs.length,
|
|
169
|
+
t.is(obs.length, 5)
|
|
177
170
|
t.true(comparePoints(obs, exp))
|
|
178
171
|
|
|
179
172
|
exp = [
|
|
180
|
-
[-1,
|
|
181
|
-
[-0.
|
|
182
|
-
[-0.
|
|
183
|
-
[-0.
|
|
184
|
-
[
|
|
185
|
-
[0.
|
|
186
|
-
[0.
|
|
187
|
-
[0.
|
|
188
|
-
[
|
|
189
|
-
[1, -2.4492935982947064e-16]
|
|
173
|
+
[-1, 0],
|
|
174
|
+
[-0.9238795325112868, -0.38268343236508967],
|
|
175
|
+
[-0.7071067811865477, -0.7071067811865475],
|
|
176
|
+
[-0.38268343236509034, -0.9238795325112865],
|
|
177
|
+
[0, -1],
|
|
178
|
+
[0.38268343236509, -0.9238795325112866],
|
|
179
|
+
[0.7071067811865474, -0.7071067811865477],
|
|
180
|
+
[0.9238795325112865, -0.3826834323650904],
|
|
181
|
+
[1, 0]
|
|
190
182
|
]
|
|
191
183
|
geometry = arc({ startAngle: TAU / 2, endAngle: TAU, segments: 16 })
|
|
192
184
|
obs = path2.toPoints(geometry)
|
|
193
185
|
|
|
194
186
|
t.notThrows(() => path2.validate(geometry))
|
|
195
|
-
t.is(obs.length,
|
|
187
|
+
t.is(obs.length, 9)
|
|
196
188
|
t.true(comparePoints(obs, exp))
|
|
197
189
|
|
|
198
190
|
exp = [
|
|
199
|
-
[
|
|
200
|
-
[0.
|
|
201
|
-
[0.
|
|
202
|
-
[0.
|
|
203
|
-
[
|
|
204
|
-
[0.
|
|
205
|
-
[0.
|
|
206
|
-
[0.
|
|
207
|
-
[0
|
|
208
|
-
[3.061616997868383e-16, 1]
|
|
191
|
+
[0, -1],
|
|
192
|
+
[0.38268343236509, -0.9238795325112866],
|
|
193
|
+
[0.7071067811865474, -0.7071067811865477],
|
|
194
|
+
[0.9238795325112865, -0.3826834323650904],
|
|
195
|
+
[1, 0],
|
|
196
|
+
[0.9238795325112867, 0.38268343236508995],
|
|
197
|
+
[0.7071067811865477, 0.7071067811865474],
|
|
198
|
+
[0.38268343236509045, 0.9238795325112865],
|
|
199
|
+
[0, 1]
|
|
209
200
|
]
|
|
210
201
|
geometry = arc({ startAngle: TAU * 0.75, endAngle: TAU / 4, segments: 16 })
|
|
211
202
|
obs = path2.toPoints(geometry)
|
|
212
203
|
|
|
213
204
|
t.notThrows(() => path2.validate(geometry))
|
|
214
|
-
t.is(obs.length,
|
|
205
|
+
t.is(obs.length, 9)
|
|
215
206
|
t.true(comparePoints(obs, exp))
|
|
216
207
|
|
|
217
208
|
exp = [[-1.8369701987210297e-16, -1]]
|
package/src/primitives/circle.js
CHANGED
|
@@ -6,6 +6,7 @@ import { isGTE } from './commonChecks.js'
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Construct a circle in two dimensional space where all points are at the same distance from the center.
|
|
9
|
+
*
|
|
9
10
|
* @see [ellipse]{@link module:modeling/primitives.ellipse} for more options
|
|
10
11
|
* @param {object} [options] - options for construction
|
|
11
12
|
* @param {Array} [options.center=[0,0]] - center of circle
|
|
@@ -15,18 +16,18 @@ import { isGTE } from './commonChecks.js'
|
|
|
15
16
|
* @param {number} [options.segments=32] - number of segments to create per full rotation
|
|
16
17
|
* @returns {Geom2} new 2D geometry
|
|
17
18
|
* @alias module:modeling/primitives.circle
|
|
19
|
+
*
|
|
18
20
|
* @example
|
|
19
21
|
* let myshape = circle({radius: 10})
|
|
20
22
|
*/
|
|
21
|
-
export const circle = (options) => {
|
|
22
|
-
|
|
23
|
-
center
|
|
24
|
-
radius
|
|
25
|
-
startAngle
|
|
26
|
-
endAngle
|
|
27
|
-
segments
|
|
28
|
-
}
|
|
29
|
-
let { center, radius, startAngle, endAngle, segments } = Object.assign({}, defaults, options)
|
|
23
|
+
export const circle = (options = {}) => {
|
|
24
|
+
let {
|
|
25
|
+
center = [0, 0],
|
|
26
|
+
radius = 1,
|
|
27
|
+
startAngle = 0,
|
|
28
|
+
endAngle = TAU,
|
|
29
|
+
segments = 32
|
|
30
|
+
} = options
|
|
30
31
|
|
|
31
32
|
if (!isGTE(radius, 0)) throw new Error('radius must be positive')
|
|
32
33
|
|
package/src/primitives/cube.js
CHANGED
|
@@ -12,12 +12,11 @@ import { isGTE } from './commonChecks.js'
|
|
|
12
12
|
* @example
|
|
13
13
|
* let myshape = cube({size: 10})
|
|
14
14
|
*/
|
|
15
|
-
export const cube = (options) => {
|
|
16
|
-
|
|
17
|
-
center
|
|
18
|
-
size
|
|
19
|
-
}
|
|
20
|
-
let { center, size } = Object.assign({}, defaults, options)
|
|
15
|
+
export const cube = (options = {}) => {
|
|
16
|
+
let {
|
|
17
|
+
center = [0, 0, 0],
|
|
18
|
+
size = 2
|
|
19
|
+
} = options
|
|
21
20
|
|
|
22
21
|
if (!isGTE(size, 0)) throw new Error('size must be positive')
|
|
23
22
|
|
package/src/primitives/cuboid.js
CHANGED
|
@@ -5,6 +5,7 @@ import { isNumberArray } from './commonChecks.js'
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Construct an axis-aligned solid cuboid in three dimensional space.
|
|
8
|
+
*
|
|
8
9
|
* @param {object} [options] - options for construction
|
|
9
10
|
* @param {Array} [options.center=[0,0,0]] - center of cuboid
|
|
10
11
|
* @param {Array} [options.size=[2,2,2]] - dimensions of cuboid; width, depth, height
|
|
@@ -14,12 +15,11 @@ import { isNumberArray } from './commonChecks.js'
|
|
|
14
15
|
* @example
|
|
15
16
|
* let myshape = cuboid({size: [5, 10, 5]})
|
|
16
17
|
*/
|
|
17
|
-
export const cuboid = (options) => {
|
|
18
|
-
const
|
|
19
|
-
center
|
|
20
|
-
size
|
|
21
|
-
}
|
|
22
|
-
const { center, size } = Object.assign({}, defaults, options)
|
|
18
|
+
export const cuboid = (options = {}) => {
|
|
19
|
+
const {
|
|
20
|
+
center = [0, 0, 0],
|
|
21
|
+
size = [2, 2, 2]
|
|
22
|
+
} = options
|
|
23
23
|
|
|
24
24
|
if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
|
|
25
25
|
if (!isNumberArray(size, 3)) throw new Error('size must be an array of width, depth and height values')
|
|
@@ -4,6 +4,7 @@ import * as geom3 from '../geometries/geom3/index.js'
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Construct a Z axis-aligned cylinder in three dimensional space.
|
|
7
|
+
*
|
|
7
8
|
* @see [cylinderElliptic]{@link module:modeling/primitives.cylinderElliptic} for more options
|
|
8
9
|
* @param {object} [options] - options for construction
|
|
9
10
|
* @param {Array} [options.center=[0,0,0]] - center of cylinder
|
|
@@ -16,14 +17,13 @@ import * as geom3 from '../geometries/geom3/index.js'
|
|
|
16
17
|
* @example
|
|
17
18
|
* let myshape = cylinder({height: 2, radius: 10})
|
|
18
19
|
*/
|
|
19
|
-
export const cylinder = (options) => {
|
|
20
|
-
const
|
|
21
|
-
center
|
|
22
|
-
height
|
|
23
|
-
radius
|
|
24
|
-
segments
|
|
25
|
-
}
|
|
26
|
-
const { center, height, radius, segments } = Object.assign({}, defaults, options)
|
|
20
|
+
export const cylinder = (options = {}) => {
|
|
21
|
+
const {
|
|
22
|
+
center = [0, 0, 0],
|
|
23
|
+
height = 2,
|
|
24
|
+
radius = 1,
|
|
25
|
+
segments = 32
|
|
26
|
+
} = options
|
|
27
27
|
|
|
28
28
|
if (!isGTE(radius, 0)) throw new Error('radius must be positive')
|
|
29
29
|
|
|
@@ -11,6 +11,7 @@ import { isGT, isGTE, isNumberArray } from './commonChecks.js'
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Construct a Z axis-aligned elliptic cylinder in three dimensional space.
|
|
14
|
+
*
|
|
14
15
|
* @param {object} [options] - options for construction
|
|
15
16
|
* @param {Array} [options.center=[0,0,0]] - center of cylinder
|
|
16
17
|
* @param {number} [options.height=2] - height of cylinder
|
|
@@ -25,17 +26,16 @@ import { isGT, isGTE, isNumberArray } from './commonChecks.js'
|
|
|
25
26
|
* @example
|
|
26
27
|
* let myshape = cylinderElliptic({height: 2, startRadius: [10,5], endRadius: [8,3]})
|
|
27
28
|
*/
|
|
28
|
-
export const cylinderElliptic = (options) => {
|
|
29
|
-
|
|
30
|
-
center
|
|
31
|
-
height
|
|
32
|
-
startRadius
|
|
33
|
-
startAngle
|
|
34
|
-
endRadius
|
|
35
|
-
endAngle
|
|
36
|
-
segments
|
|
37
|
-
}
|
|
38
|
-
let { center, height, startRadius, startAngle, endRadius, endAngle, segments } = Object.assign({}, defaults, options)
|
|
29
|
+
export const cylinderElliptic = (options = {}) => {
|
|
30
|
+
let {
|
|
31
|
+
center = [0, 0, 0],
|
|
32
|
+
height = 2,
|
|
33
|
+
startRadius = [1, 1],
|
|
34
|
+
startAngle = 0,
|
|
35
|
+
endRadius = [1, 1],
|
|
36
|
+
endAngle = TAU,
|
|
37
|
+
segments = 32
|
|
38
|
+
} = options
|
|
39
39
|
|
|
40
40
|
if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
|
|
41
41
|
if (!isGT(height, 0)) throw new Error('height must be greater then zero')
|
|
@@ -10,6 +10,7 @@ import { isGTE, isNumberArray } from './commonChecks.js'
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Construct an axis-aligned ellipse in two dimensional space.
|
|
13
|
+
*
|
|
13
14
|
* @see https://en.wikipedia.org/wiki/Ellipse
|
|
14
15
|
* @param {object} [options] - options for construction
|
|
15
16
|
* @param {Array} [options.center=[0,0]] - center of ellipse
|
|
@@ -19,18 +20,18 @@ import { isGTE, isNumberArray } from './commonChecks.js'
|
|
|
19
20
|
* @param {number} [options.segments=32] - number of segments to create per full rotation
|
|
20
21
|
* @returns {Geom2} new 2D geometry
|
|
21
22
|
* @alias module:modeling/primitives.ellipse
|
|
23
|
+
*
|
|
22
24
|
* @example
|
|
23
25
|
* let myshape = ellipse({radius: [5,10]})
|
|
24
26
|
*/
|
|
25
|
-
export const ellipse = (options) => {
|
|
26
|
-
|
|
27
|
-
center
|
|
28
|
-
radius
|
|
29
|
-
startAngle
|
|
30
|
-
endAngle
|
|
31
|
-
segments
|
|
32
|
-
}
|
|
33
|
-
let { center, radius, startAngle, endAngle, segments } = Object.assign({}, defaults, options)
|
|
27
|
+
export const ellipse = (options = {}) => {
|
|
28
|
+
let {
|
|
29
|
+
center = [0, 0],
|
|
30
|
+
radius = [1, 1],
|
|
31
|
+
startAngle = 0,
|
|
32
|
+
endAngle = TAU,
|
|
33
|
+
segments = 32
|
|
34
|
+
} = options
|
|
34
35
|
|
|
35
36
|
if (!isNumberArray(center, 2)) throw new Error('center must be an array of X and Y values')
|
|
36
37
|
if (!isNumberArray(radius, 2)) throw new Error('radius must be an array of X and Y values')
|
|
@@ -9,6 +9,7 @@ import { isGTE, isNumberArray } from './commonChecks.js'
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Construct an axis-aligned ellipsoid in three dimensional space.
|
|
12
|
+
*
|
|
12
13
|
* @param {object} [options] - options for construction
|
|
13
14
|
* @param {Array} [options.center=[0,0,0]] - center of ellipsoid
|
|
14
15
|
* @param {Array} [options.radius=[1,1,1]] - radius of ellipsoid, along X, Y and Z
|
|
@@ -20,14 +21,13 @@ import { isGTE, isNumberArray } from './commonChecks.js'
|
|
|
20
21
|
* @example
|
|
21
22
|
* let myshape = ellipsoid({radius: [5, 10, 20]})
|
|
22
23
|
*/
|
|
23
|
-
export const ellipsoid = (options) => {
|
|
24
|
-
const
|
|
25
|
-
center
|
|
26
|
-
radius
|
|
27
|
-
segments
|
|
28
|
-
axes
|
|
29
|
-
}
|
|
30
|
-
const { center, radius, segments, axes } = Object.assign({}, defaults, options)
|
|
24
|
+
export const ellipsoid = (options = {}) => {
|
|
25
|
+
const {
|
|
26
|
+
center = [0, 0, 0],
|
|
27
|
+
radius = [1, 1, 1],
|
|
28
|
+
segments = 32,
|
|
29
|
+
axes = [[1, 0, 0], [0, -1, 0], [0, 0, 1]]
|
|
30
|
+
} = options
|
|
31
31
|
|
|
32
32
|
if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
|
|
33
33
|
if (!isNumberArray(radius, 3)) throw new Error('radius must be an array of X, Y and Z values')
|
|
@@ -8,6 +8,7 @@ import { isGTE } from './commonChecks.js'
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Construct a geodesic sphere based on icosahedron symmetry.
|
|
11
|
+
*
|
|
11
12
|
* @param {object} [options] - options for construction
|
|
12
13
|
* @param {number} [options.radius=1] - target radius of sphere
|
|
13
14
|
* @param {number} [options.frequency=6] - subdivision frequency per face, multiples of 6
|
|
@@ -17,12 +18,11 @@ import { isGTE } from './commonChecks.js'
|
|
|
17
18
|
* @example
|
|
18
19
|
* let myshape = geodesicSphere({radius: 15, frequency: 18})
|
|
19
20
|
*/
|
|
20
|
-
export const geodesicSphere = (options) => {
|
|
21
|
-
|
|
22
|
-
radius
|
|
23
|
-
frequency
|
|
24
|
-
}
|
|
25
|
-
let { radius, frequency } = Object.assign({}, defaults, options)
|
|
21
|
+
export const geodesicSphere = (options = {}) => {
|
|
22
|
+
let {
|
|
23
|
+
radius = 1,
|
|
24
|
+
frequency = 6
|
|
25
|
+
} = options
|
|
26
26
|
|
|
27
27
|
if (!isGTE(radius, 0)) throw new Error('radius must be positive')
|
|
28
28
|
if (!isGTE(frequency, 6)) throw new Error('frequency must be six or more')
|
package/src/primitives/line.js
CHANGED
|
@@ -2,7 +2,9 @@ import * as path2 from '../geometries/path2/index.js'
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Construct a new line in two dimensional space from the given points.
|
|
5
|
+
*
|
|
5
6
|
* The points must be provided as an array, where each element is a 2D point.
|
|
7
|
+
*
|
|
6
8
|
* @param {Array} points - array of points from which to create the path
|
|
7
9
|
* @returns {Path2} new 2D path
|
|
8
10
|
* @alias module:modeling/primitives.line
|
|
@@ -24,13 +24,12 @@ import * as geom2 from '../geometries/geom2/index.js'
|
|
|
24
24
|
* or
|
|
25
25
|
* let poly = polygon({ points: [roof, wall], paths: [[0, 1, 2], [3, 4, 5, 6]] })
|
|
26
26
|
*/
|
|
27
|
-
export const polygon = (options) => {
|
|
28
|
-
const
|
|
29
|
-
points
|
|
30
|
-
paths
|
|
31
|
-
orientation
|
|
32
|
-
}
|
|
33
|
-
const { points, paths, orientation } = Object.assign({}, defaults, options)
|
|
27
|
+
export const polygon = (options = {}) => {
|
|
28
|
+
const {
|
|
29
|
+
points = [],
|
|
30
|
+
paths = [],
|
|
31
|
+
orientation = 'counterclockwise'
|
|
32
|
+
} = options
|
|
34
33
|
|
|
35
34
|
if (!(Array.isArray(points) && Array.isArray(paths))) throw new Error('points and paths must be arrays')
|
|
36
35
|
|
|
@@ -21,14 +21,13 @@ import { isNumberArray } from './commonChecks.js'
|
|
|
21
21
|
* let myFaces = [ [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4], [1, 0, 3], [2, 1, 3] ]
|
|
22
22
|
* let myShape = polyhedron({points: myPoints, faces: myFaces, orientation: 'inward'})
|
|
23
23
|
*/
|
|
24
|
-
export const polyhedron = (options) => {
|
|
25
|
-
const
|
|
26
|
-
points
|
|
27
|
-
faces
|
|
28
|
-
colors
|
|
29
|
-
orientation
|
|
30
|
-
}
|
|
31
|
-
const { points, faces, colors, orientation } = Object.assign({}, defaults, options)
|
|
24
|
+
export const polyhedron = (options = {}) => {
|
|
25
|
+
const {
|
|
26
|
+
points = [],
|
|
27
|
+
faces = [],
|
|
28
|
+
colors = undefined,
|
|
29
|
+
orientation = 'outward'
|
|
30
|
+
} = options
|
|
32
31
|
|
|
33
32
|
if (!(Array.isArray(points) && Array.isArray(faces))) {
|
|
34
33
|
throw new Error('points and faces must be arrays')
|