1
0
Fork 0

Added path.trim()

This commit is contained in:
Joost De Cock 2018-09-04 15:21:59 +02:00
parent c44b888323
commit 3738b5e98c
2 changed files with 41 additions and 58 deletions

View file

@ -287,15 +287,17 @@ function asPath(bezier) {
/** Joins path segments together into one path */ /** Joins path segments together into one path */
function joinPaths(paths, closed = false) { function joinPaths(paths, closed = false) {
let joint = new Path().move(paths[0].ops[0].to); let joint = new Path().move(paths[0].ops[0].to);
let current;
for (let p of paths) { for (let p of paths) {
for (let op of p.ops) { for (let op of p.ops) {
if (op.type === "curve") { if (op.type === "curve") {
joint.curve(op.cp1, op.cp2, op.to); joint.curve(op.cp1, op.cp2, op.to);
} else if (op.type !== "close") { } else if (op.type !== "close") {
joint.line(op.to); if (current && !op.to.sitsOn(current)) joint.line(op.to);
} else { } else {
throw "Cannot join a closed paths with another"; throw "Cannot join a closed paths with another";
} }
if (op.to) current = op.to;
} }
} }
if (closed) joint.close(); if (closed) joint.close();
@ -507,10 +509,10 @@ Path.prototype.divide = function() {
for (let i in this.ops) { for (let i in this.ops) {
let op = this.ops[i]; let op = this.ops[i];
if (op.type === "move") { if (op.type === "move") {
current = op.to;
start = op.to; start = op.to;
} else if (op.type === "line") { } else if (op.type === "line") {
paths.push(new Path().move(current).line(op.to)); if (!op.to.sitsOn(current))
paths.push(new Path().move(current).line(op.to));
} else if (op.type === "curve") { } else if (op.type === "curve") {
paths.push(new Path().move(current).curve(op.cp1, op.cp2, op.to)); paths.push(new Path().move(current).curve(op.cp1, op.cp2, op.to));
} else if (op.type === "close") { } else if (op.type === "close") {
@ -703,7 +705,6 @@ Path.prototype.split = function(point) {
/** Removes self-intersections (overlap) from the path */ /** Removes self-intersections (overlap) from the path */
Path.prototype.trim = function() { Path.prototype.trim = function() {
// Walk the path to find all intersections
let chunks = this.divide(); let chunks = this.divide();
for (let i in chunks) { for (let i in chunks) {
let chunk = chunks[i]; let chunk = chunks[i];
@ -716,62 +717,44 @@ Path.prototype.trim = function() {
let trimmedStart = chunks.slice(0, i); let trimmedStart = chunks.slice(0, i);
let trimmedEnd = chunks.slice(parseInt(j) + 1); let trimmedEnd = chunks.slice(parseInt(j) + 1);
let glue = new Path(); let glue = new Path();
let ops = chunks[i].ops; let first = true;
if (ops[1].type === "line") { for (let k of [i, j]) {
glue.line(intersection); let ops = chunks[k].ops;
} else if (ops[1].type === "curve") { if (ops[1].type === "line") {
// handle curve glue.line(intersection);
let curve = new Bezier( } else if (ops[1].type === "curve") {
{ x: ops[0].to.x, y: ops[0].to.y }, // handle curve
{ x: ops[1].cp1.x, y: ops[1].cp1.y }, let curve = new Bezier(
{ x: ops[1].cp2.x, y: ops[1].cp2.y }, { x: ops[0].to.x, y: ops[0].to.y },
{ x: ops[1].to.x, y: ops[1].to.y } { x: ops[1].cp1.x, y: ops[1].cp1.y },
); { x: ops[1].cp2.x, y: ops[1].cp2.y },
let t = pointOnCurve( { x: ops[1].to.x, y: ops[1].to.y }
ops[0].to, );
ops[1].cp1, let t = pointOnCurve(
ops[1].cp2, ops[0].to,
ops[1].to, ops[1].cp1,
intersection ops[1].cp2,
); ops[1].to,
let split = curve.split(t); intersection
glue.curve( );
new Point(split.left.points[1].x, split.left.points[1].y), let split = curve.split(t);
new Point(split.left.points[2].x, split.left.points[2].y), let side;
new Point(split.left.points[3].x, split.left.points[3].y) if (first) side = split.left;
); else side = split.right;
} glue.curve(
ops = chunks[j].ops; new Point(side.points[1].x, side.points[1].y),
if (ops[1].type === "line") { new Point(side.points[2].x, side.points[2].y),
glue.line(intersection); new Point(side.points[3].x, side.points[3].y)
} else if (ops[1].type === "curve") { );
// handle curve }
let curve = new Bezier( first = false;
{ x: ops[0].to.x, y: ops[0].to.y },
{ x: ops[1].cp1.x, y: ops[1].cp1.y },
{ x: ops[1].cp2.x, y: ops[1].cp2.y },
{ x: ops[1].to.x, y: ops[1].to.y }
);
let t = pointOnCurve(
ops[0].to,
ops[1].cp1,
ops[1].cp2,
ops[1].to,
intersection
);
let split = curve.split(t);
glue.curve(
new Point(split.right.points[1].x, split.right.points[1].y),
new Point(split.right.points[2].x, split.right.points[2].y),
new Point(split.right.points[3].x, split.right.points[3].y)
);
} }
let joint; let joint;
if (trimmedStart.length > 0) joint = joinPaths(trimmedStart).join(glue); if (trimmedStart.length > 0) joint = joinPaths(trimmedStart).join(glue);
else joint = glue; else joint = glue;
if (trimmedEnd.length > 0) joint = joint.join(joinPaths(trimmedEnd)); if (trimmedEnd.length > 0) joint = joint.join(joinPaths(trimmedEnd));
return joint; return joint.trim();
} }
} }
} }

View file

@ -38,8 +38,8 @@ it("Should offset a curve where cp1 = start", () => {
.curve(new a.Point(0, 0), new a.Point(123, 34), new a.Point(23, 4)); .curve(new a.Point(0, 0), new a.Point(123, 34), new a.Point(23, 4));
a.paths.offset = a.paths.curve.offset(10); a.paths.offset = a.paths.curve.offset(10);
pattern.render(); pattern.render();
expect(a.paths.offset.bottomRight.x).to.equal(72.50457052909852); expect(a.paths.offset.bottomRight.x).to.equal(72.6776854668095);
expect(a.paths.offset.bottomRight.y).to.equal(26.44); expect(a.paths.offset.bottomRight.y).to.equal(26.49);
}); });
it("Should offset a curve where cp2 = end", () => { it("Should offset a curve where cp2 = end", () => {
@ -53,8 +53,8 @@ it("Should offset a curve where cp2 = end", () => {
.close(); .close();
a.paths.offset = a.paths.curve.offset(10); a.paths.offset = a.paths.curve.offset(10);
pattern.render(); pattern.render();
expect(a.paths.offset.bottomRight.x).to.equal(119.23); expect(a.paths.offset.bottomRight.x).to.equal(119.25);
expect(a.paths.offset.bottomRight.y).to.equal(43.26); expect(a.paths.offset.bottomRight.y).to.equal(43.27);
}); });
it("Should throw error when offsetting line that is no line", () => { it("Should throw error when offsetting line that is no line", () => {