@jscad/modeling 3.0.5-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 (48) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/jscad-modeling.es.js +2 -2
  3. package/dist/jscad-modeling.min.js +2 -2
  4. package/package.json +2 -2
  5. package/src/colors/hsvToRgb.js +1 -0
  6. package/src/colors/rgbToHsl.js +3 -1
  7. package/src/colors/rgbToHsv.js +1 -0
  8. package/src/curves/bezier/create.js +1 -1
  9. package/src/geometries/geom2/transform.js +1 -0
  10. package/src/geometries/geom3/transform.js +1 -0
  11. package/src/geometries/geom3/validate.js +11 -1
  12. package/src/geometries/path2/appendArc.js +19 -25
  13. package/src/geometries/path2/appendBezier.js +8 -11
  14. package/src/geometries/path2/appendPoints.js +21 -3
  15. package/src/geometries/path2/appendPoints.test.js +16 -4
  16. package/src/geometries/path2/close.js +7 -10
  17. package/src/geometries/path2/concat.js +2 -2
  18. package/src/geometries/path2/fromPoints.js +7 -7
  19. package/src/geometries/path2/reverse.js +3 -3
  20. package/src/geometries/path2/transform.js +1 -0
  21. package/src/geometries/path2/validate.js +2 -2
  22. package/src/geometries/path3/close.js +7 -8
  23. package/src/geometries/path3/transform.js +1 -0
  24. package/src/geometries/slice/earcut/index.js +4 -2
  25. package/src/geometries/slice/earcut/linkedPolygon.js +4 -2
  26. package/src/geometries/slice/transform.js +2 -1
  27. package/src/maths/line2/intersectPointOfLines.js +1 -4
  28. package/src/operations/booleans/martinez/computeFields.js +6 -0
  29. package/src/operations/booleans/martinez/divideSegment.js +2 -1
  30. package/src/operations/booleans/martinez/fillQueue.js +3 -1
  31. package/src/operations/booleans/martinez/subdivideSegments.js +5 -4
  32. package/src/operations/booleans/subtractGeom3Sub.js +1 -1
  33. package/src/operations/booleans/trees/PolygonTreeNode.js +3 -0
  34. package/src/operations/extrusions/extrudeLinearGeom2.js +10 -7
  35. package/src/operations/hulls/quickhull/Face.js +8 -3
  36. package/src/operations/hulls/quickhull/QuickHull.js +10 -5
  37. package/src/operations/hulls/quickhull/VertexList.js +2 -1
  38. package/src/operations/modifiers/reTesselateCoplanarPolygons.js +2 -2
  39. package/src/operations/modifiers/reTesselateCoplanarPolygons.test.js +29 -3
  40. package/src/operations/modifiers/retessellate.js +1 -0
  41. package/src/operations/modifiers/snap.js +3 -3
  42. package/src/operations/modifiers/snap.test.js +12 -2
  43. package/src/operations/offsets/offsetGeom3.test.js +2 -2
  44. package/src/operations/transforms/translate.js +6 -2
  45. package/src/primitives/arc.js +3 -4
  46. package/src/primitives/ellipse.js +2 -3
  47. package/src/primitives/star.js +2 -4
  48. package/test/helpers/nearlyEqual.js +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jscad/modeling",
3
- "version": "3.0.5-alpha.0",
3
+ "version": "3.0.6-alpha.0",
4
4
  "description": "Constructive Solid Geometry (CSG) Library for JSCAD",
5
5
  "homepage": "https://openjscad.xyz/",
6
6
  "repository": "https://github.com/jscad/OpenJSCAD.org",
@@ -63,5 +63,5 @@
63
63
  "c8": "^10.1.0",
64
64
  "rollup": "^4.52.0"
65
65
  },
66
- "gitHead": "942d9a5eab2f234f2e1c617d5896e0230f353330"
66
+ "gitHead": "201d3987b309fd1f383b10b5555dd0a2765cad43"
67
67
  }
@@ -56,6 +56,7 @@ export const hsvToRgb = (...values) => {
56
56
  b = v
57
57
  break
58
58
  case 5:
59
+ default:
59
60
  r = v
60
61
  g = p
61
62
  b = q
@@ -24,7 +24,8 @@ export const rgbToHsl = (...values) => {
24
24
  const l = (max + min) / 2
25
25
 
26
26
  if (max === min) {
27
- h = s = 0 // achromatic
27
+ h = 0
28
+ s = 0 // achromatic
28
29
  } else {
29
30
  const d = max - min
30
31
  s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
@@ -36,6 +37,7 @@ export const rgbToHsl = (...values) => {
36
37
  h = (b - r) / d + 2
37
38
  break
38
39
  case b:
40
+ default:
39
41
  h = (r - g) / d + 4
40
42
  break
41
43
  }
@@ -35,6 +35,7 @@ export const rgbToHsv = (...values) => {
35
35
  h = (b - r) / d + 2
36
36
  break
37
37
  case b:
38
+ default:
38
39
  h = (r - g) / d + 4
39
40
  break
40
41
  }
@@ -51,7 +51,7 @@ const getPointType = function (points) {
51
51
  })
52
52
  pType = 'float_' + point.length
53
53
  } else throw new Error('Bezier points must all be numbers or arrays of number.')
54
- if (firstPointType == null) {
54
+ if (firstPointType === null) {
55
55
  firstPointType = pType
56
56
  } else {
57
57
  if (firstPointType !== pType) {
@@ -18,6 +18,7 @@ import { reverse } from './reverse.js'
18
18
  */
19
19
  export const transform = (matrix, geometry) => {
20
20
  const transforms = mat4.multiply(mat4.create(), matrix, geometry.transforms)
21
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
21
22
  const transformed = Object.assign({}, geometry, { transforms })
22
23
  // determine if the transform is mirroring in 2D
23
24
  if (matrix[0] * matrix[5] - matrix[4] * matrix[1] < 0) {
@@ -17,5 +17,6 @@ import * as mat4 from '../../maths/mat4/index.js'
17
17
  */
18
18
  export const transform = (matrix, geometry) => {
19
19
  const transforms = mat4.multiply(mat4.create(), matrix, geometry.transforms)
20
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
20
21
  return Object.assign({}, geometry, { transforms })
21
22
  }
@@ -22,7 +22,17 @@ export const validate = (object) => {
22
22
  }
23
23
 
24
24
  // check polygons
25
- object.polygons.forEach(poly3.validate)
25
+ object.polygons.forEach((p, i) => {
26
+ if (p.vertices.length < 3) {
27
+ throw new Error(`invalid polygon ${i}: only ${p.vertices.length} vertices`)
28
+ }
29
+
30
+ try {
31
+ poly3.validate(p)
32
+ } catch (e) {
33
+ throw new Error(`invalid polygon ${i}: ${e}`)
34
+ }
35
+ })
26
36
  validateManifold(object)
27
37
 
28
38
  // check transforms
@@ -1,7 +1,7 @@
1
1
  import { TAU } from '../../maths/constants.js'
2
2
  import * as vec2 from '../../maths/vec2/index.js'
3
3
 
4
- import { fromPoints } from './fromPoints.js'
4
+ import { appendPoints } from './appendPoints.js'
5
5
  import { toPoints } from './toPoints.js'
6
6
 
7
7
  /**
@@ -27,19 +27,19 @@ import { toPoints } from './toPoints.js'
27
27
  * myShape = path2.appendArc({endpoint: [12.5, -22.96875], radius: [15, -19.6875]}, myShape);
28
28
  */
29
29
  export const appendArc = (options, geometry) => {
30
- const defaults = {
31
- radius: [0, 0], // X and Y radius
32
- xaxisRotation: 0,
33
- clockwise: false,
34
- large: false,
35
- segments: 16
36
- }
37
- let { endpoint, radius, xaxisRotation, clockwise, large, segments } = Object.assign({}, defaults, options)
30
+ const {
31
+ endpoint = null,
32
+ radius = [0, 0], // X and Y radius
33
+ xaxisRotation = 0,
34
+ clockwise = false,
35
+ large = false,
36
+ segments = 16
37
+ } = options
38
38
 
39
39
  // validate the given options
40
40
  if (!Array.isArray(endpoint)) throw new Error('endpoint must be an array of X and Y values')
41
- if (endpoint.length < 2) throw new Error('endpoint must contain X and Y values')
42
- endpoint = vec2.clone(endpoint)
41
+ if (endpoint.length !== 2) throw new Error('endpoint must contain X and Y values')
42
+ let xendPoint = vec2.clone(endpoint)
43
43
 
44
44
  if (!Array.isArray(radius)) throw new Error('radius must be an array of X and Y values')
45
45
  if (radius.length < 2) throw new Error('radius must contain X and Y values')
@@ -48,11 +48,6 @@ export const appendArc = (options, geometry) => {
48
48
 
49
49
  const decimals = 100000
50
50
 
51
- // validate the given geometry
52
- if (geometry.isClosed) {
53
- throw new Error('the given path cannot be closed')
54
- }
55
-
56
51
  const points = toPoints(geometry)
57
52
  if (points.length < 1) {
58
53
  throw new Error('the given path must contain one or more points (as the starting point for the arc)')
@@ -65,14 +60,14 @@ export const appendArc = (options, geometry) => {
65
60
  // round to precision in order to have determinate calculations
66
61
  xRadius = Math.round(xRadius * decimals) / decimals
67
62
  yRadius = Math.round(yRadius * decimals) / decimals
68
- endpoint = vec2.fromValues(Math.round(endpoint[0] * decimals) / decimals, Math.round(endpoint[1] * decimals) / decimals)
63
+ xendPoint = vec2.fromValues(Math.round(xendPoint[0] * decimals) / decimals, Math.round(xendPoint[1] * decimals) / decimals)
69
64
 
70
65
  const sweepFlag = !clockwise
71
- let newPoints = []
66
+ const newPoints = []
72
67
  if ((xRadius === 0) || (yRadius === 0)) {
73
68
  // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes:
74
69
  // If rx = 0 or ry = 0, then treat this as a straight line from (x1, y1) to (x2, y2) and stop
75
- newPoints.push(endpoint)
70
+ newPoints.push(xendPoint)
76
71
  } else {
77
72
  xRadius = Math.abs(xRadius)
78
73
  yRadius = Math.abs(yRadius)
@@ -81,7 +76,7 @@ export const appendArc = (options, geometry) => {
81
76
  const phi = xaxisRotation
82
77
  const cosPhi = Math.cos(phi)
83
78
  const sinPhi = Math.sin(phi)
84
- const minusHalfDistance = vec2.subtract(vec2.create(), startpoint, endpoint)
79
+ const minusHalfDistance = vec2.subtract(vec2.create(), startpoint, xendPoint)
85
80
  vec2.scale(minusHalfDistance, minusHalfDistance, 0.5)
86
81
  // F.6.5.1:
87
82
  // round to precision in order to have determinate calculations
@@ -106,7 +101,7 @@ export const appendArc = (options, geometry) => {
106
101
  vec2.scale(centerTranslated, centerTranslated, multiplier1)
107
102
  // F.6.5.3:
108
103
  let center = vec2.fromValues(cosPhi * centerTranslated[0] - sinPhi * centerTranslated[1], sinPhi * centerTranslated[0] + cosPhi * centerTranslated[1])
109
- center = vec2.add(center, center, vec2.scale(vec2.create(), vec2.add(vec2.create(), startpoint, endpoint), 0.5))
104
+ center = vec2.add(center, center, vec2.scale(vec2.create(), vec2.add(vec2.create(), startpoint, xendPoint), 0.5))
110
105
 
111
106
  // F.6.5.5:
112
107
  const vector1 = vec2.fromValues((startTranslated[0] - centerTranslated[0]) / xRadius, (startTranslated[1] - centerTranslated[1]) / yRadius)
@@ -134,9 +129,8 @@ export const appendArc = (options, geometry) => {
134
129
  newPoints.push(point)
135
130
  }
136
131
  // ensure end point is precisely what user gave as parameter
137
- if (numSteps) newPoints.push(options.endpoint)
132
+ if (numSteps) newPoints.push(endpoint)
138
133
  }
139
- newPoints = points.concat(newPoints)
140
- const result = fromPoints({}, newPoints)
141
- return result
134
+
135
+ return appendPoints(newPoints, geometry)
142
136
  }
@@ -1,6 +1,6 @@
1
1
  import { TAU } from '../../maths/constants.js'
2
2
  import * as vec2 from '../../maths/vec2/index.js'
3
- import * as vec3 from '../../maths/vec3/index.js' // FIXME why vec3?
3
+ import * as vec3 from '../../maths/vec3/index.js' // required due to vec2.cross()
4
4
 
5
5
  import { appendPoints } from './appendPoints.js'
6
6
  import { toPoints } from './toPoints.js'
@@ -27,10 +27,10 @@ import { toPoints } from './toPoints.js'
27
27
  * myShape = path2.appendBezier({controlPoints: [null, [25,-30],[40,-30],[40,-20]]}, myShape)
28
28
  */
29
29
  export const appendBezier = (options, geometry) => {
30
- const defaults = {
31
- segments: 16
32
- }
33
- let { controlPoints, segments } = Object.assign({}, defaults, options)
30
+ let {
31
+ controlPoints = null,
32
+ segments = 16
33
+ } = options
34
34
 
35
35
  // validate the given options
36
36
  if (!Array.isArray(controlPoints)) throw new Error('controlPoints must be an array of one or more points')
@@ -39,10 +39,6 @@ export const appendBezier = (options, geometry) => {
39
39
  if (segments < 4) throw new Error('segments must be four or more')
40
40
 
41
41
  // validate the given geometry
42
- if (geometry.isClosed) {
43
- throw new Error('the given geometry cannot be closed')
44
- }
45
-
46
42
  const points = toPoints(geometry)
47
43
  if (points.length < 1) {
48
44
  throw new Error('the given path must contain one or more points (as the starting point for the bezier curve)')
@@ -148,9 +144,10 @@ export const appendBezier = (options, geometry) => {
148
144
  }
149
145
 
150
146
  // append to the new points to the given path
151
- // but skip the first new point because it is identical to the last point in the given path
152
- newPoints.shift()
153
147
  const result = appendPoints(newPoints, geometry)
148
+
149
+ // add a hint for the next bezier
154
150
  result.lastBezierControlPoint = controlPoints[controlPoints.length - 2]
151
+
155
152
  return result
156
153
  }
@@ -1,5 +1,7 @@
1
- import { concat } from './concat.js'
2
- import { create } from './create.js'
1
+ import { equals } from '../../maths/vec2/equals.js'
2
+
3
+ import { fromPoints } from './fromPoints.js'
4
+ import { toPoints } from './toPoints.js'
3
5
 
4
6
  /**
5
7
  * Append the given list of points to the end of the given geometry.
@@ -12,4 +14,20 @@ import { create } from './create.js'
12
14
  * @example
13
15
  * let newPath = path2.appendPoints([[3, 4], [4, 5]], oldPath)
14
16
  */
15
- export const appendPoints = (points, geometry) => concat(geometry, create(points))
17
+ export const appendPoints = (points, geometry) => {
18
+ let originalPoints = toPoints(geometry)
19
+
20
+ if (geometry.isClosed && originalPoints.length > 1) {
21
+ // add the closing point to the originalPoints
22
+ originalPoints = originalPoints.slice()
23
+ originalPoints.push(originalPoints[0])
24
+ }
25
+
26
+ if (originalPoints.length > 0) {
27
+ // remove redundant points
28
+ const lastPoint = originalPoints[originalPoints.length - 1]
29
+ while (points.length > 0 && equals(points[0], lastPoint)) points.shift()
30
+ }
31
+
32
+ return fromPoints({}, originalPoints.concat(points))
33
+ }
@@ -12,10 +12,16 @@ test('appendPoints: appending to an empty path produces a new path with expected
12
12
 
13
13
  test('appendPoints: appending to a path produces a new path with expected points', (t) => {
14
14
  const p1 = fromPoints({}, [[1, 1], [2, 2]])
15
- const obs = appendPoints([[3, 3], [4, 4]], p1)
16
- const pts = toPoints(obs)
15
+ let obs = appendPoints([[3, 3], [4, 4]], p1)
16
+ let pts = toPoints(obs)
17
17
  t.not(p1, obs)
18
18
  t.is(pts.length, 4)
19
+
20
+ const p2 = fromPoints({ closed: true }, [[0, 0], [1, 0], [0, 1]])
21
+ obs = appendPoints([[0, -1], [0, -2]], p2)
22
+ pts = toPoints(obs)
23
+ t.not(p2, obs)
24
+ t.is(pts.length, 6)
19
25
  })
20
26
 
21
27
  test('appendPoints: appending empty points to a path produces a new path with expected points', (t) => {
@@ -28,8 +34,14 @@ test('appendPoints: appending empty points to a path produces a new path with ex
28
34
 
29
35
  test('appendPoints: appending same points to a path produces a new path with expected points', (t) => {
30
36
  const p1 = fromPoints({}, [[1, 1], [2, 2]])
31
- const obs = appendPoints([[2, 2], [3, 3]], p1)
32
- const pts = toPoints(obs)
37
+ let obs = appendPoints([[2, 2], [3, 3]], p1)
38
+ let pts = toPoints(obs)
33
39
  t.not(p1, obs)
34
40
  t.is(pts.length, 3)
41
+
42
+ const p2 = fromPoints({ closed: true }, [[0, 0], [1, 0], [0, 1]])
43
+ obs = appendPoints([[0, 0], [0, 0], [0, -1]], p2)
44
+ pts = toPoints(obs)
45
+ t.not(p2, obs)
46
+ t.is(pts.length, 5)
35
47
  })
@@ -1,8 +1,6 @@
1
1
  import { EPS } from '../../maths/constants.js'
2
2
 
3
- import * as vec2 from '../../maths/vec2/index.js'
4
-
5
- import { clone } from './clone.js'
3
+ import { distance } from '../../maths/vec2/distance.js'
6
4
 
7
5
  /**
8
6
  * Close the given geometry.
@@ -17,19 +15,18 @@ import { clone } from './clone.js'
17
15
  export const close = (geometry) => {
18
16
  if (geometry.isClosed) return geometry
19
17
 
20
- const cloned = clone(geometry)
21
- cloned.isClosed = true
22
-
23
- if (cloned.points.length > 1) {
18
+ const isClosed = true
19
+ const points = geometry.points.slice()
20
+ if (points.length > 1) {
24
21
  // make sure the paths are formed properly
25
- const points = cloned.points
26
22
  const p0 = points[0]
27
23
  let pn = points[points.length - 1]
28
- while (vec2.distance(p0, pn) < (EPS * EPS)) {
24
+ while (distance(p0, pn) < EPS) {
29
25
  points.pop()
30
26
  if (points.length === 1) break
31
27
  pn = points[points.length - 1]
32
28
  }
33
29
  }
34
- return cloned
30
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
31
+ return Object.assign({}, geometry, { isClosed, points })
35
32
  }
@@ -1,4 +1,4 @@
1
- import { equals } from '../../maths/vec2/index.js'
1
+ import { equals } from '../../maths/vec2/equals.js'
2
2
 
3
3
  import { fromPoints } from './fromPoints.js'
4
4
  import { toPoints } from './toPoints.js'
@@ -6,7 +6,7 @@ import { toPoints } from './toPoints.js'
6
6
  /**
7
7
  * Concatenate the given paths.
8
8
  *
9
- * If both contain the same point at the junction, merge it into one.
9
+ * If paths contain the same junction point, merge it into one.
10
10
  * A concatenation of zero paths is an empty, open path.
11
11
  * A concatenation of one closed path to a series of open paths produces a closed path.
12
12
  * A concatenation of a path to a closed path is an error.
@@ -1,6 +1,6 @@
1
1
  import { EPS } from '../../maths/constants.js'
2
2
 
3
- import * as vec2 from '../../maths/vec2/index.js'
3
+ import { distance } from '../../maths/vec2/distance.js'
4
4
 
5
5
  import { close } from './close.js'
6
6
  import { create } from './create.js'
@@ -18,20 +18,20 @@ import { create } from './create.js'
18
18
  * @alias module:modeling/path2.fromPoints
19
19
  *
20
20
  * @example
21
- * my newPath = path2.fromPoints({closed: true}, [[10, 10], [-10, 10]])
21
+ * let newPath = path2.fromPoints({closed: true}, [[10, 10], [-10, 10]])
22
22
  */
23
23
  export const fromPoints = (options, points) => {
24
- const defaults = { closed: false }
25
- let { closed } = Object.assign({}, defaults, options)
24
+ let {
25
+ closed = false
26
+ } = options
26
27
 
27
- let created = create()
28
- created.points = points.map((point) => vec2.clone(point))
28
+ let created = create(points.slice())
29
29
 
30
30
  // check if first and last points are equal
31
31
  if (created.points.length > 1) {
32
32
  const p0 = created.points[0]
33
33
  const pn = created.points[created.points.length - 1]
34
- if (vec2.distance(p0, pn) < (EPS * EPS)) {
34
+ if (distance(p0, pn) < EPS) {
35
35
  // and close automatically
36
36
  closed = true
37
37
  }
@@ -14,7 +14,7 @@ import { clone } from './clone.js'
14
14
  */
15
15
  export const reverse = (geometry) => {
16
16
  // NOTE: this only updates the order of the points
17
- const cloned = clone(geometry)
18
- cloned.points = geometry.points.slice().reverse()
19
- return cloned
17
+ const points = geometry.points.slice().reverse()
18
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
19
+ return Object.assign({}, geometry, { points })
20
20
  }
@@ -16,5 +16,6 @@ import * as mat4 from '../../maths/mat4/index.js'
16
16
  */
17
17
  export const transform = (matrix, geometry) => {
18
18
  const transforms = mat4.multiply(mat4.create(), matrix, geometry.transforms)
19
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
19
20
  return Object.assign({}, geometry, { transforms })
20
21
  }
@@ -1,4 +1,4 @@
1
- import * as vec2 from '../../maths/vec2/index.js'
1
+ import { equals } from '../../maths/vec2/equals.js'
2
2
 
3
3
  import { isA } from './isA.js'
4
4
 
@@ -24,7 +24,7 @@ export const validate = (object) => {
24
24
  // check for duplicate points
25
25
  if (object.points.length > 1) {
26
26
  for (let i = 0; i < object.points.length; i++) {
27
- if (vec2.equals(object.points[i], object.points[(i + 1) % object.points.length])) {
27
+ if (equals(object.points[i], object.points[(i + 1) % object.points.length])) {
28
28
  throw new Error(`path2 has duplicate point ${object.points[i]}`)
29
29
  }
30
30
  }
@@ -1,6 +1,6 @@
1
1
  import { EPS } from '../../maths/constants.js'
2
2
 
3
- import * as vec3 from '../../maths/vec3/index.js'
3
+ import { distance } from '../../maths/vec3/distance.js'
4
4
 
5
5
  /**
6
6
  * Close the given geometry.
@@ -15,19 +15,18 @@ import * as vec3 from '../../maths/vec3/index.js'
15
15
  export const close = (geometry) => {
16
16
  if (geometry.isClosed) return geometry
17
17
 
18
- const cloned = Object.assign({}, geometry)
19
- cloned.isClosed = true
20
-
21
- if (cloned.vertices.length > 1) {
18
+ const isClosed = true
19
+ const vertices = geometry.vertices.slice()
20
+ if (vertices.length > 1) {
22
21
  // make sure the paths are formed properly
23
- const vertices = cloned.vertices
24
22
  const p0 = vertices[0]
25
23
  let pn = vertices[vertices.length - 1]
26
- while (vec3.distance(p0, pn) < (EPS * EPS)) {
24
+ while (distance(p0, pn) < EPS) {
27
25
  vertices.pop()
28
26
  if (vertices.length === 1) break
29
27
  pn = vertices[vertices.length - 1]
30
28
  }
31
29
  }
32
- return cloned
30
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
31
+ return Object.assign({}, geometry, { isClosed, vertices })
33
32
  }
@@ -16,5 +16,6 @@ import * as mat4 from '../../maths/mat4/index.js'
16
16
  */
17
17
  export const transform = (matrix, geometry) => {
18
18
  const transforms = mat4.multiply(mat4.create(), matrix, geometry.transforms)
19
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
19
20
  return Object.assign({}, geometry, { transforms })
20
21
  }
@@ -28,8 +28,10 @@ export const triangulate = (data, holeIndices, dim = 2) => {
28
28
 
29
29
  // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
30
30
  if (data.length > 80 * dim) {
31
- minX = maxX = data[0]
32
- minY = maxY = data[1]
31
+ minX = data[0]
32
+ maxX = data[0]
33
+ minY = data[1]
34
+ maxY = data[1]
33
35
 
34
36
  for (let i = dim; i < outerLen; i += dim) {
35
37
  const x = data[i]
@@ -39,7 +39,8 @@ export const filterPoints = (start, end) => {
39
39
 
40
40
  if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {
41
41
  removeNode(p)
42
- p = end = p.prev
42
+ p = p.prev
43
+ end = p.prev
43
44
  if (p === p.next) break
44
45
  again = true
45
46
  } else {
@@ -68,7 +69,8 @@ export const cureLocalIntersections = (start, triangles, dim) => {
68
69
  removeNode(p)
69
70
  removeNode(p.next)
70
71
 
71
- p = start = b
72
+ p = b
73
+ start = b
72
74
  }
73
75
 
74
76
  p = p.next
@@ -16,5 +16,6 @@ import { create } from './create.js'
16
16
  */
17
17
  export const transform = (matrix, slice) => {
18
18
  const contours = slice.contours.map((contour) => contour.map((vertex) => vec3.transform(vec3.create(), vertex, matrix)))
19
- return create(contours)
19
+ // use Object.assign in order to assign EXTRA attributes like color, name, etc
20
+ return Object.assign({}, slice, { contours })
20
21
  }
@@ -14,7 +14,4 @@ import { solve2Linear } from '../utils/solve2Linear.js'
14
14
  * @return {Vec2} the point of intersection
15
15
  * @alias module:modeling/maths/line2.intersectPointOfLines
16
16
  */
17
- export const intersectPointOfLines = (line1, line2) => {
18
- const point = solve2Linear(line1[0], line1[1], line2[0], line2[1], line1[2], line2[2])
19
- return vec2.clone(point)
20
- }
17
+ export const intersectPointOfLines = (line1, line2) => solve2Linear(line1[0], line1[1], line2[0], line2[1], line1[2], line2[2])
@@ -70,6 +70,8 @@ const inResult = (event, operation) => {
70
70
  (!event.isSubject && !event.otherInOut)
71
71
  case XOR:
72
72
  return true
73
+ default:
74
+ throw new Error('computeFields01')
73
75
  }
74
76
  break
75
77
  case SAME_TRANSITION:
@@ -78,6 +80,8 @@ const inResult = (event, operation) => {
78
80
  return operation === DIFFERENCE
79
81
  case NON_CONTRIBUTING:
80
82
  return false
83
+ default:
84
+ throw new Error('computeFields02')
81
85
  }
82
86
  return false
83
87
  }
@@ -104,6 +108,8 @@ const determineResultTransition = (event, operation) => {
104
108
  isIn = thatIn && !thisIn
105
109
  }
106
110
  break
111
+ default:
112
+ throw new Error('computeFields03')
107
113
  }
108
114
  return isIn ? +1 : -1
109
115
  }
@@ -12,7 +12,8 @@ export const divideSegment = (segment, point, queue) => {
12
12
  const r = new SweepEvent(point, false, segment, segment.isSubject)
13
13
  const l = new SweepEvent(point, true, segment.otherEvent, segment.isSubject)
14
14
 
15
- r.contourId = l.contourId = segment.contourId
15
+ r.contourId = segment.contourId
16
+ l.contourId = segment.contourId
16
17
 
17
18
  // avoid a rounding error. The left event would be processed after the right event
18
19
  if (compareEvents(l, segment.otherEvent) > 0) {
@@ -25,7 +25,9 @@ const processPolygon = (contourOrHole, isSubject, ringId, queue, bbox, isExterio
25
25
  continue // skip collapsed edges, or it breaks
26
26
  }
27
27
 
28
- e1.contourId = e2.contourId = ringId
28
+ e1.contourId = ringId
29
+ e2.contourId = ringId
30
+
29
31
  if (!isExteriorRing) {
30
32
  e1.isExteriorRing = false
31
33
  e2.isExteriorRing = false
@@ -32,14 +32,14 @@ export const subdivideSegments = (eventQueue, subject, clipping, sbbox, cbbox, o
32
32
  }
33
33
 
34
34
  if (event.left) {
35
- next = prev = sweepLine.insert(event)
35
+ prev = sweepLine.insert(event)
36
36
  begin = sweepLine.minNode()
37
37
 
38
+ next = sweepLine.next(prev)
39
+
38
40
  if (prev !== begin) prev = sweepLine.prev(prev)
39
41
  else prev = null
40
42
 
41
- next = sweepLine.next(next)
42
-
43
43
  const prevEvent = prev ? prev.key : null
44
44
  let prevprevEvent
45
45
  computeFields(event, prevEvent, operation)
@@ -62,7 +62,8 @@ export const subdivideSegments = (eventQueue, subject, clipping, sbbox, cbbox, o
62
62
  }
63
63
  }
64
64
  } else {
65
- next = prev = sweepLine.find(event.otherEvent)
65
+ prev = sweepLine.find(event.otherEvent)
66
+ next = prev
66
67
 
67
68
  if (prev && next) {
68
69
  // FIXME is this correct? begin is assigned if event.left, not every iterration
@@ -13,7 +13,7 @@ import { mayOverlap } from './mayOverlap.js'
13
13
  */
14
14
  export const subtractGeom3Sub = (geometry1, geometry2) => {
15
15
  if (!mayOverlap(geometry1, geometry2)) {
16
- return geom3.clone(geometry1)
16
+ return geometry1
17
17
  }
18
18
 
19
19
  const a = new Tree(geom3.toPolygons(geometry1))
@@ -215,6 +215,9 @@ export class PolygonTreeNode {
215
215
  backNodes.push(backNode)
216
216
  }
217
217
  break
218
+
219
+ default:
220
+ throw new Error('PolygonTreeNode05')
218
221
  }
219
222
  }
220
223