@jscad/modeling
Version:
Constructive Solid Geometry (CSG) Library for JSCAD
189 lines (167 loc) • 6.8 kB
JavaScript
const test = require('ava')
const { comparePoints, nearlyEqual } = require('../../../test/helpers')
const { geom2, geom3, path2 } = require('../../geometries')
const measureBoundingBox = require('../../measurements/measureBoundingBox')
const area = require('../../maths/utils/area')
const { TAU } = require('../../maths/constants')
const sphere = require('../../primitives/sphere')
const { expand } = require('./index')
test('expand: edge-expanding a straight line produces rectangle', (t) => {
const points = [[0, 0], [0, 10]]
const linePath2 = path2.fromPoints({ closed: false }, points)
const expandedPathGeom2 = expand({ delta: 2, corners: 'edge', segments: 8 }, linePath2)
const expandedPoints = geom2.toPoints(expandedPathGeom2)
t.notThrows(() => geom2.validate(expandedPathGeom2))
t.is(area(expandedPoints), 40)
t.true(comparePoints(measureBoundingBox(expandedPathGeom2), [[-2, 0, 0], [2, 10, 0]]))
})
test('expand: edge-expanding a bent line produces expected geometry', (t) => {
const points = [[0, 0], [0, 10], [-5, 10]]
const linePath2 = path2.fromPoints({ closed: false }, points)
const expandedPathGeom2 = expand({ delta: 2, corners: 'edge', segments: 8 }, linePath2)
const expandedPoints = geom2.toPoints(expandedPathGeom2)
t.notThrows(() => geom2.validate(expandedPathGeom2))
t.is(area(expandedPoints), 60)
const boundingBox = measureBoundingBox(expandedPathGeom2)
t.true(comparePoints(boundingBox, [[-5, 0, 0], [2, 12, 0]]), 'Unexpected bounding box: ' + JSON.stringify(boundingBox))
})
test('expand: edge-expanding a bent line, reversed points, produces expected geometry', (t) => {
const points = [[-5, 10], [0, 10], [0, 0]]
const linePath2 = path2.fromPoints({ closed: false }, points)
const expandedPathGeom2 = expand({ delta: 2, corners: 'edge', segments: 8 }, linePath2)
const expandedPoints = geom2.toPoints(expandedPathGeom2)
t.notThrows(() => geom2.validate(expandedPathGeom2))
t.is(area(expandedPoints), 60)
const boundingBox = measureBoundingBox(expandedPathGeom2)
t.true(comparePoints(boundingBox, [[-5, 0, 0], [2, 12, 0]]), 'Unexpected bounding box: ' + JSON.stringify(boundingBox))
})
test('expand: round-expanding a bent line produces expected geometry', (t) => {
const delta = 2
const points = [[0, 0], [0, 10], [-5, 10]]
const linePath2 = path2.fromPoints({ closed: false }, points)
const expandedPathGeom2 = expand({ delta, corners: 'round', segments: 128 }, linePath2)
const expandedPoints = geom2.toPoints(expandedPathGeom2)
t.notThrows(() => geom2.validate(expandedPathGeom2))
const expectedArea = 56 + TAU * delta * 1.25 // shape will have 1 and 1/4 circles
nearlyEqual(t, area(expandedPoints), expectedArea, 0.01, 'Measured area should be pretty close')
const boundingBox = measureBoundingBox(expandedPathGeom2)
t.true(comparePoints(boundingBox, [[-7, -2, 0], [2, 12, 0]]), 'Unexpected bounding box: ' + JSON.stringify(boundingBox))
})
test('expand: chamfer-expanding a bent line produces expected geometry', (t) => {
const delta = 2
const points = [[0, 0], [0, 10], [-5, 10]]
const linePath2 = path2.fromPoints({ closed: false }, points)
const expandedPathGeom2 = expand({ delta, corners: 'chamfer', segments: 8 }, linePath2)
const expandedPoints = geom2.toPoints(expandedPathGeom2)
t.notThrows(() => geom2.validate(expandedPathGeom2))
t.is(area(expandedPoints), 58)
const boundingBox = measureBoundingBox(expandedPathGeom2)
t.true(comparePoints(boundingBox, [[-5, 0, 0], [2, 12, 0]]), 'Unexpected bounding box: ' + JSON.stringify(boundingBox))
})
test('expand: expanding of a geom2 produces expected changes to points', (t) => {
const geometry = geom2.fromPoints([[-8, -8], [8, -8], [8, 8], [-8, 8]])
const obs = expand({ delta: 2, corners: 'round', segments: 8 }, geometry)
const pts = geom2.toPoints(obs)
const exp = [
[-9.414213562373096, -9.414213562373096],
[-8, -10],
[8, -10],
[9.414213562373096, -9.414213562373096],
[10, -8],
[10, 8],
[9.414213562373096, 9.414213562373096],
[8, 10],
[-8, 10],
[-9.414213562373096, 9.414213562373096],
[-10, 8],
[-10, -8]
]
t.notThrows(() => geom2.validate(obs))
t.is(pts.length, 12)
t.true(comparePoints(pts, exp))
})
test('expand: expanding of a geom3 produces expected changes to polygons', (t) => {
const polygonsAsPoints = [
[[-5, -5, -5], [-5, -5, 15], [-5, 15, 15], [-5, 15, -5]],
[[15, -5, -5], [15, 15, -5], [15, 15, 15], [15, -5, 15]],
[[-5, -5, -5], [15, -5, -5], [15, -5, 15], [-5, -5, 15]],
[[-5, 15, -5], [-5, 15, 15], [15, 15, 15], [15, 15, -5]],
[[-5, -5, -5], [-5, 15, -5], [15, 15, -5], [15, -5, -5]],
[[-5, -5, 15], [15, -5, 15], [15, 15, 15], [-5, 15, 15]]
]
const geometry = geom3.fromPoints(polygonsAsPoints)
const obs = expand({ delta: 2, corners: 'round', segments: 8 }, geometry)
const pts = geom3.toPoints(obs)
const exp0 = [
[-7, -5, -5],
[-7, -5, 15],
[-7, 15, 15],
[-7, 15, -5]
]
const exp61 = [
[15, -7, 15],
[16.414213562373096, -6.414213562373095, 15],
[16, -6.414213562373095, 16]
]
t.notThrows.skip(() => geom3.validate(obs))
t.is(pts.length, 62)
t.true(comparePoints(pts[0], exp0))
t.true(comparePoints(pts[61], exp61))
const geometry2 = sphere({ radius: 5, segments: 8 })
const obs2 = expand({ delta: 5 }, geometry2)
const pts2 = geom3.toPoints(obs2)
t.notThrows.skip(() => geom3.validate(obs2))
t.is(pts2.length, 864)
})
test('expand (options): offsetting of a complex geom2 produces expected offset geom2', (t) => {
const geometry = geom2.create([
[[-75, 75], [-75, -75]],
[[-75, -75], [75, -75]],
[[75, -75], [75, 75]],
[[-40, 75], [-75, 75]],
[[75, 75], [40, 75]],
[[40, 75], [40, 0]],
[[40, 0], [-40, 0]],
[[-40, 0], [-40, 75]],
[[15, -10], [15, -40]],
[[-15, -10], [15, -10]],
[[-15, -40], [-15, -10]],
[[-8, -40], [-15, -40]],
[[15, -40], [8, -40]],
[[-8, -25], [-8, -40]],
[[8, -25], [-8, -25]],
[[8, -40], [8, -25]],
[[-2, -15], [-2, -19]],
[[-2, -19], [2, -19]],
[[2, -19], [2, -15]],
[[2, -15], [-2, -15]]
])
// expand +
const obs = expand({ delta: 2, corners: 'edge' }, geometry)
const pts = geom2.toPoints(obs)
const exp = [
[77, -77],
[77, 77],
[38, 77],
[38, 2],
[-38, 2],
[-37.99999999999999, 77],
[-77, 77],
[16.999999999999996, -42],
[6, -42],
[6, -27],
[-6, -27],
[-6.000000000000001, -42],
[-17, -42],
[-16.999999999999996, -8],
[17, -8.000000000000004],
[-4, -21],
[3.9999999999999996, -21],
[4, -13],
[-4, -13],
[-77, -77]
]
t.notThrows(() => geom2.validate(obs))
t.is(pts.length, 20)
t.true(comparePoints(pts, exp))
})