@jscad/modeling 3.0.4-alpha.0 → 3.0.6-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.
Files changed (116) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/jscad-modeling.es.js +2 -2
  3. package/dist/jscad-modeling.min.js +2 -2
  4. package/package.json +4 -4
  5. package/rollup.config.js +1 -1
  6. package/src/colors/colorize.js +17 -1
  7. package/src/colors/hsvToRgb.js +1 -0
  8. package/src/colors/rgbToHsl.js +3 -1
  9. package/src/colors/rgbToHsv.js +1 -0
  10. package/src/curves/bezier/create.js +1 -1
  11. package/src/geometries/geom2/fromPoints.d.ts +4 -0
  12. package/src/geometries/geom2/fromPoints.js +28 -0
  13. package/src/geometries/geom2/fromPoints.test.js +22 -0
  14. package/src/geometries/geom2/index.d.ts +1 -0
  15. package/src/geometries/geom2/index.js +1 -0
  16. package/src/geometries/geom2/transform.js +1 -0
  17. package/src/geometries/geom3/transform.js +1 -0
  18. package/src/geometries/geom3/validate.js +11 -1
  19. package/src/geometries/path2/appendArc.js +19 -25
  20. package/src/geometries/path2/appendBezier.js +8 -11
  21. package/src/geometries/path2/appendPoints.js +21 -3
  22. package/src/geometries/path2/appendPoints.test.js +16 -4
  23. package/src/geometries/path2/close.js +7 -10
  24. package/src/geometries/path2/concat.js +2 -2
  25. package/src/geometries/path2/fromPoints.js +7 -7
  26. package/src/geometries/path2/reverse.js +3 -3
  27. package/src/geometries/path2/transform.js +1 -0
  28. package/src/geometries/path2/validate.js +2 -2
  29. package/src/geometries/path3/clone.d.ts +3 -0
  30. package/src/geometries/path3/clone.js +11 -0
  31. package/src/geometries/path3/close.js +7 -8
  32. package/src/geometries/path3/index.d.ts +1 -0
  33. package/src/geometries/path3/index.js +1 -0
  34. package/src/geometries/path3/transform.js +1 -0
  35. package/src/geometries/poly2/type.d.ts +1 -5
  36. package/src/geometries/slice/earcut/index.js +4 -2
  37. package/src/geometries/slice/earcut/linkedPolygon.js +4 -2
  38. package/src/geometries/slice/fromOutlines.d.ts +5 -0
  39. package/src/geometries/slice/fromOutlines.js +16 -0
  40. package/src/geometries/slice/fromOutlines.test.js +17 -0
  41. package/src/geometries/slice/index.d.ts +1 -1
  42. package/src/geometries/slice/index.js +1 -1
  43. package/src/geometries/slice/transform.js +2 -1
  44. package/src/maths/line2/intersectPointOfLines.js +1 -4
  45. package/src/maths/plane/fromNormalAndPoint.js +4 -6
  46. package/src/maths/plane/fromPoints.js +8 -7
  47. package/src/maths/plane/fromPointsRandom.js +13 -13
  48. package/src/measurements/measureAggregateEpsilon.js +3 -1
  49. package/src/measurements/measureAggregateEpsilon.test.js +1 -1
  50. package/src/measurements/measureArea.js +6 -4
  51. package/src/measurements/measureArea.test.js +4 -1
  52. package/src/measurements/measureBoundingBox.js +16 -2
  53. package/src/measurements/measureBoundingBox.test.js +4 -1
  54. package/src/measurements/measureBoundingSphere.js +38 -29
  55. package/src/measurements/measureBoundingSphere.test.js +4 -1
  56. package/src/measurements/measureCenterOfMass.js +3 -2
  57. package/src/measurements/measureEpsilon.js +4 -2
  58. package/src/operations/booleans/martinez/computeFields.js +6 -0
  59. package/src/operations/booleans/martinez/divideSegment.js +2 -1
  60. package/src/operations/booleans/martinez/fillQueue.js +3 -1
  61. package/src/operations/booleans/martinez/subdivideSegments.js +5 -4
  62. package/src/operations/booleans/subtractGeom3Sub.js +1 -1
  63. package/src/operations/booleans/trees/PolygonTreeNode.js +3 -0
  64. package/src/operations/booleans/trees/splitPolygonByPlane.d.ts +1 -3
  65. package/src/operations/booleans/union.js +1 -1
  66. package/src/operations/extrusions/extrudeFromSlices.js +1 -1
  67. package/src/operations/extrusions/extrudeFromSlices.test.js +1 -1
  68. package/src/operations/extrusions/extrudeHelical.js +2 -1
  69. package/src/operations/extrusions/extrudeLinear.js +1 -1
  70. package/src/operations/extrusions/extrudeLinearGeom2.js +12 -8
  71. package/src/operations/extrusions/extrudeRotate.js +1 -1
  72. package/src/operations/hulls/hull.js +3 -2
  73. package/src/operations/hulls/quickhull/Face.js +8 -3
  74. package/src/operations/hulls/quickhull/QuickHull.js +10 -5
  75. package/src/operations/hulls/quickhull/VertexList.js +2 -1
  76. package/src/operations/hulls/toUniquePoints.js +3 -0
  77. package/src/operations/modifiers/generalize.js +9 -2
  78. package/src/operations/modifiers/reTesselateCoplanarPolygons.js +2 -2
  79. package/src/operations/modifiers/reTesselateCoplanarPolygons.test.js +29 -3
  80. package/src/operations/modifiers/retessellate.js +1 -0
  81. package/src/operations/modifiers/snap.js +22 -3
  82. package/src/operations/modifiers/snap.test.js +12 -2
  83. package/src/operations/offsets/offsetGeom3.test.js +2 -2
  84. package/src/operations/transforms/align.js +2 -1
  85. package/src/operations/transforms/align.test.js +1 -1
  86. package/src/operations/transforms/mirror.js +6 -2
  87. package/src/operations/transforms/rotate.js +6 -2
  88. package/src/operations/transforms/scale.js +6 -2
  89. package/src/operations/transforms/transform.js +6 -2
  90. package/src/operations/transforms/transform.test.js +16 -5
  91. package/src/operations/transforms/translate.js +12 -4
  92. package/src/primitives/arc.js +14 -14
  93. package/src/primitives/circle.js +10 -9
  94. package/src/primitives/cube.js +5 -6
  95. package/src/primitives/cuboid.js +6 -6
  96. package/src/primitives/cylinder.js +8 -8
  97. package/src/primitives/cylinderElliptic.js +11 -11
  98. package/src/primitives/ellipse.js +12 -12
  99. package/src/primitives/ellipsoid.js +8 -8
  100. package/src/primitives/geodesicSphere.js +6 -6
  101. package/src/primitives/line.js +2 -0
  102. package/src/primitives/polygon.js +6 -7
  103. package/src/primitives/polyhedron.js +7 -8
  104. package/src/primitives/rectangle.js +6 -6
  105. package/src/primitives/roundedCuboid.js +8 -8
  106. package/src/primitives/roundedCylinder.js +9 -9
  107. package/src/primitives/roundedRectangle.js +8 -8
  108. package/src/primitives/sphere.js +7 -8
  109. package/src/primitives/square.js +6 -6
  110. package/src/primitives/star.js +12 -14
  111. package/src/primitives/torus.js +11 -11
  112. package/src/primitives/triangle.js +7 -6
  113. package/src/utils/areAllShapesTheSameType.js +4 -0
  114. package/test/helpers/nearlyEqual.js +1 -0
  115. package/src/geometries/slice/fromGeom2.d.ts +0 -5
  116. package/src/geometries/slice/fromGeom2.js +0 -17
@@ -3,6 +3,8 @@ import * as mat4 from '../../maths/mat4/index.js'
3
3
  import * as geom2 from '../../geometries/geom2/index.js'
4
4
  import * as geom3 from '../../geometries/geom3/index.js'
5
5
  import * as path2 from '../../geometries/path2/index.js'
6
+ import * as path3 from '../../geometries/path3/index.js'
7
+ import * as slice from '../../geometries/slice/index.js'
6
8
 
7
9
  /**
8
10
  * Translate the given objects using the given options.
@@ -18,15 +20,21 @@ export const translate = (offset, ...objects) => {
18
20
  if (!Array.isArray(offset)) throw new Error('offset must be an array')
19
21
 
20
22
  // adjust the offset if necessary
21
- offset = offset.slice() // don't modify the original
22
- while (offset.length < 3) offset.push(0)
23
+ if (offset.length < 3) {
24
+ offset = offset.slice() // don't modify the original
25
+ while (offset.length < 3) {
26
+ offset.push(0)
27
+ }
28
+ }
23
29
 
24
30
  const matrix = mat4.fromTranslation(mat4.create(), offset)
25
31
 
26
32
  const results = objects.map((object) => {
27
- if (path2.isA(object)) return path2.transform(matrix, object)
28
- if (geom2.isA(object)) return geom2.transform(matrix, object)
29
33
  if (geom3.isA(object)) return geom3.transform(matrix, object)
34
+ if (geom2.isA(object)) return geom2.transform(matrix, object)
35
+ if (path2.isA(object)) return path2.transform(matrix, object)
36
+ if (path3.isA(object)) return path3.transform(matrix, object)
37
+ if (slice.isA(object)) return slice.transform(matrix, object)
30
38
  // handle recursive arrays
31
39
  if (Array.isArray(object)) return translate(offset, ...object)
32
40
  return object
@@ -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
- const defaults = {
25
- center: [0, 0],
26
- radius: 1,
27
- startAngle: 0,
28
- endAngle: TAU,
29
- makeTangent: false,
30
- segments: 32
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')
@@ -50,14 +51,13 @@ export const arc = (options) => {
50
51
 
51
52
  const minAngle = Math.acos(((radius * radius) + (radius * radius) - (EPS * EPS)) / (2 * radius * radius))
52
53
 
53
- const centerV = vec2.clone(center)
54
54
  let point
55
55
  const pointArray = []
56
56
  if (rotation < minAngle) {
57
57
  // there is no rotation, just a single point
58
58
  point = vec2.fromAngleRadians(vec2.create(), startAngle)
59
59
  vec2.scale(point, point, radius)
60
- vec2.add(point, point, centerV)
60
+ vec2.add(point, point, center)
61
61
  pointArray.push(point)
62
62
  } else {
63
63
  const numSteps = Math.floor(segments * (Math.abs(rotation) / TAU))
@@ -76,9 +76,9 @@ export const arc = (options) => {
76
76
  const angle = startAngle + (step * (rotation / numSteps))
77
77
  point = vec2.fromAngleRadians(vec2.create(), angle)
78
78
  vec2.scale(point, point, radius)
79
- vec2.add(point, point, centerV)
79
+ vec2.add(point, point, center)
80
80
  pointArray.push(point)
81
81
  }
82
82
  }
83
- return path2.fromPoints({ closed: false }, pointArray)
83
+ return path2.fromPoints({}, pointArray)
84
84
  }
@@ -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
- const defaults = {
23
- center: [0, 0],
24
- radius: 1,
25
- startAngle: 0,
26
- endAngle: TAU,
27
- segments: 32
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
 
@@ -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
- const defaults = {
17
- center: [0, 0, 0],
18
- size: 2
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
 
@@ -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 defaults = {
19
- center: [0, 0, 0],
20
- size: [2, 2, 2]
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 defaults = {
21
- center: [0, 0, 0],
22
- height: 2,
23
- radius: 1,
24
- segments: 32
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
- const defaults = {
30
- center: [0, 0, 0],
31
- height: 2,
32
- startRadius: [1, 1],
33
- startAngle: 0,
34
- endRadius: [1, 1],
35
- endAngle: TAU,
36
- segments: 32
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
- const defaults = {
27
- center: [0, 0],
28
- radius: [1, 1],
29
- startAngle: 0,
30
- endAngle: TAU,
31
- segments: 32
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')
@@ -60,7 +61,6 @@ export const ellipse = (options) => {
60
61
 
61
62
  segments = Math.floor(segments * (rotation / TAU))
62
63
 
63
- const centerV = vec2.clone(center)
64
64
  const step = rotation / segments // radians per segment
65
65
 
66
66
  const points = []
@@ -68,9 +68,9 @@ export const ellipse = (options) => {
68
68
  for (let i = 0; i < segments; i++) {
69
69
  const angle = (step * i) + startAngle
70
70
  const point = vec2.fromValues(radius[0] * cos(angle), radius[1] * sin(angle))
71
- vec2.add(point, centerV, point)
71
+ vec2.add(point, center, point)
72
72
  points.push(point)
73
73
  }
74
- if (rotation < TAU) points.push(centerV)
74
+ if (rotation < TAU) points.push(vec2.clone(center)) // close with a new point
75
75
  return geom2.create([points])
76
76
  }
@@ -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 defaults = {
25
- center: [0, 0, 0],
26
- radius: [1, 1, 1],
27
- segments: 32,
28
- axes: [[1, 0, 0], [0, -1, 0], [0, 0, 1]]
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
- const defaults = {
22
- radius: 1,
23
- frequency: 6
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')
@@ -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 defaults = {
29
- points: [],
30
- paths: [],
31
- orientation: 'counterclockwise'
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 defaults = {
26
- points: [],
27
- faces: [],
28
- colors: undefined,
29
- orientation: 'outward'
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')
@@ -6,6 +6,7 @@ import { isNumberArray } from './commonChecks.js'
6
6
 
7
7
  /**
8
8
  * Construct an axis-aligned rectangle in two dimensional space with four sides at right angles.
9
+ *
9
10
  * @param {object} [options] - options for construction
10
11
  * @param {Array} [options.center=[0,0]] - center of rectangle
11
12
  * @param {Array} [options.size=[2,2]] - dimension of rectangle, width and length
@@ -15,12 +16,11 @@ import { isNumberArray } from './commonChecks.js'
15
16
  * @example
16
17
  * let myshape = rectangle({size: [10, 20]})
17
18
  */
18
- export const rectangle = (options) => {
19
- const defaults = {
20
- center: [0, 0],
21
- size: [2, 2]
22
- }
23
- const { center, size } = Object.assign({}, defaults, options)
19
+ export const rectangle = (options = {}) => {
20
+ const {
21
+ center = [0, 0],
22
+ size = [2, 2]
23
+ } = options
24
24
 
25
25
  if (!isNumberArray(center, 2)) throw new Error('center must be an array of X and Y values')
26
26
  if (!isNumberArray(size, 2)) throw new Error('size must be an array of X and Y values')
@@ -115,6 +115,7 @@ const stitchSides = (bottomCorners, topCorners) => {
115
115
 
116
116
  /**
117
117
  * Construct an axis-aligned solid cuboid in three dimensional space with rounded corners.
118
+ *
118
119
  * @param {object} [options] - options for construction
119
120
  * @param {Array} [options.center=[0,0,0]] - center of rounded cube
120
121
  * @param {Array} [options.size=[2,2,2]] - dimension of rounded cube; width, depth, height
@@ -126,14 +127,13 @@ const stitchSides = (bottomCorners, topCorners) => {
126
127
  * @example
127
128
  * let myCube = roundedCuboid({size: [10, 20, 10], roundRadius: 2, segments: 16})
128
129
  */
129
- export const roundedCuboid = (options) => {
130
- const defaults = {
131
- center: [0, 0, 0],
132
- size: [2, 2, 2],
133
- roundRadius: 0.2,
134
- segments: 32
135
- }
136
- let { center, size, roundRadius, segments } = Object.assign({}, defaults, options)
130
+ export const roundedCuboid = (options = {}) => {
131
+ let {
132
+ center = [0, 0, 0],
133
+ size = [2, 2, 2],
134
+ roundRadius = 0.2,
135
+ segments = 32
136
+ } = options
137
137
 
138
138
  if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
139
139
  if (!isNumberArray(size, 3)) throw new Error('size must be an array of X, Y and Z values')
@@ -12,6 +12,7 @@ import { cylinder } from './cylinder.js'
12
12
 
13
13
  /**
14
14
  * Construct a Z axis-aligned solid cylinder in three dimensional space with rounded ends.
15
+ *
15
16
  * @param {object} [options] - options for construction
16
17
  * @param {Array} [options.center=[0,0,0]] - center of cylinder
17
18
  * @param {number} [options.height=2] - height of cylinder
@@ -24,15 +25,14 @@ import { cylinder } from './cylinder.js'
24
25
  * @example
25
26
  * let myshape = roundedCylinder({ height: 10, radius: 2, roundRadius: 0.5 })
26
27
  */
27
- export const roundedCylinder = (options) => {
28
- const defaults = {
29
- center: [0, 0, 0],
30
- height: 2,
31
- radius: 1,
32
- roundRadius: 0.2,
33
- segments: 32
34
- }
35
- const { center, height, radius, roundRadius, segments } = Object.assign({}, defaults, options)
28
+ export const roundedCylinder = (options = {}) => {
29
+ const {
30
+ center = [0, 0, 0],
31
+ height = 2,
32
+ radius = 1,
33
+ roundRadius = 0.2,
34
+ segments = 32
35
+ } = options
36
36
 
37
37
  if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
38
38
  if (!isGTE(height, 0)) throw new Error('height must be positive')
@@ -10,6 +10,7 @@ import { rectangle } from './rectangle.js'
10
10
 
11
11
  /**
12
12
  * Construct an axis-aligned rectangle in two dimensional space with rounded corners.
13
+ *
13
14
  * @param {object} [options] - options for construction
14
15
  * @param {Array} [options.center=[0,0]] - center of rounded rectangle
15
16
  * @param {Array} [options.size=[2,2]] - dimension of rounded rectangle; width and length
@@ -21,14 +22,13 @@ import { rectangle } from './rectangle.js'
21
22
  * @example
22
23
  * let myshape = roundedRectangle({size: [10, 20], roundRadius: 2})
23
24
  */
24
- export const roundedRectangle = (options) => {
25
- const defaults = {
26
- center: [0, 0],
27
- size: [2, 2],
28
- roundRadius: 0.2,
29
- segments: 32
30
- }
31
- let { center, size, roundRadius, segments } = Object.assign({}, defaults, options)
25
+ export const roundedRectangle = (options = {}) => {
26
+ let {
27
+ center = [0, 0],
28
+ size = [2, 2],
29
+ roundRadius = 0.2,
30
+ segments = 32
31
+ } = options
32
32
 
33
33
  if (!isNumberArray(center, 2)) throw new Error('center must be an array of X and Y values')
34
34
  if (!isNumberArray(size, 2)) throw new Error('size must be an array of X and Y values')
@@ -15,14 +15,13 @@ import { isGTE } from './commonChecks.js'
15
15
  * @example
16
16
  * let myshape = sphere({radius: 5})
17
17
  */
18
- export const sphere = (options) => {
19
- const defaults = {
20
- center: [0, 0, 0],
21
- radius: 1,
22
- segments: 32,
23
- axes: [[1, 0, 0], [0, -1, 0], [0, 0, 1]]
24
- }
25
- let { center, radius, segments, axes } = Object.assign({}, defaults, options)
18
+ export const sphere = (options = {}) => {
19
+ let {
20
+ center = [0, 0, 0],
21
+ radius = 1,
22
+ segments = 32,
23
+ axes = [[1, 0, 0], [0, -1, 0], [0, 0, 1]]
24
+ } = options
26
25
 
27
26
  if (!isGTE(radius, 0)) throw new Error('radius must be positive')
28
27
 
@@ -3,6 +3,7 @@ import { isGTE } from './commonChecks.js'
3
3
 
4
4
  /**
5
5
  * Construct an axis-aligned square in two dimensional space with four equal sides at right angles.
6
+ *
6
7
  * @see [rectangle]{@link module:modeling/primitives.rectangle} for more options
7
8
  * @param {object} [options] - options for construction
8
9
  * @param {Array} [options.center=[0,0]] - center of square
@@ -13,12 +14,11 @@ import { isGTE } from './commonChecks.js'
13
14
  * @example
14
15
  * let myshape = square({size: 10})
15
16
  */
16
- export const square = (options) => {
17
- const defaults = {
18
- center: [0, 0],
19
- size: 2
20
- }
21
- let { center, size } = Object.assign({}, defaults, options)
17
+ export const square = (options = {}) => {
18
+ let {
19
+ center = [0, 0],
20
+ size = 2
21
+ } = options
22
22
 
23
23
  if (!isGTE(size, 0)) throw new Error('size must be positive')
24
24
 
@@ -28,6 +28,7 @@ const getPoints = (vertices, radius, startAngle, center) => {
28
28
 
29
29
  /**
30
30
  * Construct a star in two dimensional space.
31
+ *
31
32
  * @see https://en.wikipedia.org/wiki/Star_polygon
32
33
  * @param {object} [options] - options for construction
33
34
  * @param {Array} [options.center=[0,0]] - center of star
@@ -43,16 +44,15 @@ const getPoints = (vertices, radius, startAngle, center) => {
43
44
  * let star1 = star({vertices: 8, outerRadius: 10}) // star with 8/2 density
44
45
  * let star2 = star({vertices: 12, outerRadius: 40, innerRadius: 20}) // star with given radius
45
46
  */
46
- export const star = (options) => {
47
- const defaults = {
48
- center: [0, 0],
49
- vertices: 5,
50
- outerRadius: 1,
51
- innerRadius: 0,
52
- density: 2,
53
- startAngle: 0
54
- }
55
- let { center, vertices, outerRadius, innerRadius, density, startAngle } = Object.assign({}, defaults, options)
47
+ export const star = (options = {}) => {
48
+ let {
49
+ center = [0, 0],
50
+ vertices = 5,
51
+ outerRadius = 1,
52
+ innerRadius = 0,
53
+ density = 2,
54
+ startAngle = 0
55
+ } = options
56
56
 
57
57
  if (!isNumberArray(center, 2)) throw new Error('center must be an array of X and Y values')
58
58
  if (!isGTE(vertices, 2)) throw new Error('vertices must be two or more')
@@ -71,10 +71,8 @@ export const star = (options) => {
71
71
  innerRadius = outerRadius * getRadiusRatio(vertices, density)
72
72
  }
73
73
 
74
- const centerV = vec2.clone(center)
75
-
76
- const outerPoints = getPoints(vertices, outerRadius, startAngle, centerV)
77
- const innerPoints = getPoints(vertices, innerRadius, startAngle + Math.PI / vertices, centerV)
74
+ const outerPoints = getPoints(vertices, outerRadius, startAngle, center)
75
+ const innerPoints = getPoints(vertices, innerRadius, startAngle + Math.PI / vertices, center)
78
76
 
79
77
  const allPoints = []
80
78
  for (let i = 0; i < vertices; i++) {