diff --git a/src/sliceActions/createLines.js b/src/sliceActions/createLines.js index bd53efa..7f0a696 100644 --- a/src/sliceActions/createLines.js +++ b/src/sliceActions/createLines.js @@ -13,7 +13,7 @@ function addLine(geometry, lineLookup, lines, a, b) { return index; } -export default function createLines(geometry, settings) { +export default function createLines(geometry, settings, openClosed) { console.log('constructing unique lines from geometry'); const lines = []; @@ -21,6 +21,8 @@ export default function createLines(geometry, settings) { for (let i = 0; i < geometry.faces.length; i ++) { const face = geometry.faces[i]; + const open = openClosed[i]; + if (face.normal.y !== 1 && face.normal.y !== -1) { const normal = new THREE.Vector2(face.normal.z, face.normal.x).normalize(); @@ -42,6 +44,8 @@ export default function createLines(geometry, settings) { lines[indexA].normals.push(normal); lines[indexB].normals.push(normal); lines[indexC].normals.push(normal); + + lines[indexA].open = open; } } diff --git a/src/sliceActions/detectOpenClosed.js b/src/sliceActions/detectOpenClosed.js new file mode 100644 index 0000000..bcfbad9 --- /dev/null +++ b/src/sliceActions/detectOpenClosed.js @@ -0,0 +1,71 @@ +export default function detectOpenClosed(geometry) { + console.log('detecting open and closed lines'); + + const pools = getPools(geometry); + const openVertices = getOpenVertices(geometry); + + const openFaces = []; + for (let i = 0; i < pools.length; i ++) { + const pool = pools[i]; + + const isOpen = pool.some(face => openVertices[face.a] || openVertices[face.b] || openVertices[face.c]); + + if (isOpen) openFaces.splice(openFaces.length, 0, ...pool); + } + + return geometry.faces.map(face => openFaces.includes(face)); +} + +function findPool(pools, faceA) { + for (let i = 0; i < pools.length; i ++) { + const pool = pools[i]; + + if (pool.find(faceB => faceA.a === faceB.a || faceA.a === faceB.b || faceA.a === faceB.c)) { + return pool; + } + } + + const pool = []; + pools.push(pool); + return pool; +} + +function getPools(geometry) { + const pools = []; + + for (let i = 0; i < geometry.faces.length; i ++) { + const face = geometry.faces[i]; + const pool = findPool(pools, face); + pool.push(face); + } + + for (let i = 0; i < pools.length; i ++) { + const poolA = pools[i]; + + for (let j = i + 1; j < pools.length; j ++) { + const poolB = pools[j]; + + for (let k = 0; k < poolA.length; k ++) { + const faceA = poolA[k]; + if (poolB.find(faceB => faceA.a === faceB.a || faceA.a === faceB.b || faceA.a === faceB.c)) { + poolA.splice(poolA.length, 0, ...poolB); + poolB.splice(0, poolB.length); + } + } + } + } + + return pools.filter(pool => pool.length > 0); +} + +function getOpenVertices(geometry) { + const vertices = Array(geometry.vertices.length).fill(0); + for (let i = 0; i < geometry.faces.length; i ++) { + const face = geometry.faces[i]; + vertices[face.a] ++; + vertices[face.b] ++; + vertices[face.c] ++; + } + + return vertices.map(numFaces => numFaces < 4); +} diff --git a/src/sliceActions/intersectionsToShapes.js b/src/sliceActions/intersectionsToShapes.js index 9dd10e0..f06e7c0 100644 --- a/src/sliceActions/intersectionsToShapes.js +++ b/src/sliceActions/intersectionsToShapes.js @@ -22,8 +22,9 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt const shape = []; const firstPoints = [index]; + const { open: openGeometry } = lines[index]; let isFirstPoint = true; - let closed = false; + let openShape = true; while (index !== -1) { const intersection = intersectionPoints[index]; @@ -38,8 +39,8 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt for (let i = 0; i < connects.length; i ++) { index = connects[i]; - if (firstPoints.indexOf(index) !== -1 && shape.length > 2) { - closed = true; + if (firstPoints.includes(index) && shape.length > 2) { + openShape = false; index = -1; break; } @@ -82,7 +83,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt isFirstPoint = false; } - if (!closed) { + if (openShape) { index = firstPoints[0]; while (index !== -1) { @@ -107,10 +108,11 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt } } - if (closed) { - closedShapes.push(shape); - } else { + if (openGeometry) { + if (!openShape) shape.push(shape[0].clone()); openShapes.push(shape); + } else { + closedShapes.push(shape); } } diff --git a/src/sliceActions/slice.js b/src/sliceActions/slice.js index 28d4da4..8ee13b9 100644 --- a/src/sliceActions/slice.js +++ b/src/sliceActions/slice.js @@ -8,12 +8,14 @@ import addBrim from './addBrim.js'; import optimizePaths from './optimizePaths.js'; import shapesToSlices from './shapesToSlices.js'; import slicesToGCode from './slicesToGCode.js'; +import detectOpenClosed from './detectOpenClosed.js'; import applyPrecision from './applyPrecision.js'; import removePrecision from './removePrecision.js'; export default function(geometry, settings) { // get unique lines from geometry; - const lines = createLines(geometry, settings); + const openClosed = detectOpenClosed(geometry); + const lines = createLines(geometry, settings, openClosed); const { layerIntersectionIndexes,