Skip to content

Commit

Permalink
fix(modeling): V2 - primitives revisited (#697)
Browse files Browse the repository at this point in the history
* style(modeling): updated to conform with coding standards

* fix(modeling): added further checks of parameters in primitives

* style(modeling): implemented common checks for primitives, and adjusted code

* style(modeling): renamed isArray check to isNumberArray, and reversed parameter order
  • Loading branch information
z3dev authored Sep 28, 2020
1 parent 15f96a4 commit 4721484
Show file tree
Hide file tree
Showing 32 changed files with 415 additions and 445 deletions.
14 changes: 7 additions & 7 deletions packages/modeling/src/primitives/arc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const vec2 = require('../maths/vec2')

const path2 = require('../geometries/path2')

const { isGT, isGTE, isNumberArray } = require('./commonChecks')

/**
* Construct an arc in two dimensional space.
* @param {Object} [options] - options for construction
Expand All @@ -27,13 +29,11 @@ const arc = (options) => {
}
let { center, radius, startAngle, endAngle, makeTangent, segments } = Object.assign({}, defaults, options)

if (!Array.isArray(center)) throw new Error('center must be an array')
if (center.length < 2) throw new Error('center must contain X and Y values')

if (!Number.isFinite(radius)) throw new Error('radius must be a number')

if (startAngle < 0 || endAngle < 0) throw new Error('the start and end angles must be positive')
if (segments < 4) throw new Error('segments must be four or more')
if (!isNumberArray(center, 2)) throw new Error('center must be an array of X and Y values')
if (!isGT(radius, 0)) throw new Error('radius must be greater than zero')
if (!isGTE(startAngle, 0)) throw new Error('startAngle must be positive')
if (!isGTE(endAngle, 0)) throw new Error('endAngle must be positive')
if (!isGTE(segments, 4)) throw new Error('segments must be four or more')

startAngle = startAngle % (Math.PI * 2)
endAngle = endAngle % (Math.PI * 2)
Expand Down
6 changes: 4 additions & 2 deletions packages/modeling/src/primitives/circle.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const ellipse = require('./ellipse')

const { isGT } = require('./commonChecks')

/**
* Construct a circle in two dimensional space where are points are at the same distance from the center.
* Construct a circle in two dimensional space where all points are at the same distance from the center.
* @see [ellipse]{@link module:modeling/primitives.ellipse} for more options
* @param {Object} [options] - options for construction
* @param {Array} [options.center=[0,0]] - center of circle
Expand All @@ -20,7 +22,7 @@ const circle = (options) => {
}
let { center, radius, segments } = Object.assign({}, defaults, options)

if (!Number.isFinite(radius)) throw new Error('radius must be a number')
if (!isGT(radius, 0)) throw new Error('radius must be greater than zero')

radius = [radius, radius]

Expand Down
66 changes: 33 additions & 33 deletions packages/modeling/src/primitives/circle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,41 @@ test('circle (defaults)', (t) => {

test('circle (options)', (t) => {
// test center
let geometry = circle({radius: 3.5, center: [6.5, 6.5]})
let geometry = circle({ radius: 3.5, center: [6.5, 6.5] })
let pts = geom2.toPoints(geometry)
let exp = [
[ 10, 6.5 ],
[ 9.932748481411306, 7.182816127056449 ],
[ 9.733578363789503, 7.8393920132778145 ],
[ 9.410143643058909, 8.444495815568608 ],
[ 8.974873734152917, 8.974873734152915 ],
[ 8.444495815568608, 9.410143643058909 ],
[ 7.8393920132778145, 9.733578363789503 ],
[ 7.182816127056449, 9.932748481411306 ],
[ 6.5, 10 ],
[ 5.817183872943551, 9.932748481411306 ],
[ 5.1606079867221855, 9.733578363789503 ],
[ 4.555504184431394, 9.410143643058909 ],
[ 4.025126265847084, 8.974873734152917 ],
[ 3.589856356941091, 8.444495815568608 ],
[ 3.2664216362104965, 7.8393920132778145 ],
[ 3.0672515185886935, 7.18281612705645 ],
[ 3, 6.5 ],
[ 3.0672515185886935, 5.81718387294355 ],
[ 3.266421636210496, 5.160607986722186 ],
[ 3.589856356941091, 4.555504184431394 ],
[ 4.025126265847083, 4.025126265847084 ],
[ 4.555504184431392, 3.5898563569410915 ],
[ 5.160607986722184, 3.266421636210497 ],
[ 5.817183872943549, 3.067251518588694 ],
[ 6.499999999999999, 3 ],
[ 7.182816127056449, 3.0672515185886935 ],
[ 7.8393920132778145, 3.266421636210497 ],
[ 8.444495815568606, 3.589856356941091 ],
[ 8.974873734152915, 4.025126265847083 ],
[ 9.410143643058909, 4.555504184431392 ],
[ 9.733578363789503, 5.160607986722184 ],
[ 9.932748481411306, 5.817183872943549 ]
[10, 6.5],
[9.932748481411306, 7.182816127056449],
[9.733578363789503, 7.8393920132778145],
[9.410143643058909, 8.444495815568608],
[8.974873734152917, 8.974873734152915],
[8.444495815568608, 9.410143643058909],
[7.8393920132778145, 9.733578363789503],
[7.182816127056449, 9.932748481411306],
[6.5, 10],
[5.817183872943551, 9.932748481411306],
[5.1606079867221855, 9.733578363789503],
[4.555504184431394, 9.410143643058909],
[4.025126265847084, 8.974873734152917],
[3.589856356941091, 8.444495815568608],
[3.2664216362104965, 7.8393920132778145],
[3.0672515185886935, 7.18281612705645],
[3, 6.5],
[3.0672515185886935, 5.81718387294355],
[3.266421636210496, 5.160607986722186],
[3.589856356941091, 4.555504184431394],
[4.025126265847083, 4.025126265847084],
[4.555504184431392, 3.5898563569410915],
[5.160607986722184, 3.266421636210497],
[5.817183872943549, 3.067251518588694],
[6.499999999999999, 3],
[7.182816127056449, 3.0672515185886935],
[7.8393920132778145, 3.266421636210497],
[8.444495815568606, 3.589856356941091],
[8.974873734152915, 4.025126265847083],
[9.410143643058909, 4.555504184431392],
[9.733578363789503, 5.160607986722184],
[9.932748481411306, 5.817183872943549]
]

t.deepEqual(pts.length, 32)
Expand Down
19 changes: 19 additions & 0 deletions packages/modeling/src/primitives/commonChecks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// verify that the array has the given dimension, and contains Number values
const isNumberArray = (array, dimension) => {
if (Array.isArray(array) && array.length >= dimension) {
return array.every((n) => Number.isFinite(n))
}
return false
}

// verify that the value is a Number greater than the constant
const isGT = (value, constant) => (Number.isFinite(value) && value > constant)

// verify that the value is a Number greater than or equal to the constant
const isGTE = (value, constant) => (Number.isFinite(value) && value >= constant)

module.exports = {
isNumberArray,
isGT,
isGTE
}
4 changes: 3 additions & 1 deletion packages/modeling/src/primitives/cube.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const cuboid = require('./cuboid')

const { isGT } = require('./commonChecks')

/**
* Construct an axis-aligned solid cube in three dimensional space with six square faces.
* @see [cuboid]{@link module:modeling/primitives.cuboid} for more options
Expand All @@ -18,7 +20,7 @@ const cube = (options) => {
}
let { center, size } = Object.assign({}, defaults, options)

if (!Number.isFinite(size)) throw new Error('size must be a number')
if (!isGT(size, 0)) throw new Error('size must be greater than zero')

size = [size, size, size]

Expand Down
14 changes: 7 additions & 7 deletions packages/modeling/src/primitives/cube.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ test('cube (defaults)', (t) => {

test('cube (options)', (t) => {
// test center
let obs = cube({size: 7, center: [6.5, 6.5, 6.5]})
let obs = cube({ size: 7, center: [6.5, 6.5, 6.5] })
let pts = geom3.toPoints(obs)
let exp = [
[ [ 3, 3, 3 ], [ 3, 3, 10 ], [ 3, 10, 10 ], [ 3, 10, 3 ] ],
[ [ 10, 3, 3 ], [ 10, 10, 3 ], [ 10, 10, 10 ], [ 10, 3, 10 ] ],
[ [ 3, 3, 3 ], [ 10, 3, 3 ], [ 10, 3, 10 ], [ 3, 3, 10 ] ],
[ [ 3, 10, 3 ], [ 3, 10, 10 ], [ 10, 10, 10 ], [ 10, 10, 3 ] ],
[ [ 3, 3, 3 ], [ 3, 10, 3 ], [ 10, 10, 3 ], [ 10, 3, 3 ] ],
[ [ 3, 3, 10 ], [ 10, 3, 10 ], [ 10, 10, 10 ], [ 3, 10, 10 ] ]
[[3, 3, 3], [3, 3, 10], [3, 10, 10], [3, 10, 3]],
[[10, 3, 3], [10, 10, 3], [10, 10, 10], [10, 3, 10]],
[[3, 3, 3], [10, 3, 3], [10, 3, 10], [3, 3, 10]],
[[3, 10, 3], [3, 10, 10], [10, 10, 10], [10, 10, 3]],
[[3, 3, 3], [3, 10, 3], [10, 10, 3], [10, 3, 3]],
[[3, 3, 10], [10, 3, 10], [10, 10, 10], [3, 10, 10]]
]

t.is(pts.length, 6)
Expand Down
10 changes: 5 additions & 5 deletions packages/modeling/src/primitives/cuboid.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const geom3 = require('../geometries/geom3')
const poly3 = require('../geometries/poly3')

const { isNumberArray } = require('./commonChecks')

/**
* Construct an axis-aligned solid cuboid in three dimensional space.
* @param {Object} [options] - options for construction
Expand All @@ -19,11 +21,9 @@ const cuboid = (options) => {
}
const { center, size } = Object.assign({}, defaults, options)

if (!Array.isArray(center)) throw new Error('center must be an array')
if (center.length < 3) throw new Error('center must contain X, Y and Z values')

if (!Array.isArray(size)) throw new Error('size must be an array')
if (size.length < 3) throw new Error('size must contain width, depth and height values')
if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
if (!isNumberArray(size, 3)) throw new Error('size must be an array of width, depth and height values')
if (!size.every((n) => n > 0)) throw new Error('size values must be greater than zero')

const result = geom3.create(
// adjust a basic shape to size
Expand Down
14 changes: 7 additions & 7 deletions packages/modeling/src/primitives/cuboid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ test('cuboid (defaults)', (t) => {

test('cuboid (options)', (t) => {
// test center
let obs = cuboid({size: [6, 6, 6], center: [3, 5, 7]})
let obs = cuboid({ size: [6, 6, 6], center: [3, 5, 7] })
let pts = geom3.toPoints(obs)
let exp = [
[ [ 0, 2, 4 ], [ 0, 2, 10 ], [ 0, 8, 10 ], [ 0, 8, 4 ] ],
[ [ 6, 2, 4 ], [ 6, 8, 4 ], [ 6, 8, 10 ], [ 6, 2, 10 ] ],
[ [ 0, 2, 4 ], [ 6, 2, 4 ], [ 6, 2, 10 ], [ 0, 2, 10 ] ],
[ [ 0, 8, 4 ], [ 0, 8, 10 ], [ 6, 8, 10 ], [ 6, 8, 4 ] ],
[ [ 0, 2, 4 ], [ 0, 8, 4 ], [ 6, 8, 4 ], [ 6, 2, 4 ] ],
[ [ 0, 2, 10 ], [ 6, 2, 10 ], [ 6, 8, 10 ], [ 0, 8, 10 ] ]
[[0, 2, 4], [0, 2, 10], [0, 8, 10], [0, 8, 4]],
[[6, 2, 4], [6, 8, 4], [6, 8, 10], [6, 2, 10]],
[[0, 2, 4], [6, 2, 4], [6, 2, 10], [0, 2, 10]],
[[0, 8, 4], [0, 8, 10], [6, 8, 10], [6, 8, 4]],
[[0, 2, 4], [0, 8, 4], [6, 8, 4], [6, 2, 4]],
[[0, 2, 10], [6, 2, 10], [6, 8, 10], [0, 8, 10]]
]

t.is(pts.length, 6)
Expand Down
4 changes: 3 additions & 1 deletion packages/modeling/src/primitives/cylinder.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const cylinderElliptic = require('./cylinderElliptic')

const { isGT } = require('./commonChecks')

/**
* Construct a solid cylinder in three dimensional space.
* @see [cylinderElliptic]{@link module:modeling/primitives.cylinderElliptic} for more options
Expand All @@ -26,7 +28,7 @@ const cylinder = (options) => {
}
const { center, height, radius, segments } = Object.assign({}, defaults, options)

if (!Number.isFinite(radius)) throw new Error('radius must be a number')
if (!isGT(radius, 0)) throw new Error('radius must be greater than zero')

const newoptions = {
center,
Expand Down
72 changes: 21 additions & 51 deletions packages/modeling/src/primitives/cylinder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,59 +43,29 @@ test('cylinder (options)', (t) => {
t.true(comparePolygonsAsPoints(pts, exp))

// test center
obs = cylinder({center: [-5, -5, -5], segments: 5})
obs = cylinder({ center: [-5, -5, -5], segments: 5 })
pts = geom3.toPoints(obs)
exp = [
[ [ -5, -5, -6 ],
[ -4.6909830056250525, -4.048943483704846, -6 ],
[ -4, -5, -6 ] ],
[ [ -4.6909830056250525, -4.048943483704846, -6 ],
[ -4.6909830056250525, -4.048943483704846, -4 ],
[ -4, -5, -4 ],
[ -4, -5, -6 ] ],
[ [ -5, -5, -4 ],
[ -4, -5, -4 ],
[ -4.6909830056250525, -4.048943483704846, -4 ] ],
[ [ -5, -5, -6 ],
[ -5.8090169943749475, -4.412214747707527, -6 ],
[ -4.6909830056250525, -4.048943483704846, -6 ] ],
[ [ -5.8090169943749475, -4.412214747707527, -6 ],
[ -5.8090169943749475, -4.412214747707527, -4 ],
[ -4.6909830056250525, -4.048943483704846, -4 ],
[ -4.6909830056250525, -4.048943483704846, -6 ] ],
[ [ -5, -5, -4 ],
[ -4.6909830056250525, -4.048943483704846, -4 ],
[ -5.8090169943749475, -4.412214747707527, -4 ] ],
[ [ -5, -5, -6 ],
[ -5.8090169943749475, -5.587785252292473, -6 ],
[ -5.8090169943749475, -4.412214747707527, -6 ] ],
[ [ -5.8090169943749475, -5.587785252292473, -6 ],
[ -5.8090169943749475, -5.587785252292473, -4 ],
[ -5.8090169943749475, -4.412214747707527, -4 ],
[ -5.8090169943749475, -4.412214747707527, -6 ] ],
[ [ -5, -5, -4 ],
[ -5.8090169943749475, -4.412214747707527, -4 ],
[ -5.8090169943749475, -5.587785252292473, -4 ] ],
[ [ -5, -5, -6 ],
[ -4.6909830056250525, -5.951056516295154, -6 ],
[ -5.8090169943749475, -5.587785252292473, -6 ] ],
[ [ -4.6909830056250525, -5.951056516295154, -6 ],
[ -4.6909830056250525, -5.951056516295154, -4 ],
[ -5.8090169943749475, -5.587785252292473, -4 ],
[ -5.8090169943749475, -5.587785252292473, -6 ] ],
[ [ -5, -5, -4 ],
[ -5.8090169943749475, -5.587785252292473, -4 ],
[ -4.6909830056250525, -5.951056516295154, -4 ] ],
[ [ -5, -5, -6 ],
[ -4, -5, -6 ],
[ -4.6909830056250525, -5.951056516295154, -6 ] ],
[ [ -4, -5, -6 ],
[ -4, -5, -4 ],
[ -4.6909830056250525, -5.951056516295154, -4 ],
[ -4.6909830056250525, -5.951056516295154, -6 ] ],
[ [ -5, -5, -4 ],
[ -4.6909830056250525, -5.951056516295154, -4 ],
[ -4, -5, -4 ] ]
[[-5, -5, -6], [-4.6909830056250525, -4.048943483704846, -6], [-4, -5, -6]],
[[-4.6909830056250525, -4.048943483704846, -6], [-4.6909830056250525, -4.048943483704846, -4],
[-4, -5, -4], [-4, -5, -6]],
[[-5, -5, -4], [-4, -5, -4], [-4.6909830056250525, -4.048943483704846, -4]],
[[-5, -5, -6], [-5.8090169943749475, -4.412214747707527, -6], [-4.6909830056250525, -4.048943483704846, -6]],
[[-5.8090169943749475, -4.412214747707527, -6], [-5.8090169943749475, -4.412214747707527, -4],
[-4.6909830056250525, -4.048943483704846, -4], [-4.6909830056250525, -4.048943483704846, -6]],
[[-5, -5, -4], [-4.6909830056250525, -4.048943483704846, -4], [-5.8090169943749475, -4.412214747707527, -4]],
[[-5, -5, -6], [-5.8090169943749475, -5.587785252292473, -6], [-5.8090169943749475, -4.412214747707527, -6]],
[[-5.8090169943749475, -5.587785252292473, -6], [-5.8090169943749475, -5.587785252292473, -4],
[-5.8090169943749475, -4.412214747707527, -4], [-5.8090169943749475, -4.412214747707527, -6]],
[[-5, -5, -4], [-5.8090169943749475, -4.412214747707527, -4], [-5.8090169943749475, -5.587785252292473, -4]],
[[-5, -5, -6], [-4.6909830056250525, -5.951056516295154, -6], [-5.8090169943749475, -5.587785252292473, -6]],
[[-4.6909830056250525, -5.951056516295154, -6], [-4.6909830056250525, -5.951056516295154, -4],
[-5.8090169943749475, -5.587785252292473, -4], [-5.8090169943749475, -5.587785252292473, -6]],
[[-5, -5, -4], [-5.8090169943749475, -5.587785252292473, -4], [-4.6909830056250525, -5.951056516295154, -4]],
[[-5, -5, -6], [-4, -5, -6], [-4.6909830056250525, -5.951056516295154, -6]],
[[-4, -5, -6], [-4, -5, -4],
[-4.6909830056250525, -5.951056516295154, -4], [-4.6909830056250525, -5.951056516295154, -6]],
[[-5, -5, -4], [-4.6909830056250525, -5.951056516295154, -4], [-4, -5, -4]]
]

t.is(pts.length, 15)
Expand Down
22 changes: 11 additions & 11 deletions packages/modeling/src/primitives/cylinderElliptic.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const vec3 = require('../maths/vec3')
const geom3 = require('../geometries/geom3')
const poly3 = require('../geometries/poly3')

const { isGT, isGTE, isNumberArray } = require('./commonChecks')

/**
* Construct an elliptic cylinder in three dimensional space.
* @param {Object} [options] - options for construction
Expand Down Expand Up @@ -37,17 +39,15 @@ const cylinderElliptic = (options) => {
}
let { center, height, startRadius, startAngle, endRadius, endAngle, segments } = Object.assign({}, defaults, options)

if (!Array.isArray(center)) throw new Error('center must be an array')
if (center.length < 3) throw new Error('center must contain X, Y and Z values')

if (height < (EPS * 2)) throw new Error('height must be larger then zero')

if ((endRadius[0] <= 0) || (startRadius[0] <= 0) || (endRadius[1] <= 0) || (startRadius[1] <= 0)) {
throw new Error('endRadus and startRadius should be positive')
}
if (startAngle < 0 || endAngle < 0) throw new Error('startAngle and endAngle must be positive')

if (segments < 4) throw new Error('segments must be four or more')
if (!isNumberArray(center, 3)) throw new Error('center must be an array of X, Y and Z values')
if (!isGT(height, 0)) throw new Error('height must be greater then zero')
if (!isNumberArray(startRadius, 2)) throw new Error('startRadius must be an array of X and Y values')
if (!startRadius.every((n) => n > 0)) throw new Error('startRadius values must be greater than zero')
if (!isNumberArray(endRadius, 2)) throw new Error('endRadius must be an array of X and Y values')
if (!endRadius.every((n) => n > 0)) throw new Error('endRadius values must be greater than zero')
if (!isGTE(startAngle, 0)) throw new Error('startAngle must be positive')
if (!isGTE(endAngle, 0)) throw new Error('endAngle must be positive')
if (!isGTE(segments, 4)) throw new Error('segments must be four or more')

startAngle = startAngle % (Math.PI * 2)
endAngle = endAngle % (Math.PI * 2)
Expand Down
Loading

0 comments on commit 4721484

Please sign in to comment.