@jscad/modeling 2.9.6 → 2.11.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 +33 -0
- package/README.md +12 -2
- package/dist/jscad-modeling.min.js +154 -151
- package/package.json +2 -2
- package/src/geometries/path2/appendArc.js +6 -5
- package/src/geometries/path2/appendArc.test.js +3 -1
- package/src/geometries/path2/appendBezier.js +2 -1
- package/src/geometries/path2/transform.js +1 -1
- package/src/index.d.ts +1 -0
- package/src/maths/constants.js +10 -0
- package/src/maths/mat4/fromRotation.js +1 -1
- package/src/maths/mat4/fromTaitBryanRotation.js +1 -1
- package/src/maths/mat4/fromXRotation.js +1 -1
- package/src/maths/mat4/fromYRotation.js +1 -1
- package/src/maths/mat4/fromZRotation.js +1 -1
- package/src/maths/mat4/invert.test.js +5 -2
- package/src/maths/mat4/isOnlyTransformScale.js +1 -1
- package/src/maths/mat4/isOnlyTransformScale.test.js +3 -1
- package/src/maths/rotation.test.js +5 -2
- package/src/maths/utils/trigonometry.js +6 -6
- package/src/maths/utils/trigonometry.test.js +10 -8
- package/src/maths/vec2/fromAngleDegrees.js +1 -1
- package/src/maths/vec2/fromAngleRadians.test.js +4 -1
- package/src/maths/vec2/normal.js +3 -1
- package/src/maths/vec2/rotate.test.js +4 -1
- package/src/maths/vec3/rotateX.test.js +4 -1
- package/src/maths/vec3/rotateY.test.js +4 -1
- package/src/maths/vec3/rotateZ.test.js +4 -1
- package/src/measurements/index.d.ts +4 -0
- package/src/measurements/measureBoundingSphere.d.ts +9 -0
- package/src/measurements/measureCenter.d.ts +7 -0
- package/src/measurements/measureCenterOfMass.d.ts +7 -0
- package/src/measurements/measureDimensions.d.ts +7 -0
- package/src/operations/expansions/expand.test.js +3 -1
- package/src/operations/expansions/expandShell.js +4 -4
- package/src/operations/expansions/offsetFromPoints.js +2 -2
- package/src/operations/extrusions/extrudeFromSlices.test.js +3 -2
- package/src/operations/extrusions/extrudeHelical.d.ts +14 -0
- package/src/operations/extrusions/extrudeHelical.js +114 -0
- package/src/operations/extrusions/extrudeHelical.test.js +62 -0
- package/src/operations/extrusions/extrudeLinear.test.js +5 -3
- package/src/operations/extrusions/extrudeRectangular.js +1 -1
- package/src/operations/extrusions/extrudeRectangular.test.js +5 -3
- package/src/operations/extrusions/extrudeRotate.js +14 -13
- package/src/operations/extrusions/extrudeRotate.test.js +7 -5
- package/src/operations/extrusions/index.js +1 -0
- package/src/operations/extrusions/slice/calculatePlane.test.js +3 -2
- package/src/operations/extrusions/slice/index.js +2 -0
- package/src/operations/modifiers/generalize.d.ts +12 -0
- package/src/operations/modifiers/generalize.test.js +3 -1
- package/src/operations/modifiers/index.d.ts +2 -0
- package/src/operations/modifiers/snap.d.ts +6 -0
- package/src/operations/modifiers/snap.test.js +5 -3
- package/src/operations/transforms/rotate.js +1 -1
- package/src/operations/transforms/rotate.test.js +13 -11
- package/src/operations/transforms/transform.js +1 -1
- package/src/primitives/arc.js +8 -8
- package/src/primitives/arc.test.js +9 -8
- package/src/primitives/circle.js +4 -2
- package/src/primitives/circle.test.js +6 -5
- package/src/primitives/cuboid.js +1 -1
- package/src/primitives/cylinderElliptic.js +11 -11
- package/src/primitives/cylinderElliptic.test.js +3 -2
- package/src/primitives/ellipse.js +10 -10
- package/src/primitives/ellipse.test.js +6 -5
- package/src/primitives/ellipsoid.js +3 -2
- package/src/primitives/roundedCuboid.js +6 -6
- package/src/primitives/roundedCylinder.js +3 -3
- package/src/primitives/roundedRectangle.js +5 -5
- package/src/primitives/star.js +3 -2
- package/src/primitives/torus.js +4 -2
- package/src/primitives/torus.test.js +5 -3
- package/src/primitives/triangle.test.js +2 -1
- package/src/utils/degToRad.test.js +5 -5
- package/src/utils/insertSorted.js +1 -1
- package/src/utils/radToDeg.test.js +6 -6
- package/src/utils/radiusToSegments.js +6 -4
- package/src/utils/radiusToSegments.test.js +5 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/modeling",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.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",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"nyc": "15.1.0",
|
|
62
62
|
"uglifyify": "5.0.2"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "5899622c5ffc640001da7261d7c06a1223064ccc"
|
|
65
65
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { TAU } = require('../../maths/constants')
|
|
1
2
|
const vec2 = require('../../maths/vec2')
|
|
2
3
|
|
|
3
4
|
const fromPoints = require('./fromPoints')
|
|
@@ -12,7 +13,7 @@ const toPoints = require('./toPoints')
|
|
|
12
13
|
* @param {vec2} [options.radius=[0,0]] - radius of arc (X and Y)
|
|
13
14
|
* @param {Number} [options.xaxisrotation=0] - rotation (RADIANS) of the X axis of the arc with respect to the X axis of the coordinate system
|
|
14
15
|
* @param {Boolean} [options.clockwise=false] - draw an arc clockwise with respect to the center point
|
|
15
|
-
* @param {Boolean} [options.large=false] - draw an arc longer than
|
|
16
|
+
* @param {Boolean} [options.large=false] - draw an arc longer than TAU / 2 radians
|
|
16
17
|
* @param {Number} [options.segments=16] - number of segments per full rotation
|
|
17
18
|
* @param {path2} geometry - the path of which to append the arc
|
|
18
19
|
* @returns {path2} a new path with the appended points
|
|
@@ -111,15 +112,15 @@ const appendArc = (options, geometry) => {
|
|
|
111
112
|
const theta1 = vec2.angleRadians(vector1)
|
|
112
113
|
const theta2 = vec2.angleRadians(vector2)
|
|
113
114
|
let deltatheta = theta2 - theta1
|
|
114
|
-
deltatheta = deltatheta %
|
|
115
|
+
deltatheta = deltatheta % TAU
|
|
115
116
|
if ((!sweepFlag) && (deltatheta > 0)) {
|
|
116
|
-
deltatheta -=
|
|
117
|
+
deltatheta -= TAU
|
|
117
118
|
} else if ((sweepFlag) && (deltatheta < 0)) {
|
|
118
|
-
deltatheta +=
|
|
119
|
+
deltatheta += TAU
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
// Ok, we have the center point and angle range (from theta1, deltatheta radians) so we can create the ellipse
|
|
122
|
-
let numsteps = Math.ceil(Math.abs(deltatheta) /
|
|
123
|
+
let numsteps = Math.ceil(Math.abs(deltatheta) / TAU * segments) + 1
|
|
123
124
|
if (numsteps < 1) numsteps = 1
|
|
124
125
|
for (let step = 1; step < numsteps; step++) {
|
|
125
126
|
const theta = theta1 + step / numsteps * deltatheta
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
2
|
|
|
3
|
+
const { TAU } = require('../../maths/constants')
|
|
4
|
+
|
|
3
5
|
const { appendArc, fromPoints, toPoints } = require('./index')
|
|
4
6
|
|
|
5
7
|
const { comparePoints } = require('../../../test/helpers/')
|
|
@@ -48,7 +50,7 @@ test('appendArc: appending to a path produces a new path', (t) => {
|
|
|
48
50
|
t.is(pts.length, 16)
|
|
49
51
|
|
|
50
52
|
// test xaxisrotation
|
|
51
|
-
obs = appendArc({ endpoint: [12, -22], radius: [15, -20], xaxisrotation:
|
|
53
|
+
obs = appendArc({ endpoint: [12, -22], radius: [15, -20], xaxisrotation: TAU / 4 }, p2)
|
|
52
54
|
pts = toPoints(obs)
|
|
53
55
|
exp = [
|
|
54
56
|
[27, -22],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { TAU } = require('../../maths/constants')
|
|
1
2
|
const vec2 = require('../../maths/vec2')
|
|
2
3
|
const vec3 = require('../../maths/vec2')
|
|
3
4
|
|
|
@@ -117,7 +118,7 @@ const appendBezier = (options, geometry) => {
|
|
|
117
118
|
|
|
118
119
|
// subdivide each segment until the angle at each vertex becomes small enough:
|
|
119
120
|
let subdivideBase = 1
|
|
120
|
-
const maxangle =
|
|
121
|
+
const maxangle = TAU / segments
|
|
121
122
|
const maxsinangle = Math.sin(maxangle)
|
|
122
123
|
while (subdivideBase < newpoints.length - 1) {
|
|
123
124
|
const dir1 = vec2.subtract(v0, newpoints[subdivideBase], newpoints[subdivideBase - 1])
|
|
@@ -10,7 +10,7 @@ const mat4 = require('../../maths/mat4')
|
|
|
10
10
|
* @alias module:modeling/geometries/path2.transform
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
|
-
* let newpath = transform(fromZRotation(
|
|
13
|
+
* let newpath = transform(fromZRotation(TAU / 8), path)
|
|
14
14
|
*/
|
|
15
15
|
const transform = (matrix, geometry) => {
|
|
16
16
|
const transforms = mat4.multiply(mat4.create(), matrix, geometry.transforms)
|
package/src/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * as booleans from './operations/booleans'
|
|
|
11
11
|
export * as expansions from './operations/expansions'
|
|
12
12
|
export * as extrusions from './operations/extrusions'
|
|
13
13
|
export * as hulls from './operations/hulls'
|
|
14
|
+
export * as modifiers from './operations/modifiers'
|
|
14
15
|
export * as transforms from './operations/transforms'
|
|
15
16
|
|
|
16
17
|
export as namespace modeling
|
package/src/maths/constants.js
CHANGED
|
@@ -24,8 +24,18 @@ const NEPS = 1e-13
|
|
|
24
24
|
// for comparing coplanar polygons, as provided by the sphere primitive at high
|
|
25
25
|
// segmentation. NEPS is for 64 bit Number values.
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* The TAU property represents the ratio of the circumference of a circle to its radius.
|
|
29
|
+
* Approximately 6.28318530717958647692
|
|
30
|
+
* @default
|
|
31
|
+
* @example
|
|
32
|
+
* const { TAU } = require('@jscad/modeling').maths.constants
|
|
33
|
+
*/
|
|
34
|
+
const TAU = Math.PI * 2
|
|
35
|
+
|
|
27
36
|
module.exports = {
|
|
28
37
|
EPS,
|
|
29
38
|
NEPS,
|
|
39
|
+
TAU,
|
|
30
40
|
spatialResolution
|
|
31
41
|
}
|
|
@@ -17,7 +17,7 @@ const identity = require('./identity')
|
|
|
17
17
|
* @returns {mat4} out
|
|
18
18
|
* @alias module:modeling/maths/mat4.fromRotation
|
|
19
19
|
* @example
|
|
20
|
-
* let matrix = fromRotation(create(),
|
|
20
|
+
* let matrix = fromRotation(create(), TAU / 4, [0, 0, 3])
|
|
21
21
|
*/
|
|
22
22
|
const fromRotation = (out, rad, axis) => {
|
|
23
23
|
let [x, y, z] = axis
|
|
@@ -13,7 +13,7 @@ const { sin, cos } = require('../utils/trigonometry')
|
|
|
13
13
|
* @returns {mat4} out
|
|
14
14
|
* @alias module:modeling/maths/mat4.fromTaitBryanRotation
|
|
15
15
|
* @example
|
|
16
|
-
* let matrix = fromTaitBryanRotation(create(),
|
|
16
|
+
* let matrix = fromTaitBryanRotation(create(), TAU / 4, 0, TAU / 2)
|
|
17
17
|
*/
|
|
18
18
|
const fromTaitBryanRotation = (out, yaw, pitch, roll) => {
|
|
19
19
|
// precompute sines and cosines of Euler angles
|
|
@@ -12,7 +12,7 @@ const { sin, cos } = require('../utils/trigonometry')
|
|
|
12
12
|
* @returns {mat4} out
|
|
13
13
|
* @alias module:modeling/maths/mat4.fromXRotation
|
|
14
14
|
* @example
|
|
15
|
-
* let matrix = fromXRotation(create(),
|
|
15
|
+
* let matrix = fromXRotation(create(), TAU / 4)
|
|
16
16
|
*/
|
|
17
17
|
const fromXRotation = (out, radians) => {
|
|
18
18
|
const s = sin(radians)
|
|
@@ -12,7 +12,7 @@ const { sin, cos } = require('../utils/trigonometry')
|
|
|
12
12
|
* @returns {mat4} out
|
|
13
13
|
* @alias module:modeling/maths/mat4.fromYRotation
|
|
14
14
|
* @example
|
|
15
|
-
* let matrix = fromYRotation(create(),
|
|
15
|
+
* let matrix = fromYRotation(create(), TAU / 4)
|
|
16
16
|
*/
|
|
17
17
|
const fromYRotation = (out, radians) => {
|
|
18
18
|
const s = sin(radians)
|
|
@@ -12,7 +12,7 @@ const { sin, cos } = require('../utils/trigonometry')
|
|
|
12
12
|
* @returns {mat4} out
|
|
13
13
|
* @alias module:modeling/maths/mat4.fromZRotation
|
|
14
14
|
* @example
|
|
15
|
-
* let matrix = fromZRotation(create(),
|
|
15
|
+
* let matrix = fromZRotation(create(), TAU / 4)
|
|
16
16
|
*/
|
|
17
17
|
const fromZRotation = (out, radians) => {
|
|
18
18
|
const s = sin(radians)
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
const vec3 = require('../vec3/index')
|
|
5
|
+
|
|
2
6
|
const { create, invert, fromTranslation, fromXRotation } = require('./index')
|
|
3
7
|
|
|
4
8
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
|
-
const vec3 = require('../vec3/index')
|
|
6
9
|
|
|
7
10
|
test('mat4: invert() translate ', (t) => {
|
|
8
11
|
const matrix = fromTranslation(create(), [10, 10, 0])
|
|
@@ -17,7 +20,7 @@ test('mat4: invert() translate ', (t) => {
|
|
|
17
20
|
})
|
|
18
21
|
|
|
19
22
|
test('mat4: invert() rotate ', (t) => {
|
|
20
|
-
const matrix = fromXRotation(create(),
|
|
23
|
+
const matrix = fromXRotation(create(), TAU / 4)
|
|
21
24
|
const matrixInv = invert(create(), matrix)
|
|
22
25
|
|
|
23
26
|
const vec1 = [10, 10, 10]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
* Determine whether the given matrix is only translate and/or scale.
|
|
4
|
-
* This code returns true for
|
|
4
|
+
* This code returns true for TAU / 2 rotation as it can be interpreted as scale.
|
|
5
5
|
*
|
|
6
6
|
* @param {mat4} matrix - the matrix
|
|
7
7
|
* @returns {Boolean} true if matrix is for translate and/or scale
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
2
|
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
3
5
|
const { isOnlyTransformScale, create, fromTranslation, fromTaitBryanRotation, fromScaling, invert, multiply } = require('./index')
|
|
4
6
|
|
|
5
7
|
test('mat4: isOnlyTransformScale() should return true for right angles', (t) => {
|
|
6
|
-
let someRotation = fromTaitBryanRotation(create(),
|
|
8
|
+
let someRotation = fromTaitBryanRotation(create(), TAU / 2, 0, 0)
|
|
7
9
|
t.true(isOnlyTransformScale(someRotation))
|
|
8
10
|
t.true(isOnlyTransformScale(invert(create(), someRotation)))
|
|
9
11
|
|
|
@@ -2,15 +2,18 @@ const test = require('ava')
|
|
|
2
2
|
|
|
3
3
|
const { compareVectors } = require('../../test/helpers/index')
|
|
4
4
|
|
|
5
|
-
const { mat4, vec2, vec3 } = require('./index')
|
|
5
|
+
const { constants, mat4, vec2, vec3 } = require('./index')
|
|
6
6
|
|
|
7
7
|
// ALL POSITIVE ROTATIONS ARE CLOCKWISE
|
|
8
8
|
// see https://webglfundamentals.org/webgl/lessons/webgl-3d-orthographic.html
|
|
9
9
|
// IN A LEFT-HANDED COORDINATE SYSTEM
|
|
10
10
|
|
|
11
|
+
// JSCAD IS RIGHT-HANDED COORDINATE SYSTEM
|
|
12
|
+
// WHERE POSITIVE ROTATIONS ARE COUNTER-CLOCKWISE
|
|
13
|
+
|
|
11
14
|
// identity matrices for comparisons
|
|
12
15
|
|
|
13
|
-
const rad90 =
|
|
16
|
+
const rad90 = constants.TAU / 4
|
|
14
17
|
|
|
15
18
|
// +90 degree rotation about X
|
|
16
19
|
const cwX90Matrix = [
|
|
@@ -6,28 +6,28 @@ const { NEPS } = require('../constants')
|
|
|
6
6
|
const rezero = (n) => Math.abs(n) < NEPS ? 0 : n
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Return Math.sin but accurate for
|
|
9
|
+
* Return Math.sin but accurate for TAU / 4 rotations.
|
|
10
10
|
* Fixes rounding errors when sin should be 0.
|
|
11
11
|
*
|
|
12
12
|
* @param {Number} radians - angle in radians
|
|
13
13
|
* @returns {Number} sine of the given angle
|
|
14
14
|
* @alias module:modeling/utils.sin
|
|
15
15
|
* @example
|
|
16
|
-
* sin(
|
|
17
|
-
* sin(
|
|
16
|
+
* sin(TAU / 2) == 0
|
|
17
|
+
* sin(TAU) == 0
|
|
18
18
|
*/
|
|
19
19
|
const sin = (radians) => rezero(Math.sin(radians))
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Return Math.cos but accurate for
|
|
22
|
+
* Return Math.cos but accurate for TAU / 4 rotations.
|
|
23
23
|
* Fixes rounding errors when cos should be 0.
|
|
24
24
|
*
|
|
25
25
|
* @param {Number} radians - angle in radians
|
|
26
26
|
* @returns {Number} cosine of the given angle
|
|
27
27
|
* @alias module:modeling/utils.cos
|
|
28
28
|
* @example
|
|
29
|
-
* cos(
|
|
30
|
-
* cos(
|
|
29
|
+
* cos(TAU * 0.25) == 0
|
|
30
|
+
* cos(TAU * 0.75) == 0
|
|
31
31
|
*/
|
|
32
32
|
const cos = (radians) => rezero(Math.cos(radians))
|
|
33
33
|
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
2
|
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
3
5
|
const { cos, sin } = require('./trigonometry')
|
|
4
6
|
|
|
5
7
|
test('utils: sin() should return rounded values', (t) => {
|
|
6
8
|
t.is(sin(0), 0)
|
|
7
9
|
t.is(sin(9), Math.sin(9))
|
|
8
|
-
t.is(sin(0.
|
|
9
|
-
t.is(sin(
|
|
10
|
-
t.is(sin(
|
|
11
|
-
t.is(sin(
|
|
10
|
+
t.is(sin(0.25 * TAU), 1)
|
|
11
|
+
t.is(sin(0.5 * TAU), 0)
|
|
12
|
+
t.is(sin(0.75 * TAU), -1)
|
|
13
|
+
t.is(sin(TAU), 0)
|
|
12
14
|
t.is(sin(NaN), NaN)
|
|
13
15
|
t.is(sin(Infinity), NaN)
|
|
14
16
|
})
|
|
@@ -16,10 +18,10 @@ test('utils: sin() should return rounded values', (t) => {
|
|
|
16
18
|
test('utils: cos() should return rounded values', (t) => {
|
|
17
19
|
t.is(cos(0), 1)
|
|
18
20
|
t.is(cos(9), Math.cos(9))
|
|
19
|
-
t.is(cos(0.
|
|
20
|
-
t.is(cos(
|
|
21
|
-
t.is(cos(
|
|
22
|
-
t.is(cos(
|
|
21
|
+
t.is(cos(0.25 * TAU), 0)
|
|
22
|
+
t.is(cos(0.5 * TAU), -1)
|
|
23
|
+
t.is(cos(0.75 * TAU), 0)
|
|
24
|
+
t.is(cos(TAU), 1)
|
|
23
25
|
t.is(cos(NaN), NaN)
|
|
24
26
|
t.is(cos(Infinity), NaN)
|
|
25
27
|
})
|
|
@@ -8,6 +8,6 @@ const fromAngleRadians = require('./fromAngleRadians')
|
|
|
8
8
|
* @returns {vec2} out
|
|
9
9
|
* @alias module:modeling/maths/vec2.fromAngleDegrees
|
|
10
10
|
*/
|
|
11
|
-
const fromAngleDegrees = (out, degrees) => fromAngleRadians(out,
|
|
11
|
+
const fromAngleDegrees = (out, degrees) => fromAngleRadians(out, degrees * 0.017453292519943295)
|
|
12
12
|
|
|
13
13
|
module.exports = fromAngleDegrees
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
2
5
|
const { fromAngleRadians, create } = require('./index')
|
|
3
6
|
|
|
4
7
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
@@ -7,6 +10,6 @@ test('vec2: fromAngleRadians() should return a new vec2 with correct values', (t
|
|
|
7
10
|
const obs1 = fromAngleRadians(create(), 0)
|
|
8
11
|
t.true(compareVectors(obs1, [1.0, 0.0]))
|
|
9
12
|
|
|
10
|
-
const obs2 = fromAngleRadians(obs1,
|
|
13
|
+
const obs2 = fromAngleRadians(obs1, TAU / 2)
|
|
11
14
|
t.true(compareVectors(obs2, [-1, 1.2246468525851679e-16]))
|
|
12
15
|
})
|
package/src/maths/vec2/normal.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const { TAU } = require('../constants')
|
|
2
|
+
|
|
1
3
|
const create = require('./create')
|
|
2
4
|
const rotate = require('./rotate')
|
|
3
5
|
|
|
@@ -10,6 +12,6 @@ const rotate = require('./rotate')
|
|
|
10
12
|
* @returns {vec2} out
|
|
11
13
|
* @alias module:modeling/maths/vec2.normal
|
|
12
14
|
*/
|
|
13
|
-
const normal = (out, vector) => rotate(out, vector, create(), (
|
|
15
|
+
const normal = (out, vector) => rotate(out, vector, create(), (TAU / 4))
|
|
14
16
|
|
|
15
17
|
module.exports = normal
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
2
5
|
const { rotate, fromValues } = require('./index')
|
|
3
6
|
|
|
4
7
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
8
|
|
|
6
9
|
test('vec2: rotate() called with three parameters should update a vec2 with correct values', (t) => {
|
|
7
|
-
const radians =
|
|
10
|
+
const radians = TAU / 4
|
|
8
11
|
|
|
9
12
|
const obs1 = fromValues(0, 0)
|
|
10
13
|
const ret1 = rotate(obs1, [0, 0], [0, 0], 0)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
2
5
|
const { rotateX, fromValues } = require('./index')
|
|
3
6
|
|
|
4
7
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
8
|
|
|
6
9
|
test('vec3: rotateX() called with four parameters should update a vec3 with correct values', (t) => {
|
|
7
|
-
const radians =
|
|
10
|
+
const radians = TAU / 4
|
|
8
11
|
|
|
9
12
|
const obs1 = fromValues(0, 0, 0)
|
|
10
13
|
const ret1 = rotateX(obs1, [0, 0, 0], [0, 0, 0], 0)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
2
5
|
const { rotateY, fromValues } = require('./index')
|
|
3
6
|
|
|
4
7
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
8
|
|
|
6
9
|
test('vec3: rotateY() called with three parameters should update a vec3 with correct values', (t) => {
|
|
7
|
-
const radians =
|
|
10
|
+
const radians = TAU / 4
|
|
8
11
|
|
|
9
12
|
const obs1 = fromValues(0, 0, 0)
|
|
10
13
|
const ret1 = rotateY(obs1, [0, 0, 0], [0, 0, 0], 0)
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
|
+
|
|
3
|
+
const { TAU } = require('../constants')
|
|
4
|
+
|
|
2
5
|
const { rotateZ, fromValues } = require('./index')
|
|
3
6
|
|
|
4
7
|
const { compareVectors } = require('../../../test/helpers/index')
|
|
5
8
|
|
|
6
9
|
test('vec3: rotateZ() called with four parameters should update a vec3 with correct values', (t) => {
|
|
7
|
-
const radians =
|
|
10
|
+
const radians = TAU / 4
|
|
8
11
|
|
|
9
12
|
const obs1 = fromValues(0, 0, 0)
|
|
10
13
|
const ret1 = rotateZ(obs1, [0, 0, 0], [0, 0, 0], 0)
|
|
@@ -4,6 +4,10 @@ export { default as measureAggregateEpsilon } from './measureAggregateEpsilon'
|
|
|
4
4
|
export { default as measureAggregateVolume } from './measureAggregateVolume'
|
|
5
5
|
export { default as measureArea } from './measureArea'
|
|
6
6
|
export { default as measureBoundingBox } from './measureBoundingBox'
|
|
7
|
+
export { default as measureBoundingSphere } from './measureBoundingSphere'
|
|
8
|
+
export { default as measureCenter } from './measureCenter'
|
|
9
|
+
export { default as measureCenterOfMass } from './measureCenterOfMass'
|
|
10
|
+
export { default as measureDimensions } from './measureDimensions'
|
|
7
11
|
export { default as measureEpsilon } from './measureEpsilon'
|
|
8
12
|
export { default as measureVolume } from './measureVolume'
|
|
9
13
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Geometry } from '../geometries/types'
|
|
2
|
+
import RecursiveArray from '../utils/recursiveArray'
|
|
3
|
+
|
|
4
|
+
type Centroid = [number, number, number]
|
|
5
|
+
|
|
6
|
+
export default measureBoundingSphere
|
|
7
|
+
|
|
8
|
+
declare function measureBoundingSphere(geometry: Geometry): [Centroid, number]
|
|
9
|
+
declare function measureBoundingSphere(...geometries: RecursiveArray<Geometry>): [Centroid, number][]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Geometry } from '../geometries/types'
|
|
2
|
+
import RecursiveArray from '../utils/recursiveArray'
|
|
3
|
+
|
|
4
|
+
export default measureCenter
|
|
5
|
+
|
|
6
|
+
declare function measureCenter(geometry: Geometry): [number, number, number]
|
|
7
|
+
declare function measureCenter(...geometries: RecursiveArray<Geometry>): [number, number, number][]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Geometry } from '../geometries/types'
|
|
2
|
+
import RecursiveArray from '../utils/recursiveArray'
|
|
3
|
+
|
|
4
|
+
export default measureCenterOfMass
|
|
5
|
+
|
|
6
|
+
declare function measureCenterOfMass(geometry: Geometry): [number, number, number]
|
|
7
|
+
declare function measureCenterOfMass(...geometries: RecursiveArray<Geometry>): [number, number, number][]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Geometry } from '../geometries/types'
|
|
2
|
+
import RecursiveArray from '../utils/recursiveArray'
|
|
3
|
+
|
|
4
|
+
export default measureDimensions
|
|
5
|
+
|
|
6
|
+
declare function measureDimensions(geometry: Geometry): [number, number, number]
|
|
7
|
+
declare function measureDimensions(...geometries: RecursiveArray<Geometry>): [number, number, number][]
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const test = require('ava')
|
|
2
2
|
|
|
3
3
|
const { comparePoints, nearlyEqual } = require('../../../test/helpers')
|
|
4
|
+
|
|
4
5
|
const { geom2, geom3, path2 } = require('../../geometries')
|
|
5
6
|
const measureBoundingBox = require('../../measurements/measureBoundingBox')
|
|
6
7
|
const area = require('../../maths/utils/area')
|
|
8
|
+
const { TAU } = require('../../maths/constants')
|
|
7
9
|
const sphere = require('../../primitives/sphere')
|
|
8
10
|
|
|
9
11
|
const { expand } = require('./index')
|
|
@@ -51,7 +53,7 @@ test('expand: round-expanding a bent line produces expected geometry', (t) => {
|
|
|
51
53
|
const expandedPoints = geom2.toPoints(expandedPathGeom2)
|
|
52
54
|
|
|
53
55
|
t.notThrows(() => geom2.validate(expandedPathGeom2))
|
|
54
|
-
const expectedArea = 56 +
|
|
56
|
+
const expectedArea = 56 + TAU * delta * 1.25 // shape will have 1 and 1/4 circles
|
|
55
57
|
nearlyEqual(t, area(expandedPoints), expectedArea, 0.01, 'Measured area should be pretty close')
|
|
56
58
|
const boundingBox = measureBoundingBox(expandedPathGeom2)
|
|
57
59
|
t.true(comparePoints(boundingBox, [[-7, -2, 0], [2, 12, 0]]), 'Unexpected bounding box: ' + JSON.stringify(boundingBox))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { EPS } = require('../../maths/constants')
|
|
1
|
+
const { EPS, TAU } = require('../../maths/constants')
|
|
2
2
|
|
|
3
3
|
const mat4 = require('../../maths/mat4')
|
|
4
4
|
const vec3 = require('../../maths/vec3')
|
|
@@ -120,7 +120,7 @@ const expandShell = (options, geometry) => {
|
|
|
120
120
|
|
|
121
121
|
// first of all equally spaced around the cylinder:
|
|
122
122
|
for (let i = 0; i < segments; i++) {
|
|
123
|
-
addUniqueAngle(angles, (i *
|
|
123
|
+
addUniqueAngle(angles, (i * TAU / segments))
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// and also at every normal of all touching planes:
|
|
@@ -130,10 +130,10 @@ const expandShell = (options, geometry) => {
|
|
|
130
130
|
const co = vec3.dot(xbase, planenormal)
|
|
131
131
|
let angle = Math.atan2(si, co)
|
|
132
132
|
|
|
133
|
-
if (angle < 0) angle +=
|
|
133
|
+
if (angle < 0) angle += TAU
|
|
134
134
|
addUniqueAngle(angles, angle)
|
|
135
135
|
angle = Math.atan2(-si, -co)
|
|
136
|
-
if (angle < 0) angle +=
|
|
136
|
+
if (angle < 0) angle += TAU
|
|
137
137
|
addUniqueAngle(angles, angle)
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { EPS } = require('../../maths/constants')
|
|
1
|
+
const { EPS, TAU } = require('../../maths/constants')
|
|
2
2
|
|
|
3
3
|
const intersect = require('../../maths/utils/intersect')
|
|
4
4
|
const line2 = require('../../maths/line2')
|
|
@@ -139,7 +139,7 @@ const offsetFromPoints = (options, points) => {
|
|
|
139
139
|
|
|
140
140
|
if (rotation !== 0.0) {
|
|
141
141
|
// generate the segments
|
|
142
|
-
cornersegments = Math.floor(segments * (Math.abs(rotation) /
|
|
142
|
+
cornersegments = Math.floor(segments * (Math.abs(rotation) / TAU))
|
|
143
143
|
const step = rotation / cornersegments
|
|
144
144
|
const start = vec2.angle(vec2.subtract(v0, corner.s0[1], corner.c))
|
|
145
145
|
const cornerpoints = []
|
|
@@ -2,6 +2,7 @@ const test = require('ava')
|
|
|
2
2
|
|
|
3
3
|
const comparePolygonsAsPoints = require('../../../test/helpers/comparePolygonsAsPoints')
|
|
4
4
|
|
|
5
|
+
const { TAU } = require('../../maths/constants')
|
|
5
6
|
const mat4 = require('../../maths/mat4')
|
|
6
7
|
|
|
7
8
|
const { geom2, geom3, poly3 } = require('../../geometries')
|
|
@@ -56,10 +57,10 @@ test('extrudeFromSlices (torus)', (t) => {
|
|
|
56
57
|
hex = poly3.transform(mat4.fromTranslation(mat4.create(), [0, 20, 0]), hex)
|
|
57
58
|
hex = slice.fromPoints(poly3.toPoints(hex))
|
|
58
59
|
|
|
59
|
-
const angle =
|
|
60
|
+
const angle = TAU / 8
|
|
60
61
|
const geometry3 = extrudeFromSlices(
|
|
61
62
|
{
|
|
62
|
-
numberOfSlices:
|
|
63
|
+
numberOfSlices: TAU / angle,
|
|
63
64
|
capStart: false,
|
|
64
65
|
capEnd: false,
|
|
65
66
|
close: true,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Geom2, Geom3 } from '../../geometries/types'
|
|
2
|
+
|
|
3
|
+
export default extrudeHelical
|
|
4
|
+
|
|
5
|
+
export interface ExtrudeHelicalOptions {
|
|
6
|
+
angle?: number
|
|
7
|
+
startAngle?: number
|
|
8
|
+
pitch?: number
|
|
9
|
+
height?: number
|
|
10
|
+
endOffset?: number
|
|
11
|
+
segmentsPerRotation?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
declare function extrudeHelical(options: ExtrudeHelicalOptions, geometry: Geom2): Geom3
|