Skip to content

Commit

Permalink
fix(modeling): corrected geom2 mirroring transform
Browse files Browse the repository at this point in the history
  • Loading branch information
platypii committed Oct 5, 2023
1 parent 03a1145 commit fbf6b61
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
10 changes: 9 additions & 1 deletion packages/modeling/src/geometries/geom2/transform.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const mat4 = require('../../maths/mat4')

const reverse = require('./reverse.js')

/**
* Transform the given geometry using the given matrix.
* This is a lazy transform of the sides, as this function only adjusts the transforms.
Expand All @@ -14,7 +16,13 @@ const mat4 = require('../../maths/mat4')
*/
const transform = (matrix, geometry) => {
const transforms = mat4.multiply(mat4.create(), matrix, geometry.transforms)
return Object.assign({}, geometry, { transforms })
const transformed = Object.assign({}, geometry, { transforms })
// determine if the transform is mirroring in 2D
if (matrix[0] * matrix[5] - matrix[4] * matrix[1] < 0) {
// reverse the order to preserve the orientation
return reverse(transformed)
}
return transformed
}

module.exports = transform
59 changes: 58 additions & 1 deletion packages/modeling/src/geometries/geom2/transform.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ const test = require('ava')

const mat4 = require('../../maths/mat4')

const { transform, fromPoints, toSides } = require('./index')
const { measureArea } = require('../../measurements/index.js')

const { mirrorX, mirrorY, mirrorZ } = require('../../operations/transforms/index.js')

const { square } = require('../../primitives/index.js')

const { fromPoints, transform, toOutlines, toSides } = require('./index.js')

const { comparePoints, compareVectors } = require('../../../test/helpers/')

Expand Down Expand Up @@ -51,3 +57,54 @@ test('transform: adjusts the transforms of geom2', (t) => {
t.true(comparePoints(another.sides[2], expected.sides[2]))
t.true(compareVectors(another.transforms, expected.transforms))
})

test('transform: geom2 mirrorX', (t) => {
const geometry = square()
const transformed = mirrorX(geometry)
t.is(measureArea(geometry), 4)
// area will be negative unless we reversed the points
t.is(measureArea(transformed), 4)
const pts = toOutlines(transformed)[0]
const exp = [[-1, 1], [-1, -1], [1, -1], [1, 1]]
t.true(comparePoints(pts, exp))
t.deepEqual(toSides(transformed), [
[[1, 1], [-1, 1]],
[[-1, 1], [-1, -1]],
[[-1, -1], [1, -1]],
[[1, -1], [1, 1]]
])
})

test('transform: geom2 mirrorY', (t) => {
const geometry = square()
const transformed = mirrorY(geometry)
t.is(measureArea(geometry), 4)
// area will be negative unless we reversed the points
t.is(measureArea(transformed), 4)
const pts = toOutlines(transformed)[0]
const exp = [[1, -1], [1, 1], [-1, 1], [-1, -1]]
t.true(comparePoints(pts, exp))
t.deepEqual(toSides(transformed), [
[[-1, -1], [1, -1]],
[[1, -1], [1, 1]],
[[1, 1], [-1, 1]],
[[-1, 1], [-1, -1]]
])
})

test('transform: geom2 mirrorZ', (t) => {
const geometry = square()
const transformed = mirrorZ(geometry)
t.is(measureArea(geometry), 4)
// area will be negative unless we DIDN'T reverse the points
t.is(measureArea(transformed), 4)
const pts = toOutlines(transformed)[0]
const exp = [[-1, -1], [1, -1], [1, 1], [-1, 1]]
t.true(comparePoints(pts, exp))
t.deepEqual(toSides(transformed), [
[[-1, 1], [-1, -1]],
[[-1, -1], [1, -1]],
[[1, -1], [1, 1]],
[[1, 1], [-1, 1]]
])
})
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const extrudeRotate = (options, geometry) => {
return [point0, point1]
})
// recreate the geometry from the (-) capped points
geometry = geom2.reverse(geom2.create(shapeSides))
geometry = geom2.create(shapeSides)
geometry = mirrorX(geometry)
} else if (pointsWithPositiveX.length >= pointsWithNegativeX.length) {
shapeSides = shapeSides.map((side) => {
Expand Down
12 changes: 9 additions & 3 deletions packages/modeling/src/operations/transforms/mirror.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const test = require('ava')

const { comparePoints, comparePolygonsAsPoints } = require('../../../test/helpers')

const { measureArea } = require('../../measurements')

const { geom2, geom3, path2 } = require('../../geometries')

const { mirror, mirrorX, mirrorY, mirrorZ } = require('./index')
Expand Down Expand Up @@ -40,25 +42,29 @@ test('mirror: mirroring of geom2 about X/Y produces expected changes to points',
// mirror about X
let mirrored = mirror({ normal: [1, 0, 0] }, geometry)
let obs = geom2.toPoints(mirrored)
let exp = [[5, -5], [0, 5], [-10, -5]]
let exp = [[0, 5], [5, -5], [-10, -5]]
t.notThrows(() => geom2.validate(mirrored))
t.is(measureArea(mirrored), measureArea(geometry))
t.true(comparePoints(obs, exp))

mirrored = mirrorX(geometry)
obs = geom2.toPoints(mirrored)
t.notThrows(() => geom2.validate(mirrored))
t.is(measureArea(mirrored), measureArea(geometry))
t.true(comparePoints(obs, exp))

// mirror about Y
mirrored = mirror({ normal: [0, 1, 0] }, geometry)
obs = geom2.toPoints(mirrored)
exp = [[-5, 5], [0, -5], [10, 5]]
exp = [[0, -5], [-5, 5], [10, 5]]
t.notThrows(() => geom2.validate(mirrored))
t.is(measureArea(mirrored), measureArea(geometry))
t.true(comparePoints(obs, exp))

mirrored = mirrorY(geometry)
obs = geom2.toPoints(mirrored)
t.notThrows(() => geom2.validate(mirrored))
t.is(measureArea(mirrored), measureArea(geometry))
t.true(comparePoints(obs, exp))
})

Expand Down Expand Up @@ -146,7 +152,7 @@ test('mirror: mirroring of multiple objects produces an array of mirrored object
t.true(comparePoints(obs, exp))

obs = geom2.toPoints(mirrored[2])
exp = [[-5, 5], [0, -5], [10, 5]]
exp = [[0, -5], [-5, 5], [10, 5]]
t.notThrows(() => geom2.validate(mirrored[2]))
t.true(comparePoints(obs, exp))
})

0 comments on commit fbf6b61

Please sign in to comment.