UNPKG

@jscad/modeling

Version:

Constructive Solid Geometry (CSG) Library for JSCAD

133 lines (113 loc) 4.64 kB
const test = require('ava') const { poly3 } = require('../../../geometries') const plane = require('../../../maths/plane') const splitPolygonByPlane = require('./splitPolygonByPlane') test('splitPolygonByPlane: test coplanar-front polygon returns type 0.', (t) => { // Polygon in XY plane at z=0 const polygon = poly3.create([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]) // Plane is also XY plane at z=0, normal pointing up const splane = plane.fromPoints(plane.create(), [0, 0, 0], [1, 0, 0], [1, 1, 0]) const result = splitPolygonByPlane(splane, polygon) t.is(result.type, 0) // coplanar-front t.is(result.front, null) t.is(result.back, null) }) test('splitPolygonByPlane: test polygon entirely in front returns type 2.', (t) => { // Polygon at z=5 const polygon = poly3.create([[0, 0, 5], [1, 0, 5], [1, 1, 5], [0, 1, 5]]) // Plane at z=0 const splane = [0, 0, 1, 0] // normal (0,0,1), w=0 const result = splitPolygonByPlane(splane, polygon) t.is(result.type, 2) // front t.is(result.front, null) t.is(result.back, null) }) test('splitPolygonByPlane: test polygon entirely in back returns type 3.', (t) => { // Polygon at z=-5 const polygon = poly3.create([[0, 0, -5], [1, 0, -5], [1, 1, -5], [0, 1, -5]]) // Plane at z=0 const splane = [0, 0, 1, 0] // normal (0,0,1), w=0 const result = splitPolygonByPlane(splane, polygon) t.is(result.type, 3) // back t.is(result.front, null) t.is(result.back, null) }) test('splitPolygonByPlane: test spanning polygon returns type 4 with front and back.', (t) => { // Polygon spanning z=0 plane (from z=-1 to z=1) const polygon = poly3.create([[0, 0, -1], [1, 0, -1], [1, 0, 1], [0, 0, 1]]) // Plane at z=0 const splane = [0, 0, 1, 0] // normal (0,0,1), w=0 const result = splitPolygonByPlane(splane, polygon) t.is(result.type, 4) // spanning t.not(result.front, null) t.not(result.back, null) // Front polygon should have z >= 0 const frontPoints = poly3.toPoints(result.front) t.true(frontPoints.length >= 3) frontPoints.forEach((p) => { t.true(p[2] >= -1e-5, `front point z=${p[2]} should be >= 0`) }) // Back polygon should have z <= 0 const backPoints = poly3.toPoints(result.back) t.true(backPoints.length >= 3) backPoints.forEach((p) => { t.true(p[2] <= 1e-5, `back point z=${p[2]} should be <= 0`) }) }) test('splitPolygonByPlane: test duplicate vertices are removed from split result.', (t) => { // Create a polygon that when split would produce duplicate vertices // Triangle with one vertex on the plane const polygon = poly3.create([[0, 0, 0], [1, 0, 1], [1, 0, -1]]) // Plane at z=0 const splane = [0, 0, 1, 0] const result = splitPolygonByPlane(splane, polygon) t.is(result.type, 4) // spanning // Verify no consecutive duplicate vertices in front if (result.front) { const frontPoints = poly3.toPoints(result.front) for (let i = 0; i < frontPoints.length; i++) { const curr = frontPoints[i] const next = frontPoints[(i + 1) % frontPoints.length] const dx = curr[0] - next[0] const dy = curr[1] - next[1] const dz = curr[2] - next[2] const distSq = dx * dx + dy * dy + dz * dz t.true(distSq > 1e-10, 'front polygon should not have duplicate consecutive vertices') } } // Verify no consecutive duplicate vertices in back if (result.back) { const backPoints = poly3.toPoints(result.back) for (let i = 0; i < backPoints.length; i++) { const curr = backPoints[i] const next = backPoints[(i + 1) % backPoints.length] const dx = curr[0] - next[0] const dy = curr[1] - next[1] const dz = curr[2] - next[2] const distSq = dx * dx + dy * dy + dz * dz t.true(distSq > 1e-10, 'back polygon should not have duplicate consecutive vertices') } } }) test('splitPolygonByPlane: test complex spanning polygon splits correctly.', (t) => { // Hexagon spanning the XY plane const polygon = poly3.create([ [1, 0, -1], [0.5, 0.866, -1], [-0.5, 0.866, 1], [-1, 0, 1], [-0.5, -0.866, 1], [0.5, -0.866, -1] ]) // Plane at z=0 const splane = [0, 0, 1, 0] const result = splitPolygonByPlane(splane, polygon) t.is(result.type, 4) // spanning t.not(result.front, null) t.not(result.back, null) // Both resulting polygons should be valid (at least 3 vertices) const frontPoints = poly3.toPoints(result.front) const backPoints = poly3.toPoints(result.back) t.true(frontPoints.length >= 3, 'front polygon should have at least 3 vertices') t.true(backPoints.length >= 3, 'back polygon should have at least 3 vertices') })