mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2024-12-23 19:43:48 +01:00
Better detection of open closed shapes
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
This commit is contained in:
parent
5f5b1254ad
commit
846ddcd97a
@ -13,7 +13,7 @@ function addLine(geometry, lineLookup, lines, a, b) {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function createLines(geometry, settings) {
|
export default function createLines(geometry, settings, openClosed) {
|
||||||
console.log('constructing unique lines from geometry');
|
console.log('constructing unique lines from geometry');
|
||||||
|
|
||||||
const lines = [];
|
const lines = [];
|
||||||
@ -21,6 +21,8 @@ export default function createLines(geometry, settings) {
|
|||||||
|
|
||||||
for (let i = 0; i < geometry.faces.length; i ++) {
|
for (let i = 0; i < geometry.faces.length; i ++) {
|
||||||
const face = geometry.faces[i];
|
const face = geometry.faces[i];
|
||||||
|
const open = openClosed[i];
|
||||||
|
|
||||||
if (face.normal.y !== 1 && face.normal.y !== -1) {
|
if (face.normal.y !== 1 && face.normal.y !== -1) {
|
||||||
const normal = new THREE.Vector2(face.normal.z, face.normal.x).normalize();
|
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[indexA].normals.push(normal);
|
||||||
lines[indexB].normals.push(normal);
|
lines[indexB].normals.push(normal);
|
||||||
lines[indexC].normals.push(normal);
|
lines[indexC].normals.push(normal);
|
||||||
|
|
||||||
|
lines[indexA].open = open;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
71
src/sliceActions/detectOpenClosed.js
Normal file
71
src/sliceActions/detectOpenClosed.js
Normal file
@ -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);
|
||||||
|
}
|
@ -22,8 +22,9 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
|||||||
const shape = [];
|
const shape = [];
|
||||||
|
|
||||||
const firstPoints = [index];
|
const firstPoints = [index];
|
||||||
|
const { open: openGeometry } = lines[index];
|
||||||
let isFirstPoint = true;
|
let isFirstPoint = true;
|
||||||
let closed = false;
|
let openShape = true;
|
||||||
|
|
||||||
while (index !== -1) {
|
while (index !== -1) {
|
||||||
const intersection = intersectionPoints[index];
|
const intersection = intersectionPoints[index];
|
||||||
@ -38,8 +39,8 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
|||||||
for (let i = 0; i < connects.length; i ++) {
|
for (let i = 0; i < connects.length; i ++) {
|
||||||
index = connects[i];
|
index = connects[i];
|
||||||
|
|
||||||
if (firstPoints.indexOf(index) !== -1 && shape.length > 2) {
|
if (firstPoints.includes(index) && shape.length > 2) {
|
||||||
closed = true;
|
openShape = false;
|
||||||
index = -1;
|
index = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
|||||||
isFirstPoint = false;
|
isFirstPoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!closed) {
|
if (openShape) {
|
||||||
index = firstPoints[0];
|
index = firstPoints[0];
|
||||||
|
|
||||||
while (index !== -1) {
|
while (index !== -1) {
|
||||||
@ -107,10 +108,11 @@ export default function intersectionsToShapes(layerIntersectionIndexes, layerInt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closed) {
|
if (openGeometry) {
|
||||||
closedShapes.push(shape);
|
if (!openShape) shape.push(shape[0].clone());
|
||||||
} else {
|
|
||||||
openShapes.push(shape);
|
openShapes.push(shape);
|
||||||
|
} else {
|
||||||
|
closedShapes.push(shape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,12 +8,14 @@ import addBrim from './addBrim.js';
|
|||||||
import optimizePaths from './optimizePaths.js';
|
import optimizePaths from './optimizePaths.js';
|
||||||
import shapesToSlices from './shapesToSlices.js';
|
import shapesToSlices from './shapesToSlices.js';
|
||||||
import slicesToGCode from './slicesToGCode.js';
|
import slicesToGCode from './slicesToGCode.js';
|
||||||
|
import detectOpenClosed from './detectOpenClosed.js';
|
||||||
import applyPrecision from './applyPrecision.js';
|
import applyPrecision from './applyPrecision.js';
|
||||||
import removePrecision from './removePrecision.js';
|
import removePrecision from './removePrecision.js';
|
||||||
|
|
||||||
export default function(geometry, settings) {
|
export default function(geometry, settings) {
|
||||||
// get unique lines from geometry;
|
// get unique lines from geometry;
|
||||||
const lines = createLines(geometry, settings);
|
const openClosed = detectOpenClosed(geometry);
|
||||||
|
const lines = createLines(geometry, settings, openClosed);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
layerIntersectionIndexes,
|
layerIntersectionIndexes,
|
||||||
|
Loading…
Reference in New Issue
Block a user