@jscad/modeling 3.0.2-alpha.0 → 3.0.3-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 +8 -0
- package/dist/jscad-modeling.es.js +2 -2
- package/dist/jscad-modeling.min.js +2 -2
- package/package.json +2 -2
- package/src/colors/colorize.test.js +1 -1
- package/src/geometries/geom2/index.d.ts +0 -2
- package/src/geometries/geom2/index.js +0 -2
- package/src/geometries/geom3/applyTransforms.test.js +2 -2
- package/src/geometries/geom3/clone.test.js +2 -2
- package/src/geometries/geom3/create.js +1 -9
- package/src/geometries/geom3/{fromPoints.d.ts → fromVertices.d.ts} +1 -1
- package/src/geometries/geom3/{fromPoints.js → fromVertices.js} +3 -2
- package/src/geometries/geom3/{fromPoints.test.js → fromVertices.test.js} +6 -6
- package/src/geometries/geom3/{fromPointsConvex.d.ts → fromVerticesConvex.d.ts} +1 -1
- package/src/geometries/geom3/fromVerticesConvex.js +25 -0
- package/src/geometries/geom3/{fromPointsConvex.test.js → fromVerticesConvex.test.js} +3 -3
- package/src/geometries/geom3/index.d.ts +3 -5
- package/src/geometries/geom3/index.js +4 -6
- package/src/geometries/geom3/invert.test.js +2 -2
- package/src/geometries/geom3/isA.test.js +2 -2
- package/src/geometries/geom3/toString.test.js +2 -2
- package/src/geometries/geom3/{toPoints.d.ts → toVertices.d.ts} +1 -1
- package/src/geometries/geom3/{toPoints.js → toVertices.js} +3 -2
- package/src/geometries/geom3/{toPoints.test.js → toVertices.test.js} +4 -4
- package/src/geometries/geom3/transform.test.js +2 -2
- package/src/geometries/geom3/validate.test.js +4 -4
- package/src/geometries/index.d.ts +1 -0
- package/src/geometries/index.js +1 -0
- package/src/geometries/path2/create.js +1 -10
- package/src/geometries/path2/index.d.ts +0 -2
- package/src/geometries/path2/index.js +0 -2
- package/src/geometries/path3/applyTransforms.js +22 -0
- package/src/geometries/path3/applyTransforms.test.js +28 -0
- package/src/geometries/path3/close.d.ts +3 -0
- package/src/geometries/path3/close.js +31 -0
- package/src/geometries/path3/close.test.js +43 -0
- package/src/geometries/path3/concat.d.ts +3 -0
- package/src/geometries/path3/concat.js +36 -0
- package/src/geometries/path3/concat.test.js +35 -0
- package/src/geometries/path3/create.d.ts +4 -0
- package/src/geometries/path3/create.js +30 -0
- package/src/geometries/path3/create.test.js +8 -0
- package/src/geometries/path3/equals.d.ts +3 -0
- package/src/geometries/path3/equals.js +48 -0
- package/src/geometries/path3/equals.test.js +38 -0
- package/src/geometries/path3/fromVertices.d.ts +8 -0
- package/src/geometries/path3/fromVertices.js +45 -0
- package/src/geometries/path3/fromVertices.test.js +33 -0
- package/src/geometries/path3/index.d.ts +13 -0
- package/src/geometries/path3/index.js +21 -0
- package/src/geometries/path3/isA.d.ts +3 -0
- package/src/geometries/path3/isA.js +20 -0
- package/src/geometries/path3/isA.test.js +19 -0
- package/src/geometries/path3/reverse.d.ts +3 -0
- package/src/geometries/path3/reverse.js +19 -0
- package/src/geometries/path3/reverse.test.js +9 -0
- package/src/geometries/path3/toString.d.ts +3 -0
- package/src/geometries/path3/toString.js +24 -0
- package/src/geometries/path3/toVertices.d.ts +4 -0
- package/src/geometries/path3/toVertices.js +16 -0
- package/src/geometries/path3/toVertices.test.js +13 -0
- package/src/geometries/path3/transform.d.ts +4 -0
- package/src/geometries/path3/transform.js +21 -0
- package/src/geometries/path3/transform.test.js +50 -0
- package/src/geometries/path3/type.d.ts +10 -0
- package/src/geometries/path3/validate.d.ts +1 -0
- package/src/geometries/path3/validate.js +41 -0
- package/src/geometries/poly2/create.js +1 -6
- package/src/geometries/poly3/create.js +1 -6
- package/src/operations/booleans/intersectGeom3.test.js +4 -4
- package/src/operations/booleans/subtractGeom3.test.js +4 -4
- package/src/operations/booleans/unionGeom3.test.js +5 -5
- package/src/operations/extrusions/extrudeFromSlices.test.js +6 -6
- package/src/operations/extrusions/extrudeLinear.test.js +8 -8
- package/src/operations/extrusions/extrudeRotate.test.js +12 -12
- package/src/operations/hulls/hull.test.js +5 -5
- package/src/operations/hulls/hullChain.test.js +5 -5
- package/src/operations/hulls/toUniquePoints.js +2 -2
- package/src/operations/modifiers/generalize.test.js +6 -6
- package/src/operations/modifiers/insertTjunctions.test.js +2 -2
- package/src/operations/modifiers/retessellate.test.js +10 -10
- package/src/operations/modifiers/snap.test.js +4 -4
- package/src/operations/offsets/offsetGeom3.test.js +4 -4
- package/src/operations/transforms/center.test.js +7 -7
- package/src/operations/transforms/mirror.test.js +7 -7
- package/src/operations/transforms/rotate.test.js +7 -7
- package/src/operations/transforms/scale.test.js +7 -7
- package/src/operations/transforms/transform.test.js +2 -2
- package/src/operations/transforms/translate.test.js +7 -7
- package/src/primitives/cube.test.js +4 -4
- package/src/primitives/cuboid.test.js +4 -4
- package/src/primitives/cylinder.test.js +5 -5
- package/src/primitives/cylinderElliptic.test.js +9 -9
- package/src/primitives/ellipsoid.test.js +5 -5
- package/src/primitives/geodesicSphere.test.js +4 -4
- package/src/primitives/polyhedron.test.js +2 -2
- package/src/primitives/roundedCuboid.test.js +7 -7
- package/src/primitives/roundedCylinder.test.js +9 -9
- package/src/primitives/sphere.test.js +5 -5
- package/src/primitives/torus.test.js +4 -4
- package/src/geometries/geom2/fromCompactBinary.d.ts +0 -3
- package/src/geometries/geom2/fromCompactBinary.js +0 -40
- package/src/geometries/geom2/fromToCompactBinary.test.js +0 -100
- package/src/geometries/geom2/toCompactBinary.d.ts +0 -3
- package/src/geometries/geom2/toCompactBinary.js +0 -56
- package/src/geometries/geom3/fromCompactBinary.d.ts +0 -3
- package/src/geometries/geom3/fromCompactBinary.js +0 -42
- package/src/geometries/geom3/fromPointsConvex.js +0 -25
- package/src/geometries/geom3/fromToCompactBinary.test.js +0 -139
- package/src/geometries/geom3/toCompactBinary.d.ts +0 -3
- package/src/geometries/geom3/toCompactBinary.js +0 -66
- package/src/geometries/path2/fromCompactBinary.d.ts +0 -3
- package/src/geometries/path2/fromCompactBinary.js +0 -31
- package/src/geometries/path2/fromToCompactBinary.test.js +0 -114
- package/src/geometries/path2/toCompactBinary.d.ts +0 -3
- package/src/geometries/path2/toCompactBinary.js +0 -50
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/modeling",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3-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",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"rollup": "^2.79.1",
|
|
65
65
|
"rollup-plugin-banner": "^0.2.1"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "b0a83db054ec02ccddd9e19e51f86bf30f72a69e"
|
|
68
68
|
}
|
|
@@ -36,7 +36,7 @@ test('color (rgba on objects)', (t) => {
|
|
|
36
36
|
|
|
37
37
|
test('color (rgba on geometry)', (t) => {
|
|
38
38
|
const obj0 = geom2.create([[[0, 0], [1, 0], [0, 1]]])
|
|
39
|
-
const obj1 = geom3.
|
|
39
|
+
const obj1 = geom3.fromVertices([[[0, 0, 0], [1, 0, 0], [1, 0, 1]]])
|
|
40
40
|
const obj2 = path2.fromPoints({ closed: true }, [[0, 0], [1, 0], [1, 1]])
|
|
41
41
|
const obj3 = poly3.create([[0, 0, 0], [1, 0, 0], [1, 1, 0]])
|
|
42
42
|
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
export { clone } from './clone.js'
|
|
2
2
|
export { create } from './create.js'
|
|
3
3
|
export { fromSides } from './fromSides.js'
|
|
4
|
-
export { fromCompactBinary } from './fromCompactBinary.js'
|
|
5
4
|
export { isA } from './isA.js'
|
|
6
5
|
export { reverse } from './reverse.js'
|
|
7
6
|
export { toOutlines } from './toOutlines.js'
|
|
8
7
|
export { toPoints } from './toPoints.js'
|
|
9
8
|
export { toSides } from './toSides.js'
|
|
10
9
|
export { toString } from './toString.js'
|
|
11
|
-
export { toCompactBinary } from './toCompactBinary.js'
|
|
12
10
|
export { transform } from './transform.js'
|
|
13
11
|
export { validate } from './validate.js'
|
|
14
12
|
|
|
@@ -11,13 +11,11 @@
|
|
|
11
11
|
export { clone } from './clone.js'
|
|
12
12
|
export { create } from './create.js'
|
|
13
13
|
export { fromSides } from './fromSides.js'
|
|
14
|
-
export { fromCompactBinary } from './fromCompactBinary.js'
|
|
15
14
|
export { isA } from './isA.js'
|
|
16
15
|
export { reverse } from './reverse.js'
|
|
17
16
|
export { toOutlines } from './toOutlines.js'
|
|
18
17
|
export { toPoints } from './toPoints.js'
|
|
19
18
|
export { toSides } from './toSides.js'
|
|
20
19
|
export { toString } from './toString.js'
|
|
21
|
-
export { toCompactBinary } from './toCompactBinary.js'
|
|
22
20
|
export { transform } from './transform.js'
|
|
23
21
|
export { validate } from './validate.js'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { fromVertices } from './index.js'
|
|
4
4
|
|
|
5
5
|
import { applyTransforms } from './applyTransforms.js'
|
|
6
6
|
|
|
@@ -15,7 +15,7 @@ test('applyTransforms: Updates a geom3 with transformed polygons', (t) => {
|
|
|
15
15
|
isRetesselated: false,
|
|
16
16
|
transforms: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
17
17
|
}
|
|
18
|
-
const geometry =
|
|
18
|
+
const geometry = fromVertices(vertices)
|
|
19
19
|
const updated = applyTransforms(geometry)
|
|
20
20
|
t.is(geometry, updated)
|
|
21
21
|
t.true(comparePolygons(updated.polygons[0], expected.polygons[0]))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import { clone, create,
|
|
3
|
+
import { clone, create, fromVertices } from './index.js'
|
|
4
4
|
|
|
5
5
|
import { comparePolygons, compareVectors } from '../../../test/helpers/index.js'
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ test('clone: Creates a clone of a populated geom3', (t) => {
|
|
|
23
23
|
],
|
|
24
24
|
transforms: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
25
25
|
}
|
|
26
|
-
const geometry =
|
|
26
|
+
const geometry = fromVertices(vertices)
|
|
27
27
|
const another = clone(geometry)
|
|
28
28
|
t.not(another, geometry)
|
|
29
29
|
t.true(comparePolygons(another.polygons[0], expected.polygons[0]))
|
|
@@ -24,12 +24,4 @@ import * as mat4 from '../../maths/mat4/index.js'
|
|
|
24
24
|
* @returns {Geom3} a new geometry
|
|
25
25
|
* @alias module:modeling/geometries/geom3.create
|
|
26
26
|
*/
|
|
27
|
-
export const create = (polygons) => {
|
|
28
|
-
if (polygons === undefined) {
|
|
29
|
-
polygons = [] // empty contents
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
polygons,
|
|
33
|
-
transforms: mat4.create()
|
|
34
|
-
}
|
|
35
|
-
}
|
|
27
|
+
export const create = (polygons = []) => ({ polygons, transforms: mat4.create() })
|
|
@@ -4,14 +4,15 @@ import { create } from './create.js'
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Construct a new 3D geometry from a list of vertices.
|
|
7
|
+
*
|
|
7
8
|
* The list of vertices should contain sub-arrays, each defining a single polygon of vertices.
|
|
8
9
|
* In addition, the vertices should follow the right-hand rule for rotation in order to
|
|
9
10
|
* define an external facing polygon.
|
|
10
11
|
* @param {Array} listOfLists - list of lists, where each list is a set of vertices to construct a polygon
|
|
11
12
|
* @returns {Geom3} a new geometry
|
|
12
|
-
* @alias module:modeling/geometries/geom3.
|
|
13
|
+
* @alias module:modeling/geometries/geom3.fromVertices
|
|
13
14
|
*/
|
|
14
|
-
export const
|
|
15
|
+
export const fromVertices = (listOfLists) => {
|
|
15
16
|
if (!Array.isArray(listOfLists)) {
|
|
16
17
|
throw new Error('the given vertices must be an array')
|
|
17
18
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { fromVertices } from './index.js'
|
|
4
4
|
|
|
5
5
|
import { comparePolygons, compareVectors } from '../../../test/helpers/index.js'
|
|
6
6
|
|
|
7
|
-
test('
|
|
7
|
+
test('fromVertices: Creates a populated geom3', (t) => {
|
|
8
8
|
const vertices = [[[0, 0, 0], [1, 0, 0], [1, 0, 1]]]
|
|
9
9
|
const expected = {
|
|
10
10
|
polygons: [
|
|
@@ -13,12 +13,12 @@ test('fromPoints: Creates a populated geom3', (t) => {
|
|
|
13
13
|
isRetesselated: false,
|
|
14
14
|
transforms: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
15
15
|
}
|
|
16
|
-
const obs =
|
|
16
|
+
const obs = fromVertices(vertices)
|
|
17
17
|
t.true(comparePolygons(obs.polygons[0], expected.polygons[0]))
|
|
18
18
|
t.true(compareVectors(obs.transforms, expected.transforms))
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
test('
|
|
22
|
-
t.throws(() =>
|
|
23
|
-
t.throws(() =>
|
|
21
|
+
test('fromVertices: throws for improper vertices', (t) => {
|
|
22
|
+
t.throws(() => fromVertices(), { instanceOf: Error })
|
|
23
|
+
t.throws(() => fromVertices(0, 0, 0), { instanceOf: Error })
|
|
24
24
|
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { runner } from '../../operations/hulls/quickhull/index.js'
|
|
2
|
+
import { create } from './create.js'
|
|
3
|
+
import * as poly3 from '../poly3/index.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Construct a new convex 3D geometry from a list of unique vertices.
|
|
7
|
+
*
|
|
8
|
+
* @param {Array} uniqueVertices - list of vertices to construct convex 3D geometry
|
|
9
|
+
* @returns {geom3} a new geometry
|
|
10
|
+
* @alias module:modeling/geometries/geom3.fromVerticesConvex
|
|
11
|
+
*/
|
|
12
|
+
export const fromVerticesConvex = (uniqueVertices) => {
|
|
13
|
+
if (!Array.isArray(uniqueVertices)) {
|
|
14
|
+
throw new Error('the given vertices must be an array')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const faces = runner(uniqueVertices, { skipTriangulation: true })
|
|
18
|
+
|
|
19
|
+
const polygons = faces.map((face) => {
|
|
20
|
+
const vertices = face.map((index) => uniqueVertices[index])
|
|
21
|
+
return poly3.create(vertices)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
return create(polygons)
|
|
25
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { fromVerticesConvex, validate } from './index.js'
|
|
4
4
|
|
|
5
|
-
test('
|
|
5
|
+
test('fromVerticesConvex (uniqueVertices)', (t) => {
|
|
6
6
|
const out = []
|
|
7
7
|
for (let x = -9; x <= 9; ++x) {
|
|
8
8
|
for (let y = -9; y <= 9; ++y) {
|
|
@@ -14,7 +14,7 @@ test('fromPointsConvex (uniquePoints)', (t) => {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const obs =
|
|
17
|
+
const obs = fromVerticesConvex(out)
|
|
18
18
|
validate(obs)
|
|
19
19
|
t.is(obs.polygons.length, 170)
|
|
20
20
|
t.true(obs.polygons.every((f) => ([3, 4, 8, 9].indexOf(f.vertices.length) !== -1)))
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
export { clone } from './clone.js'
|
|
2
2
|
export { create } from './create.js'
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export { fromCompactBinary } from './fromCompactBinary.js'
|
|
3
|
+
export { fromVertices } from './fromVertices.js'
|
|
4
|
+
export { fromVerticesConvex } from './fromVerticesConvex.js'
|
|
6
5
|
export { invert } from './invert.js'
|
|
7
6
|
export { isA } from './isA.js'
|
|
8
|
-
export { toPoints } from './toPoints.js'
|
|
9
7
|
export { toPolygons } from './toPolygons.js'
|
|
10
8
|
export { toString } from './toString.js'
|
|
11
|
-
export {
|
|
9
|
+
export { toVertices } from './toVertices.js'
|
|
12
10
|
export { transform } from './transform.js'
|
|
13
11
|
export { validate } from './validate.js'
|
|
14
12
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* import { geometries } from '@jscad/modeling'
|
|
8
|
-
* const myShape = geometries.geom3.
|
|
8
|
+
* const myShape = geometries.geom3.fromVertices([
|
|
9
9
|
* [[-1,-1,-1], [-1,-1,1], [-1,1,1], [-1,1,-1]],
|
|
10
10
|
* [[1,-1,-1], [1,1,-1], [1,1,1], [1,-1,1]],
|
|
11
11
|
* [[-1,-1,-1], [1,-1,-1], [1,-1,1], [-1,-1,1]]
|
|
@@ -16,14 +16,12 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { clone } from './clone.js'
|
|
18
18
|
export { create } from './create.js'
|
|
19
|
-
export {
|
|
20
|
-
export {
|
|
21
|
-
export { fromCompactBinary } from './fromCompactBinary.js'
|
|
19
|
+
export { fromVertices } from './fromVertices.js'
|
|
20
|
+
export { fromVerticesConvex } from './fromVerticesConvex.js'
|
|
22
21
|
export { invert } from './invert.js'
|
|
23
22
|
export { isA } from './isA.js'
|
|
24
|
-
export { toPoints } from './toPoints.js'
|
|
25
23
|
export { toPolygons } from './toPolygons.js'
|
|
26
24
|
export { toString } from './toString.js'
|
|
27
|
-
export {
|
|
25
|
+
export { toVertices } from './toVertices.js'
|
|
28
26
|
export { transform } from './transform.js'
|
|
29
27
|
export { validate } from './validate.js'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import { invert, create,
|
|
3
|
+
import { invert, create, fromVertices } from './index.js'
|
|
4
4
|
|
|
5
5
|
import { comparePolygons, compareVectors } from '../../../test/helpers/index.js'
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ test('invert: Creates a invert of a populated geom3', (t) => {
|
|
|
23
23
|
],
|
|
24
24
|
transforms: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
25
25
|
}
|
|
26
|
-
const geometry =
|
|
26
|
+
const geometry = fromVertices(vertices)
|
|
27
27
|
const another = invert(geometry)
|
|
28
28
|
t.not(another, geometry)
|
|
29
29
|
t.true(comparePolygons(another.polygons[0], expected.polygons[0]))
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import { isA, create,
|
|
3
|
+
import { isA, create, fromVertices } from './index.js'
|
|
4
4
|
|
|
5
5
|
test('isA: identifies created geom3', (t) => {
|
|
6
6
|
const p1 = create()
|
|
7
|
-
const p2 =
|
|
7
|
+
const p2 = fromVertices([[[0, 0, 0], [1, 0, 0], [1, 0, 1]]])
|
|
8
8
|
t.true(isA(p1))
|
|
9
9
|
t.true(isA(p2))
|
|
10
10
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import { create,
|
|
3
|
+
import { create, fromVertices, toString } from './index.js'
|
|
4
4
|
|
|
5
5
|
test('toString: serialize empty geom3 into a string', (t) => {
|
|
6
6
|
const geometry = create()
|
|
@@ -10,7 +10,7 @@ test('toString: serialize empty geom3 into a string', (t) => {
|
|
|
10
10
|
})
|
|
11
11
|
|
|
12
12
|
test('toString: serialize geom3 into a string', (t) => {
|
|
13
|
-
const geometry =
|
|
13
|
+
const geometry = fromVertices([[[0, 0, 3], [0, 1, 3], [2, 0, 3]]])
|
|
14
14
|
const result = toString(geometry)
|
|
15
15
|
const expected = 'geom3 (1 polygons):\n poly3: [[0.0000000, 0.0000000, 3.0000000], [0.0000000, 1.0000000, 3.0000000], [2.0000000, 0.0000000, 3.0000000]]\n'
|
|
16
16
|
t.is(result, expected)
|
|
@@ -4,12 +4,13 @@ import { toPolygons } from './toPolygons.js'
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Return the given geometry as a list of points, after applying transforms.
|
|
7
|
+
*
|
|
7
8
|
* The returned array should not be modified as the points are shared with the geometry.
|
|
8
9
|
* @param {Geom3} geometry - the geometry
|
|
9
10
|
* @return {Array} list of points, where each sub-array represents a polygon
|
|
10
|
-
* @alias module:modeling/geometries/geom3.
|
|
11
|
+
* @alias module:modeling/geometries/geom3.toVertices
|
|
11
12
|
*/
|
|
12
|
-
export const
|
|
13
|
+
export const toVertices = (geometry) => {
|
|
13
14
|
const polygons = toPolygons(geometry)
|
|
14
15
|
return polygons.map((polygon) => poly3.toVertices(polygon))
|
|
15
16
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { toVertices, fromVertices, toString } from './index.js'
|
|
4
4
|
|
|
5
5
|
import { comparePolygonsAsPoints } from '../../../test/helpers/index.js'
|
|
6
6
|
|
|
7
|
-
test('
|
|
7
|
+
test('toVertices: Creates an array of vertices from a populated geom3', (t) => {
|
|
8
8
|
const vertices = [[[0, 0, 0], [1, 0, 0], [1, 0, 1]]]
|
|
9
|
-
const geometry =
|
|
9
|
+
const geometry = fromVertices(vertices)
|
|
10
10
|
|
|
11
11
|
toString(geometry)
|
|
12
12
|
|
|
13
13
|
const expected = [[[0, 0, 0], [1, 0, 0], [1, 0, 1]]]
|
|
14
|
-
const vertexList =
|
|
14
|
+
const vertexList = toVertices(geometry)
|
|
15
15
|
t.deepEqual(vertexList, expected)
|
|
16
16
|
t.true(comparePolygonsAsPoints(vertexList, expected))
|
|
17
17
|
|
|
@@ -2,7 +2,7 @@ import test from 'ava'
|
|
|
2
2
|
|
|
3
3
|
import { mat4 } from '../../maths/index.js'
|
|
4
4
|
|
|
5
|
-
import { transform,
|
|
5
|
+
import { transform, fromVertices, toPolygons } from './index.js'
|
|
6
6
|
|
|
7
7
|
import { comparePolygons, compareVectors } from '../../../test/helpers/index.js'
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ test('transform: Adjusts the transforms of a populated geom3', (t) => {
|
|
|
20
20
|
],
|
|
21
21
|
transforms: [0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
22
22
|
}
|
|
23
|
-
const geometry =
|
|
23
|
+
const geometry = fromVertices(vertices)
|
|
24
24
|
let another = transform(rotate90, geometry)
|
|
25
25
|
t.not(geometry, another)
|
|
26
26
|
t.true(comparePolygons(another.polygons[0], expected.polygons[0]))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
3
|
import * as vec3 from '../../maths/vec3/index.js'
|
|
4
|
-
import {
|
|
4
|
+
import { fromVertices, validate } from './index.js'
|
|
5
5
|
|
|
6
6
|
// tetrahedron
|
|
7
7
|
const a = vec3.fromValues(-1, -1, 1)
|
|
@@ -11,16 +11,16 @@ const d = vec3.fromValues(1, 1, 1)
|
|
|
11
11
|
|
|
12
12
|
test('validate: allow valid geom3', (t) => {
|
|
13
13
|
// simplest valid geometry
|
|
14
|
-
const geometry =
|
|
14
|
+
const geometry = fromVertices([[a, b, c], [d, b, a], [d, a, c], [c, b, d]])
|
|
15
15
|
t.notThrows(() => validate(geometry))
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
test('validate: throw exception for nan', (t) => {
|
|
19
|
-
const geometry =
|
|
19
|
+
const geometry = fromVertices([[a, b, c], [d, b, a], [d, a, c], [c, b, [1, 1, NaN]]])
|
|
20
20
|
t.throws(() => validate(geometry))
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
test('validate: throw exception for infinity', (t) => {
|
|
24
|
-
const geometry =
|
|
24
|
+
const geometry = fromVertices([[a, b, c], [d, b, a], [d, a, c], [c, b, [1, 1, Infinity]]])
|
|
25
25
|
t.throws(() => validate(geometry))
|
|
26
26
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * as geom2 from './geom2/index.js'
|
|
2
2
|
export * as geom3 from './geom3/index.js'
|
|
3
3
|
export * as path2 from './path2/index.js'
|
|
4
|
+
export * as path3 from './path3/index.js'
|
|
4
5
|
export * as poly2 from './poly2/index.js'
|
|
5
6
|
export * as poly3 from './poly3/index.js'
|
|
6
7
|
export * as slice from './slice/index.js'
|
package/src/geometries/index.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
export * as geom2 from './geom2/index.js'
|
|
17
17
|
export * as geom3 from './geom3/index.js'
|
|
18
18
|
export * as path2 from './path2/index.js'
|
|
19
|
+
export * as path3 from './path3/index.js'
|
|
19
20
|
export * as poly2 from './poly2/index.js'
|
|
20
21
|
export * as poly3 from './poly3/index.js'
|
|
21
22
|
export * as slice from './slice/index.js'
|
|
@@ -21,13 +21,4 @@ import * as mat4 from '../../maths/mat4/index.js'
|
|
|
21
21
|
* @example
|
|
22
22
|
* let newPath = create()
|
|
23
23
|
*/
|
|
24
|
-
export const create = (points) => {
|
|
25
|
-
if (points === undefined) {
|
|
26
|
-
points = []
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
points: points,
|
|
30
|
-
isClosed: false,
|
|
31
|
-
transforms: mat4.create()
|
|
32
|
-
}
|
|
33
|
-
}
|
|
24
|
+
export const create = (points = []) => ({ points: points, isClosed: false, transforms: mat4.create() })
|
|
@@ -7,12 +7,10 @@ export { concat } from './concat.js'
|
|
|
7
7
|
export { create } from './create.js'
|
|
8
8
|
export { equals } from './equals.js'
|
|
9
9
|
export { fromPoints, FromPointsOptions } from './fromPoints.js'
|
|
10
|
-
export { fromCompactBinary } from './fromCompactBinary.js'
|
|
11
10
|
export { isA } from './isA.js'
|
|
12
11
|
export { reverse } from './reverse.js'
|
|
13
12
|
export { toPoints } from './toPoints.js'
|
|
14
13
|
export { toString } from './toString.js'
|
|
15
|
-
export { toCompactBinary } from './toCompactBinary.js'
|
|
16
14
|
export { transform } from './transform.js'
|
|
17
15
|
export { validate } from './validate.js'
|
|
18
16
|
|
|
@@ -16,11 +16,9 @@ export { concat } from './concat.js'
|
|
|
16
16
|
export { create } from './create.js'
|
|
17
17
|
export { equals } from './equals.js'
|
|
18
18
|
export { fromPoints } from './fromPoints.js'
|
|
19
|
-
export { fromCompactBinary } from './fromCompactBinary.js'
|
|
20
19
|
export { isA } from './isA.js'
|
|
21
20
|
export { reverse } from './reverse.js'
|
|
22
21
|
export { toPoints } from './toPoints.js'
|
|
23
22
|
export { toString } from './toString.js'
|
|
24
|
-
export { toCompactBinary } from './toCompactBinary.js'
|
|
25
23
|
export { transform } from './transform.js'
|
|
26
24
|
export { validate } from './validate.js'
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as mat4 from '../../maths/mat4/index.js'
|
|
2
|
+
import * as vec3 from '../../maths/vec3/index.js'
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Apply the transforms of the given geometry.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This function must be called BEFORE exposing any data. See toVertices.
|
|
8
|
+
*
|
|
9
|
+
* @param {Path3} geometry - the geometry to transform
|
|
10
|
+
* @returns {Path3} the given geometry
|
|
11
|
+
* @function
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* geometry = applyTransforms(geometry)
|
|
15
|
+
*/
|
|
16
|
+
export const applyTransforms = (geometry) => {
|
|
17
|
+
if (mat4.isIdentity(geometry.transforms)) return geometry
|
|
18
|
+
|
|
19
|
+
geometry.vertices = geometry.vertices.map((vertex) => vec3.transform(vec3.create(), vertex, geometry.transforms))
|
|
20
|
+
geometry.transforms = mat4.create()
|
|
21
|
+
return geometry
|
|
22
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import test from 'ava'
|
|
2
|
+
|
|
3
|
+
import { fromVertices } from './index.js'
|
|
4
|
+
|
|
5
|
+
import { applyTransforms } from './applyTransforms.js'
|
|
6
|
+
|
|
7
|
+
import { comparePoints, compareVectors } from '../../../test/helpers/index.js'
|
|
8
|
+
|
|
9
|
+
test('applyTransforms: Updates a populated path with transformed points', (t) => {
|
|
10
|
+
const vertices = [[0, 0, 0], [1, 0, 0], [0, 1, 0]]
|
|
11
|
+
const expected = {
|
|
12
|
+
vertices: [[0, 0, 0], [1, 0, 0], [0, 1, 0]],
|
|
13
|
+
isClosed: false,
|
|
14
|
+
transforms: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
|
15
|
+
}
|
|
16
|
+
const geometry = fromVertices({}, vertices)
|
|
17
|
+
const updated = applyTransforms(geometry)
|
|
18
|
+
t.is(geometry, updated)
|
|
19
|
+
t.true(comparePoints(updated.vertices, expected.vertices))
|
|
20
|
+
t.false(updated.isClosed)
|
|
21
|
+
t.true(compareVectors(updated.transforms, expected.transforms))
|
|
22
|
+
|
|
23
|
+
const updated2 = applyTransforms(updated)
|
|
24
|
+
t.is(updated, updated2)
|
|
25
|
+
t.true(comparePoints(updated2.vertices, expected.vertices))
|
|
26
|
+
t.false(updated2.isClosed)
|
|
27
|
+
t.true(compareVectors(updated2.transforms, expected.transforms))
|
|
28
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { EPS } from '../../maths/constants.js'
|
|
2
|
+
|
|
3
|
+
import * as vec3 from '../../maths/vec3/index.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Close the given geometry.
|
|
7
|
+
*
|
|
8
|
+
* @param {Path3} geometry - the path to close
|
|
9
|
+
* @returns {Path3} a new path
|
|
10
|
+
* @function
|
|
11
|
+
* @alias module:modeling/geometries/path3.close
|
|
12
|
+
*/
|
|
13
|
+
export const close = (geometry) => {
|
|
14
|
+
if (geometry.isClosed) return geometry
|
|
15
|
+
|
|
16
|
+
const cloned = Object.assign({}, geometry)
|
|
17
|
+
cloned.isClosed = true
|
|
18
|
+
|
|
19
|
+
if (cloned.vertices.length > 1) {
|
|
20
|
+
// make sure the paths are formed properly
|
|
21
|
+
const vertices = cloned.vertices
|
|
22
|
+
const p0 = vertices[0]
|
|
23
|
+
let pn = vertices[vertices.length - 1]
|
|
24
|
+
while (vec3.distance(p0, pn) < (EPS * EPS)) {
|
|
25
|
+
vertices.pop()
|
|
26
|
+
if (vertices.length === 1) break
|
|
27
|
+
pn = vertices[vertices.length - 1]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return cloned
|
|
31
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import test from 'ava'
|
|
2
|
+
|
|
3
|
+
import { close, create, fromVertices } from './index.js'
|
|
4
|
+
|
|
5
|
+
test('close: closes an empty path', (t) => {
|
|
6
|
+
const p1 = create()
|
|
7
|
+
t.false(p1.isClosed)
|
|
8
|
+
|
|
9
|
+
const p2 = close(p1)
|
|
10
|
+
t.true(p2.isClosed)
|
|
11
|
+
t.not(p1, p2)
|
|
12
|
+
|
|
13
|
+
const p3 = close(p2)
|
|
14
|
+
t.true(p3.isClosed)
|
|
15
|
+
t.is(p2, p3)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('close: closes various paths', (t) => {
|
|
19
|
+
let p1 = create()
|
|
20
|
+
p1 = close(p1)
|
|
21
|
+
t.true(p1.isClosed)
|
|
22
|
+
t.is(0, p1.vertices.length)
|
|
23
|
+
|
|
24
|
+
let p2 = fromVertices({ closed: false }, [])
|
|
25
|
+
p2 = close(p2)
|
|
26
|
+
t.true(p2.isClosed)
|
|
27
|
+
t.is(0, p2.vertices.length)
|
|
28
|
+
|
|
29
|
+
let p3 = fromVertices({ closed: true }, [[0, 0, 0]])
|
|
30
|
+
p3 = close(p3)
|
|
31
|
+
t.true(p3.isClosed)
|
|
32
|
+
t.is(1, p3.vertices.length)
|
|
33
|
+
|
|
34
|
+
let p4 = fromVertices({ closed: true }, [[0, 0, 0], [0, 0, 0]])
|
|
35
|
+
p4 = close(p4)
|
|
36
|
+
t.true(p4.isClosed)
|
|
37
|
+
t.is(1, p4.vertices.length) // the last point is removed
|
|
38
|
+
|
|
39
|
+
let p5 = fromVertices({ closed: true }, [[0, 0, 0], [1, 1, 0], [0, 0, 0]])
|
|
40
|
+
p5 = close(p5)
|
|
41
|
+
t.true(p5.isClosed)
|
|
42
|
+
t.is(2, p5.vertices.length) // the last point is removed
|
|
43
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { equals } from '../../maths/vec3/index.js'
|
|
2
|
+
|
|
3
|
+
import { fromVertices } from './fromVertices.js'
|
|
4
|
+
import { toVertices } from './toVertices.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Concatenate the given paths.
|
|
8
|
+
*
|
|
9
|
+
* If both contain the same vertex at the junction, merge it into one.
|
|
10
|
+
* A concatenation of zero paths is an empty, open path.
|
|
11
|
+
* A concatenation of one closed path to a series of open paths produces a closed path.
|
|
12
|
+
* A concatenation of a path to a closed path is an error.
|
|
13
|
+
*
|
|
14
|
+
* @param {...Path3} paths - the paths to concatenate
|
|
15
|
+
* @returns {Path3} a new path
|
|
16
|
+
* @function
|
|
17
|
+
* @alias module:modeling/geometries/path3.concat
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* let newPath = concat(fromVertices({}, [[1, 2, 3]]), fromVertices({}, [[4, 5, 6]]))
|
|
21
|
+
*/
|
|
22
|
+
export const concat = (...paths) => {
|
|
23
|
+
// Only the last path can be closed, producing a closed path.
|
|
24
|
+
let isClosed = false
|
|
25
|
+
let vertices = []
|
|
26
|
+
paths.forEach((path, i) => {
|
|
27
|
+
const tmp = toVertices(path).slice()
|
|
28
|
+
if (vertices.length > 0 && tmp.length > 0 && equals(tmp[0], vertices[vertices.length - 1])) tmp.shift()
|
|
29
|
+
if (tmp.length > 0 && isClosed) {
|
|
30
|
+
throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`)
|
|
31
|
+
}
|
|
32
|
+
isClosed = path.isClosed
|
|
33
|
+
vertices = vertices.concat(tmp)
|
|
34
|
+
})
|
|
35
|
+
return fromVertices({ closed: isClosed }, vertices)
|
|
36
|
+
}
|