From 8b3a33eb86eede898cb6586cb283b50396601cb8 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Fri, 26 May 2017 17:11:38 +0200 Subject: [PATCH] Better detection of open closed shapes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when a ‘single walled’, ‘closed’ shape is sliced the shape will appear to be closed by the slicer. This happens because the start and endpoint of the 2d shape are connected. This commits fixes this. In the new approach al parts of the geometry are split up into shapes. Then the 3d shapes are places into two categories (closed and open geometries). Based on weather the 3d geometry is open or closed the 2d shape will be open or closed @mith @peteruithoven --- src/sliceActions/createLines.js | 6 +- src/sliceActions/detectOpenClosed.js | 71 +++++++++++++++++++++++ src/sliceActions/intersectionsToShapes.js | 16 ++--- src/sliceActions/slice.js | 4 +- 4 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 src/sliceActions/detectOpenClosed.js 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,