UNPKG

@jscad/modeling

Version:

Constructive Solid Geometry (CSG) Library for JSCAD

79 lines (63 loc) 2.42 kB
const { EPS } = require('../../maths/constants') const vec3 = require('../../maths/vec3') const poly3 = require('../../geometries/poly3') const slice = require('./slice') // https://en.wikipedia.org/wiki/Greatest_common_divisor#Using_Euclid's_algorithm const gcd = (a, b) => { if (a === b) { return a } if (a < b) { return gcd(b, a) } if (b === 1) { return 1 } if (b === 0) { return a } return gcd(b, a % b) } const lcm = (a, b) => (a * b) / gcd(a, b) // Return a set of edges that encloses the same area by splitting // the given edges to have newlength total edges. const repartitionEdges = (newlength, edges) => { // NOTE: This implementation splits each edge evenly. const multiple = newlength / edges.length if (multiple === 1) { return edges } const divisor = vec3.fromValues(multiple, multiple, multiple) const newEdges = [] edges.forEach((edge) => { const increment = vec3.subtract(vec3.create(), edge[1], edge[0]) vec3.divide(increment, increment, divisor) // repartition the edge let prev = edge[0] for (let i = 1; i <= multiple; ++i) { const next = vec3.add(vec3.create(), prev, increment) newEdges.push([prev, next]) prev = next } }) return newEdges } const EPSAREA = (EPS * EPS / 2) * Math.sin(Math.PI / 3) /* * Extrude (build) walls between the given slices. * Each wall consists of two triangles, which may be invalid if slices are overlapping. */ const extrudeWalls = (slice0, slice1) => { let edges0 = slice.toEdges(slice0) let edges1 = slice.toEdges(slice1) if (edges0.length !== edges1.length) { // different shapes, so adjust one or both to the same number of edges const newlength = lcm(edges0.length, edges1.length) if (newlength !== edges0.length) edges0 = repartitionEdges(newlength, edges0) if (newlength !== edges1.length) edges1 = repartitionEdges(newlength, edges1) } const walls = [] edges0.forEach((edge0, i) => { const edge1 = edges1[i] const poly0 = poly3.create([edge0[0], edge0[1], edge1[1]]) const poly0area = poly3.measureArea(poly0) if (Number.isFinite(poly0area) && poly0area > EPSAREA) walls.push(poly0) const poly1 = poly3.create([edge0[0], edge1[1], edge1[0]]) const poly1area = poly3.measureArea(poly1) if (Number.isFinite(poly1area) && poly1area > EPSAREA) walls.push(poly1) }) return walls } module.exports = extrudeWalls