@jscad/modeling 2.12.1 → 2.12.3
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 +29 -0
- package/dist/jscad-modeling.min.js +393 -387
- package/package.json +2 -2
- package/src/geometries/geom3/fromPointsConvex.d.ts +6 -0
- package/src/geometries/geom3/fromPointsConvex.js +26 -0
- package/src/geometries/geom3/fromPointsConvex.test.js +26 -0
- package/src/geometries/geom3/index.d.ts +1 -0
- package/src/geometries/geom3/index.js +1 -0
- package/src/geometries/poly3/type.d.ts +2 -0
- package/src/maths/mat4/index.d.ts +1 -0
- package/src/maths/mat4/isIdentity.d.ts +5 -0
- package/src/operations/booleans/index.d.ts +1 -0
- package/src/operations/booleans/scission.d.ts +6 -0
- package/src/operations/booleans/trees/splitPolygonByPlane.d.ts +33 -0
- package/src/operations/hulls/hull.test.js +9 -1
- package/src/operations/hulls/hullGeom2.js +3 -0
- package/src/operations/hulls/hullGeom3.js +7 -12
- package/src/operations/hulls/hullPath2.js +4 -1
- package/src/operations/hulls/hullPoints2.d.ts +5 -0
- package/src/operations/hulls/hullPoints2.js +4 -2
- package/src/operations/hulls/hullPoints3.d.ts +6 -0
- package/src/operations/hulls/hullPoints3.js +23 -0
- package/src/operations/hulls/index.d.ts +2 -0
- package/src/operations/hulls/index.js +3 -1
- package/src/primitives/roundedCuboid.js +1 -1
- package/src/primitives/roundedCylinder.js +1 -1
- package/src/primitives/roundedRectangle.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/modeling",
|
|
3
|
-
"version": "2.12.
|
|
3
|
+
"version": "2.12.3",
|
|
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",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"nyc": "15.1.0",
|
|
62
62
|
"uglifyify": "5.0.2"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "4627312c2337120447a607ff3ac3da10056ce132"
|
|
65
65
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const quickhull = require('../../operations/hulls/quickhull')
|
|
2
|
+
const create = require('./create')
|
|
3
|
+
const poly3 = require('../poly3')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Construct a new convex 3D geometry from a list of unique points.
|
|
7
|
+
* @param {Array} uniquePoints - list of points to construct convex 3D geometry
|
|
8
|
+
* @returns {geom3} a new geometry
|
|
9
|
+
* @alias module:modeling/geometries/geom3.fromPointsConvex
|
|
10
|
+
*/
|
|
11
|
+
const fromPointsConvex = (uniquePoints) => {
|
|
12
|
+
if (!Array.isArray(uniquePoints)) {
|
|
13
|
+
throw new Error('the given points must be an array')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const faces = quickhull(uniquePoints, { skipTriangulation: true })
|
|
17
|
+
|
|
18
|
+
const polygons = faces.map((face) => {
|
|
19
|
+
const vertices = face.map((index) => uniquePoints[index])
|
|
20
|
+
return poly3.create(vertices)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return create(polygons)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = fromPointsConvex
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { fromPointsConvex, validate } = require('./index')
|
|
4
|
+
|
|
5
|
+
test('fromPointsConvex (uniquePoints)', (t) => {
|
|
6
|
+
let out = []
|
|
7
|
+
for(x=-9;x<=9;++x)
|
|
8
|
+
for(y=-9;y<=9;++y)
|
|
9
|
+
for(z=-9;z<=9;++z)
|
|
10
|
+
if (x*x+y*y+z*z <= 96)
|
|
11
|
+
out.push([x,y,z])
|
|
12
|
+
|
|
13
|
+
let obs = fromPointsConvex(out)
|
|
14
|
+
validate(obs)
|
|
15
|
+
t.is(obs.polygons.length, 170)
|
|
16
|
+
t.true(obs.polygons.every((f) => ([3,4,8,9].indexOf(f.vertices.length) !== -1)))
|
|
17
|
+
let c = [0,0,0,0,0,0,0,0,0,0]
|
|
18
|
+
obs.polygons.forEach((f) => c[f.vertices.length]++)
|
|
19
|
+
t.is(c[3], 120);
|
|
20
|
+
t.is(c[4], 24);
|
|
21
|
+
t.is(c[8], 18);
|
|
22
|
+
t.is(c[9], 8);
|
|
23
|
+
let edges2 = 336*2
|
|
24
|
+
obs.polygons.forEach((f) => edges2 -= f.vertices.length)
|
|
25
|
+
t.is(edges2, 0);
|
|
26
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as clone } from './clone'
|
|
2
2
|
export { default as create } from './create'
|
|
3
|
+
export { default as fromPointsConvex } from './fromPointsConvex'
|
|
3
4
|
export { default as fromPoints } from './fromPoints'
|
|
4
5
|
export { default as fromCompactBinary } from './fromCompactBinary'
|
|
5
6
|
export { default as invert } from './invert'
|
|
@@ -12,6 +12,7 @@ export { default as fromXRotation } from './fromXRotation'
|
|
|
12
12
|
export { default as fromYRotation } from './fromYRotation'
|
|
13
13
|
export { default as fromZRotation } from './fromZRotation'
|
|
14
14
|
export { default as identity } from './identity'
|
|
15
|
+
export { default as isIdentity } from './isIdentity'
|
|
15
16
|
export { default as isMirroring } from './isMirroring'
|
|
16
17
|
export { default as mirrorByPlane } from './mirrorByPlane'
|
|
17
18
|
export { default as multiply } from './multiply'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Poly3 } from '../../../geometries/types';
|
|
2
|
+
import { Plane } from '../../../maths/types';
|
|
3
|
+
|
|
4
|
+
enum ResType
|
|
5
|
+
{
|
|
6
|
+
coplanar_front = 0,
|
|
7
|
+
coplanar_back = 1,
|
|
8
|
+
front = 2,
|
|
9
|
+
back = 3,
|
|
10
|
+
spanning = 4,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
interface SplitRes
|
|
15
|
+
{
|
|
16
|
+
type: ResType,
|
|
17
|
+
front: Poly3,
|
|
18
|
+
back: Poly3;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Returns object:
|
|
22
|
+
// .type:
|
|
23
|
+
// 0: coplanar-front
|
|
24
|
+
// 1: coplanar-back
|
|
25
|
+
// 2: front
|
|
26
|
+
// 3: back
|
|
27
|
+
// 4: spanning
|
|
28
|
+
// In case the polygon is spanning, returns:
|
|
29
|
+
// .front: a Polygon3 of the front part
|
|
30
|
+
// .back: a Polygon3 of the back part
|
|
31
|
+
declare function splitPolygonByPlane(plane: Plane, polygon: Poly3): SplitRes;
|
|
32
|
+
|
|
33
|
+
export default splitPolygonByPlane;
|
|
@@ -2,7 +2,9 @@ const test = require('ava')
|
|
|
2
2
|
|
|
3
3
|
const { geom2, geom3, path2 } = require('../../geometries')
|
|
4
4
|
|
|
5
|
-
const {
|
|
5
|
+
const { measureVolume } = require('../../measurements')
|
|
6
|
+
|
|
7
|
+
const { sphere, cuboid, ellipsoid, torus } = require('../../primitives')
|
|
6
8
|
|
|
7
9
|
const { center } = require('../transforms/center')
|
|
8
10
|
|
|
@@ -274,3 +276,9 @@ test('hull (multiple, overlapping, geom3)', (t) => {
|
|
|
274
276
|
t.notThrows(() => geom3.validate(obs))
|
|
275
277
|
t.is(pts.length, 92)
|
|
276
278
|
})
|
|
279
|
+
|
|
280
|
+
test('hull (single, unconvex, geom3)', (t) => {
|
|
281
|
+
const geometry = torus()
|
|
282
|
+
const obs = hull(geometry)
|
|
283
|
+
t.assert(measureVolume(obs) > measureVolume(geometry))
|
|
284
|
+
})
|
|
@@ -7,6 +7,9 @@ const toUniquePoints = require('./toUniquePoints')
|
|
|
7
7
|
|
|
8
8
|
/*
|
|
9
9
|
* Create a convex hull of the given geom2 geometries.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: The given geometries must be valid geom2 geometries.
|
|
12
|
+
*
|
|
10
13
|
* @param {...geometries} geometries - list of geom2 geometries
|
|
11
14
|
* @returns {geom2} new geometry
|
|
12
15
|
*/
|
|
@@ -1,32 +1,27 @@
|
|
|
1
1
|
const flatten = require('../../utils/flatten')
|
|
2
2
|
|
|
3
3
|
const geom3 = require('../../geometries/geom3')
|
|
4
|
-
const poly3 = require('../../geometries/poly3')
|
|
5
4
|
|
|
6
|
-
const quickhull = require('./quickhull')
|
|
7
5
|
const toUniquePoints = require('./toUniquePoints')
|
|
6
|
+
const hullPoints3 = require('./hullPoints3')
|
|
8
7
|
|
|
9
8
|
/*
|
|
10
|
-
* Create a convex hull of the given geometries
|
|
9
|
+
* Create a convex hull of the given geom3 geometries.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: The given geometries must be valid geom3 geometries.
|
|
12
|
+
*
|
|
11
13
|
* @param {...geometries} geometries - list of geom3 geometries
|
|
12
14
|
* @returns {geom3} new geometry
|
|
13
15
|
*/
|
|
14
16
|
const hullGeom3 = (...geometries) => {
|
|
15
17
|
geometries = flatten(geometries)
|
|
16
18
|
|
|
17
|
-
if (geometries.length === 1) return geometries[0]
|
|
18
|
-
|
|
19
19
|
// extract the unique vertices from the geometries
|
|
20
20
|
const unique = toUniquePoints(geometries)
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const polygons = faces.map((face) => {
|
|
25
|
-
const vertices = face.map((index) => unique[index])
|
|
26
|
-
return poly3.create(vertices)
|
|
27
|
-
})
|
|
22
|
+
if (unique.length === 0) return geom3.create()
|
|
28
23
|
|
|
29
|
-
return geom3.create(
|
|
24
|
+
return geom3.create(hullPoints3(unique))
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
module.exports = hullGeom3
|
|
@@ -6,7 +6,10 @@ const hullPoints2 = require('./hullPoints2')
|
|
|
6
6
|
const toUniquePoints = require('./toUniquePoints')
|
|
7
7
|
|
|
8
8
|
/*
|
|
9
|
-
* Create a convex hull of the given geometries
|
|
9
|
+
* Create a convex hull of the given path2 geometries.
|
|
10
|
+
*
|
|
11
|
+
* NOTE: The given geometries must be valid path2 geometry.
|
|
12
|
+
*
|
|
10
13
|
* @param {...geometries} geometries - list of path2 geometries
|
|
11
14
|
* @returns {path2} new geometry
|
|
12
15
|
*/
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
const vec2 = require('../../maths/vec2')
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
4
|
* Create a convex hull of the given set of points, where each point is an array of [x,y].
|
|
5
|
-
*
|
|
5
|
+
* @see https://en.wikipedia.org/wiki/Graham_scan
|
|
6
|
+
*
|
|
6
7
|
* @param {Array} uniquePoints - list of UNIQUE points from which to create a hull
|
|
7
8
|
* @returns {Array} a list of points that form the hull
|
|
9
|
+
* @alias module:modeling/hulls.hullPoints2
|
|
8
10
|
*/
|
|
9
11
|
const hullPoints2 = (uniquePoints) => {
|
|
10
12
|
// find min point
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const poly3 = require('../../geometries/poly3')
|
|
2
|
+
|
|
3
|
+
const quickhull = require('./quickhull')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Create a convex hull of the given set of points, where each point is an array of [x,y,z].
|
|
7
|
+
*
|
|
8
|
+
* @param {Array} uniquePoints - list of UNIQUE points from which to create a hull
|
|
9
|
+
* @returns {Array} a list of polygons (poly3)
|
|
10
|
+
* @alias module:modeling/hulls.hullPoints3
|
|
11
|
+
*/
|
|
12
|
+
const hullPoints3 = (uniquePoints) => {
|
|
13
|
+
const faces = quickhull(uniquePoints, { skipTriangulation: true })
|
|
14
|
+
|
|
15
|
+
const polygons = faces.map((face) => {
|
|
16
|
+
const vertices = face.map((index) => uniquePoints[index])
|
|
17
|
+
return poly3.create(vertices)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return polygons
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = hullPoints3
|
|
@@ -150,7 +150,7 @@ const roundedCuboid = (options) => {
|
|
|
150
150
|
|
|
151
151
|
if (roundRadius > (size[0] - EPS) ||
|
|
152
152
|
roundRadius > (size[1] - EPS) ||
|
|
153
|
-
roundRadius > (size[2] - EPS)) throw new Error('roundRadius must be smaller
|
|
153
|
+
roundRadius > (size[2] - EPS)) throw new Error('roundRadius must be smaller than the radius of all dimensions')
|
|
154
154
|
|
|
155
155
|
segments = Math.floor(segments / 4)
|
|
156
156
|
|
|
@@ -38,7 +38,7 @@ const roundedCylinder = (options) => {
|
|
|
38
38
|
if (!isGTE(height, 0)) throw new Error('height must be positive')
|
|
39
39
|
if (!isGTE(radius, 0)) throw new Error('radius must be positive')
|
|
40
40
|
if (!isGTE(roundRadius, 0)) throw new Error('roundRadius must be positive')
|
|
41
|
-
if (roundRadius > radius) throw new Error('roundRadius must be smaller
|
|
41
|
+
if (roundRadius > radius) throw new Error('roundRadius must be smaller than the radius')
|
|
42
42
|
if (!isGTE(segments, 4)) throw new Error('segments must be four or more')
|
|
43
43
|
|
|
44
44
|
// if size is zero return empty geometry
|
|
@@ -44,7 +44,7 @@ const roundedRectangle = (options) => {
|
|
|
44
44
|
size = size.map((v) => v / 2) // convert to radius
|
|
45
45
|
|
|
46
46
|
if (roundRadius > (size[0] - EPS) ||
|
|
47
|
-
roundRadius > (size[1] - EPS)) throw new Error('roundRadius must be smaller
|
|
47
|
+
roundRadius > (size[1] - EPS)) throw new Error('roundRadius must be smaller than the radius of all dimensions')
|
|
48
48
|
|
|
49
49
|
const cornersegments = Math.floor(segments / 4)
|
|
50
50
|
|