Skip to content

Commit 074f05a

Browse files
committed
fix(modeling): corrected handling of pitch vs height in extrudeHelical
1 parent e2a212f commit 074f05a

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

packages/modeling/src/operations/extrusions/extrudeHelical.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
const { TAU } = require('../../maths/constants')
2-
const slice = require('./slice')
32
const mat4 = require('../../maths/mat4')
4-
const extrudeFromSlices = require('./extrudeFromSlices')
3+
54
const geom2 = require('../../geometries/geom2')
65

6+
const extrudeFromSlices = require('./extrudeFromSlices')
7+
const slice = require('./slice')
8+
79
/**
810
* Perform a helical extrude of the geometry, using the given options.
911
*
1012
* @param {Object} options - options for extrusion
11-
* @param {Number} [options.angle=TAU] - angle of the extrusion (RADIANS) positive for right-hand rotation, negative for left-hand
13+
* @param {Number} [options.angle=TAU] - angle of the extrusion (RADIANS); positive for right-hand rotation, negative for left-hand
1214
* @param {Number} [options.startAngle=0] - start angle of the extrusion (RADIANS)
13-
* @param {Number} [options.pitch=10] - elevation gain for each turn
15+
* @param {Number} [options.pitch=10] - elevation gain for each full rotation
1416
* @param {Number} [options.height] - total height of the helix path. Ignored if pitch is set.
1517
* @param {Number} [options.endOffset=0] - offset the final radius of the extrusion, allowing for tapered helix, and or spiral
1618
* @param {Number} [options.segmentsPerRotation=32] - number of segments per full rotation of the extrusion
@@ -20,24 +22,23 @@ const geom2 = require('../../geometries/geom2')
2022
*
2123
* @example
2224
* const myshape = circle({size: 3, center: [10, 0]}) // position for extrusion about Z
23-
* const mycoil = extrudeHelical({angle: TAU*2, pitch: 10, segmentsPerRotation: 64}, myshape))
25+
* const mycoil = extrudeHelical({angle: TAU * 2, pitch: 10, segmentsPerRotation: 64}, myshape))
2426
*/
2527
const extrudeHelical = (options, geometry) => {
2628
const defaults = {
2729
angle: TAU,
2830
startAngle: 0,
2931
pitch: 10,
32+
height: 0,
3033
endOffset: 0,
3134
segmentsPerRotation: 32
3235
}
33-
const { angle, endOffset, segmentsPerRotation, startAngle } = Object.assign({}, defaults, options)
34-
35-
let pitch
36-
// ignore height if pitch is set
37-
if (!options.pitch && options.height) {
38-
pitch = options.height / (angle / TAU)
39-
} else {
40-
pitch = options.pitch ? options.pitch : defaults.pitch
36+
let { angle, startAngle, pitch, height, endOffset, segmentsPerRotation } = Object.assign({}, defaults, options)
37+
38+
// calculate pitch from height if available
39+
if (height != 0) {
40+
// height / number of full rotations
41+
pitch = height / (angle / TAU)
4142
}
4243

4344
// needs at least 3 segments for each revolution
@@ -46,7 +47,7 @@ const extrudeHelical = (options, geometry) => {
4647
if (segmentsPerRotation < minNumberOfSegments) { throw new Error('The number of segments per rotation needs to be at least 3.') }
4748

4849
const shapeSides = geom2.toSides(geometry)
49-
if (shapeSides.length === 0) throw new Error('the given geometry cannot be empty')
50+
if (shapeSides.length === 0) throw new Error('The given geometry cannot be empty')
5051

5152
// const pointsWithNegativeX = shapeSides.filter((s) => (s[0][0] < 0))
5253
const pointsWithPositiveX = shapeSides.filter((s) => (s[0][0] >= 0))
@@ -60,9 +61,11 @@ const extrudeHelical = (options, geometry) => {
6061

6162
const calculatedSegments = Math.round(segmentsPerRotation / TAU * Math.abs(angle))
6263
const segments = calculatedSegments >= 2 ? calculatedSegments : 2
64+
6365
// define transform matrix variables for performance increase
6466
const step1 = mat4.create()
65-
let matrix
67+
const step2 = mat4.create()
68+
6669
const sliceCallback = (progress, index, base) => {
6770
const zRotation = startAngle + angle / segments * index
6871
const xOffset = endOffset / segments * index
@@ -84,14 +87,13 @@ const extrudeHelical = (options, geometry) => {
8487
mat4.fromXRotation(mat4.create(), -TAU / 4 * Math.sign(angle)) // rotate the slice correctly to not create inside-out polygon
8588
)
8689

87-
matrix = mat4.create()
8890
mat4.multiply(
89-
matrix,
91+
step2,
9092
// finally rotate around Z axis
9193
mat4.fromZRotation(mat4.create(), zRotation),
9294
step1
9395
)
94-
return slice.transform(matrix, base)
96+
return slice.transform(step2, base)
9597
}
9698

9799
return extrudeFromSlices(

0 commit comments

Comments
 (0)