From 5374a2d9c0d9ef480dd0d9110a2e8efaf826aa65 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Sat, 7 May 2016 22:33:15 +0200 Subject: [PATCH] implement optimize paths --- src/slice.js | 73 ---------------- src/sliceActions/optimizePaths.js | 141 +++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 75 deletions(-) diff --git a/src/slice.js b/src/slice.js index 99e0870..deb8ecf 100644 --- a/src/slice.js +++ b/src/slice.js @@ -5,79 +5,6 @@ export default class { this.parts = []; } - optimizePaths(start) { - // if (this.brim !== undefined && this.brim.length > 0) { - // this.brim = this.brim.optimizePath(start); - // start = this.brim.lastPoint(); - // } - // - // var parts = []; - // - // while (this.parts.length > 0) { - // var closestDistance = Infinity; - // var closestPart; - // - // for (var i = 0; i < this.parts.length; i ++) { - // var part = this.parts[i]; - // if (part.shape.closed) { - // var bounds = part.outerLine.bounds(); - // } - // else { - // var bounds = part.shape.bounds(); - // } - // - // var top = bounds.top - start.y; - // var bottom = start.y - bounds.bottom; - // var left = bounds.left - start.x; - // var right = start.x - bounds.right; - // - // var distance = Math.max(top, bottom, left, right); - // - // if (distance < closestDistance) { - // closestDistance = distance; - // closestPart = i; - // } - // } - // - // var part = this.parts.splice(closestPart, 1)[0]; - // parts.push(part); - // - // if (part.shape.closed) { - // if (part.outerLine.length > 0) { - // part.outerLine = part.outerLine.optimizePath(start); - // start = part.outerLine.lastPoint(); - // } - // - // for (var j = 0; j < part.innerLines.length; j ++) { - // var innerLine = part.innerLines[j]; - // if (innerLine.length > 0) { - // part.innerLines[j] = innerLine.optimizePath(start); - // start = part.innerLines[j].lastPoint(); - // } - // } - // - // if (part.fill.length > 0) { - // part.fill = part.fill.optimizePath(start); - // start = part.fill.lastPoint(); - // } - // } - // else { - // part.shape.optimizePath(start); - // start = part.shape.lastPoint(); - // } - // - // } - // - // this.parts = parts; - // - // if (this.support !== undefined && this.support.length > 0) { - // this.support = this.support.optimizePath(start); - // start = this.support.lastPoint(); - // } - - return start; - } - getOutline () { const outLines = new Shape([], true); diff --git a/src/sliceActions/optimizePaths.js b/src/sliceActions/optimizePaths.js index 82b60e2..af7b728 100644 --- a/src/sliceActions/optimizePaths.js +++ b/src/sliceActions/optimizePaths.js @@ -1,4 +1,5 @@ import THREE from 'three.js'; +import Shape from 'Doodle3D/clipper-js'; export default function optimizePaths(slices, settings) { console.log('optimize paths'); @@ -8,8 +9,144 @@ export default function optimizePaths(slices, settings) { for (let layer = 0; layer < slices.length; layer ++) { const slice = slices[layer]; - const end = slice.optimizePaths(start); + if (slice.brim !== undefined && slice.brim.paths.length > 0) { + slice.brim = optimizeShape(slice.brim, start); + start.copy(slice.brim.lastPoint()); + } - start.copy(end); + const parts = []; + + while (slice.parts.length > 0) { + let closestDistance = Infinity; + let closestPart; + + for (let i = 0; i < slice.parts.length; i ++) { + const part = slice.parts[i]; + + let bounds; + if (part.shape.closed) { + bounds = part.outerLine.shapeBounds(); + } else { + bounds = part.shape.shapeBounds(); + } + + const top = bounds.top - start.y; + const bottom = start.y - bounds.bottom; + const left = bounds.left - start.x; + const right = start.x - bounds.right; + + const distance = Math.max(top, bottom, left, right); + + if (distance < closestDistance) { + closestDistance = distance; + closestPart = i; + } + } + + const part = slice.parts.splice(closestPart, 1)[0]; + parts.push(part); + + if (part.shape.closed) { + if (part.outerLine.paths.length > 0) { + part.outerLine = optimizeShape(part.outerLine, start); + start.copy(part.outerLine.lastPoint()); + } + + for (let i = 0; i < part.innerLines.length; i ++) { + const innerLine = part.innerLines[i]; + + if (innerLine.paths.length > 0) { + part.innerLines[i] = optimizeShape(innerLine, start); + start.copy(part.innerLines[i].lastPoint()); + } + } + + if (part.fill.paths.length > 0) { + part.fill = optimizeShape(part.fill, start); + start.copy(part.fill.lastPoint()); + } + } else { + part.shape = optimizeShape(part.shape, start); + start.copy(part.shape.lastPoint()); + } + } + + slice.parts = parts; + + if (slice.support !== undefined && slice.support.length > 0) { + slice.support = optimizeShape(slice.support, start); + start.copy(slice.support.lastPoint()); + } } } + +function optimizeShape(shape, start) { + start = start.clone(); + + const inputPaths = shape.mapToLower(); + const optimizedPaths = []; + const donePaths = []; + + while (optimizedPaths.length !== inputPaths.length) { + let minLength = false; + let reverse; + let minPath; + let offset; + let pathIndex; + + for (let i = 0; i < inputPaths.length; i ++) { + if (donePaths.indexOf(i) !== -1) continue; + + const path = inputPaths[i]; + + if (shape.closed) { + for (let j = 0; j < path.length; j += 1) { + const point = new THREE.Vector2().copy(path[j]); + const length = point.sub(start).length(); + if (minLength === false || length < minLength) { + minPath = path; + minLength = length; + offset = j; + pathIndex = i; + } + } + } else { + const startPoint = new THREE.Vector2().copy(path[0]); + const lengthToStart = startPoint.sub(start).length(); + if (minLength === false || lengthToStart < minLength) { + minPath = path; + minLength = lengthToStart; + reverse = false; + pathIndex = i; + } + + const endPoint = new THREE.Vector2().copy(path[path.length - 1]); + const lengthToEnd = endPoint.sub(start).length(); + if (lengthToEnd < minLength) { + minPath = path; + minLength = lengthToEnd; + reverse = true; + pathIndex = i; + } + } + } + + let point; + if (shape.closed) { + minPath = minPath.concat(minPath.splice(0, offset)); + point = minPath[0]; + } else { + if (reverse) { + minPath.reverse(); + } + point = minPath[minPath.length - 1]; + } + + donePaths.push(pathIndex); + start.copy(point); + + optimizedPaths.push(minPath); + } + + return new Shape(optimizedPaths, shape.closed, true); +}