✨ Added Path.edge()
This commit is contained in:
parent
bb597282ee
commit
04bf540a5a
2 changed files with 176 additions and 8 deletions
118
src/path.js
118
src/path.js
|
@ -123,13 +123,26 @@ Path.prototype.boundary = function() {
|
||||||
let current;
|
let current;
|
||||||
let topLeft = new Point(Infinity, Infinity);
|
let topLeft = new Point(Infinity, Infinity);
|
||||||
let bottomRight = new Point(-Infinity, -Infinity);
|
let bottomRight = new Point(-Infinity, -Infinity);
|
||||||
|
let edges = [];
|
||||||
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" || op.type === "line") {
|
if (op.type === "move" || op.type === "line") {
|
||||||
if (op.to.x < topLeft.x) topLeft.x = op.to.x;
|
if (op.to.x < topLeft.x) {
|
||||||
if (op.to.y < topLeft.y) topLeft.y = op.to.y;
|
topLeft.x = op.to.x;
|
||||||
if (op.to.x > bottomRight.x) bottomRight.x = op.to.x;
|
edges["leftOp"] = i;
|
||||||
if (op.to.y > bottomRight.y) bottomRight.y = op.to.y;
|
}
|
||||||
|
if (op.to.y < topLeft.y) {
|
||||||
|
topLeft.y = op.to.y;
|
||||||
|
edges["topOp"] = i;
|
||||||
|
}
|
||||||
|
if (op.to.x > bottomRight.x) {
|
||||||
|
bottomRight.x = op.to.x;
|
||||||
|
edges["rightOp"] = i;
|
||||||
|
}
|
||||||
|
if (op.to.y > bottomRight.y) {
|
||||||
|
bottomRight.y = op.to.y;
|
||||||
|
edges["bottomOp"] = i;
|
||||||
|
}
|
||||||
} else if (op.type === "curve") {
|
} else if (op.type === "curve") {
|
||||||
let bb = new Bezier(
|
let bb = new Bezier(
|
||||||
{ x: current.x, y: current.y },
|
{ x: current.x, y: current.y },
|
||||||
|
@ -137,10 +150,22 @@ Path.prototype.boundary = function() {
|
||||||
{ x: op.cp2.x, y: op.cp2.y },
|
{ x: op.cp2.x, y: op.cp2.y },
|
||||||
{ x: op.to.x, y: op.to.y }
|
{ x: op.to.x, y: op.to.y }
|
||||||
).bbox();
|
).bbox();
|
||||||
if (bb.x.min < topLeft.x) topLeft.x = bb.x.min;
|
if (bb.x.min < topLeft.x) {
|
||||||
if (bb.y.min < topLeft.y) topLeft.y = bb.y.min;
|
topLeft.x = bb.x.min;
|
||||||
if (bb.x.max > bottomRight.x) bottomRight.x = bb.x.max;
|
edges["leftOp"] = i;
|
||||||
if (bb.y.max > bottomRight.y) bottomRight.y = bb.y.max;
|
}
|
||||||
|
if (bb.y.min < topLeft.y) {
|
||||||
|
topLeft.y = bb.y.min;
|
||||||
|
edges["topOp"] = i;
|
||||||
|
}
|
||||||
|
if (bb.x.max > bottomRight.x) {
|
||||||
|
bottomRight.x = bb.x.max;
|
||||||
|
edges["rightOp"] = i;
|
||||||
|
}
|
||||||
|
if (bb.y.max > bottomRight.y) {
|
||||||
|
bottomRight.y = bb.y.max;
|
||||||
|
edges["bottomOp"] = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (op.to) current = op.to;
|
if (op.to) current = op.to;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +173,13 @@ Path.prototype.boundary = function() {
|
||||||
this.topLeft = topLeft;
|
this.topLeft = topLeft;
|
||||||
this.bottomRight = bottomRight;
|
this.bottomRight = bottomRight;
|
||||||
|
|
||||||
|
for (let side of ["top", "left", "bottom", "right"]) {
|
||||||
|
let s = side + "Op";
|
||||||
|
this[s] = this.ops[edges[s]];
|
||||||
|
this[s].from =
|
||||||
|
this[s].type === "move" ? this[s].to : this.ops[edges[s] - 1].to;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -418,4 +450,74 @@ Path.prototype.reverse = function() {
|
||||||
return rev;
|
return rev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Returns a reversed version of this */
|
||||||
|
Path.prototype.edge = function(side) {
|
||||||
|
this.boundary();
|
||||||
|
if (side === "topLeft") return this.topLeft;
|
||||||
|
else if (side === "bottomRight") return this.bottomRight;
|
||||||
|
else if (side === "topRight")
|
||||||
|
return new Point(this.bottomRight.x, this.topLeft.y);
|
||||||
|
else if (side === "bottomLeft")
|
||||||
|
return new Point(this.topLeft.x, this.bottomRight.y);
|
||||||
|
else {
|
||||||
|
let s = side + "Op";
|
||||||
|
if (this[s].type === "move") return this[s].to;
|
||||||
|
else if (this[s].type === "line") {
|
||||||
|
if (side === "top") {
|
||||||
|
if (this.topOp.to.y < this.topOp.from.y) return this.topOp.to;
|
||||||
|
else return this.topOp.to;
|
||||||
|
} else if (side === "left") {
|
||||||
|
if (this.leftOp.to.x < this.leftOp.from.x) return this.leftOp.to;
|
||||||
|
else return this.leftOp.to;
|
||||||
|
} else if (side === "bottom") {
|
||||||
|
if (this.bottomOp.to.y > this.bottomOp.from.y) return this.bottomOp.to;
|
||||||
|
else return this.bottomOp.to;
|
||||||
|
} else if (side === "right") {
|
||||||
|
if (this.rightOp.to.x > this.rightOp.from.x) return this.rightOp.to;
|
||||||
|
else return this.rightOp.to;
|
||||||
|
}
|
||||||
|
} else if (this[s].type === "curve") {
|
||||||
|
let line;
|
||||||
|
if (side === "top")
|
||||||
|
line = {
|
||||||
|
p1: { x: this.topLeft.x, y: this.topLeft.y },
|
||||||
|
p2: { x: this.bottomRight.x, y: this.topLeft.y }
|
||||||
|
};
|
||||||
|
else if (side === "left")
|
||||||
|
line = {
|
||||||
|
p1: { x: this.topLeft.x, y: this.topLeft.y },
|
||||||
|
p2: { x: this.topLeft.x, y: this.bottomRight.y }
|
||||||
|
};
|
||||||
|
else if (side === "bottom")
|
||||||
|
line = {
|
||||||
|
p1: { x: this.topLeft.x, y: this.bottomRight.y },
|
||||||
|
p2: { x: this.bottomRight.x, y: this.bottomRight.y }
|
||||||
|
};
|
||||||
|
else if (side === "right")
|
||||||
|
line = {
|
||||||
|
p1: { x: this.bottomRight.x, y: this.topLeft.y },
|
||||||
|
p2: { x: this.bottomRight.x, y: this.bottomRight.y }
|
||||||
|
};
|
||||||
|
let bz = edgeCurveAsBezier(this[s]);
|
||||||
|
let isect = bz.intersects(line);
|
||||||
|
let edge = bz.get(isect[0]);
|
||||||
|
return new Point(edge.x, edge.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function edgeCurveAsBezier(op) {
|
||||||
|
return new Bezier(
|
||||||
|
{ x: op.from.x, y: op.from.y },
|
||||||
|
{ x: op.cp1.x, y: op.cp1.y },
|
||||||
|
{ x: op.cp2.x, y: op.cp2.y },
|
||||||
|
{ x: op.to.x, y: op.to.y }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
///* Returns the edge of a single path operation */
|
||||||
|
//function opEdge(op, side) {
|
||||||
|
// if(op.type === 'move' || op.type
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
export default Path;
|
export default Path;
|
||||||
|
|
|
@ -329,3 +329,69 @@ it("Should reverse a path", () => {
|
||||||
expect(rev.ops[1].type).to.equal("curve");
|
expect(rev.ops[1].type).to.equal("curve");
|
||||||
expect(rev.ops[2].type).to.equal("line");
|
expect(rev.ops[2].type).to.equal("line");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should find the edges of a path", () => {
|
||||||
|
let pattern = new freesewing.Pattern();
|
||||||
|
pattern.parts.a = new pattern.Part();
|
||||||
|
let a = pattern.parts.a;
|
||||||
|
a.points.A = new a.Point(45, 60);
|
||||||
|
a.points.B = new a.Point(10, 30);
|
||||||
|
a.points.BCp2 = new a.Point(40, 20);
|
||||||
|
a.points.C = new a.Point(90, 30);
|
||||||
|
a.points.CCp1 = new a.Point(50, -30);
|
||||||
|
a.points.D = new a.Point(-60, 90);
|
||||||
|
a.points.E = new a.Point(90, 190);
|
||||||
|
a.paths.test = new a.Path()
|
||||||
|
.move(a.points.A)
|
||||||
|
.line(a.points.B)
|
||||||
|
.curve(a.points.BCp2, a.points.CCp1, a.points.C)
|
||||||
|
.curve(a.points.E, a.points.D, a.points.A)
|
||||||
|
.close();
|
||||||
|
expect(round(a.paths.test.edge("topLeft").x)).to.equal(7.7);
|
||||||
|
expect(round(a.paths.test.edge("topLeft").y)).to.equal(0.97);
|
||||||
|
expect(round(a.paths.test.edge("bottomLeft").x)).to.equal(7.7);
|
||||||
|
expect(round(a.paths.test.edge("bottomLeft").y)).to.equal(118.46);
|
||||||
|
expect(round(a.paths.test.edge("bottomRight").x)).to.equal(90);
|
||||||
|
expect(round(a.paths.test.edge("bottomRight").y)).to.equal(118.46);
|
||||||
|
expect(round(a.paths.test.edge("topRight").x)).to.equal(90);
|
||||||
|
expect(round(a.paths.test.edge("topRight").y)).to.equal(0.97);
|
||||||
|
expect(round(a.paths.test.edge("left").x)).to.equal(7.7);
|
||||||
|
expect(round(a.paths.test.edge("left").y)).to.equal(91.7);
|
||||||
|
expect(round(a.paths.test.edge("bottom").x)).to.equal(40.75);
|
||||||
|
expect(round(a.paths.test.edge("bottom").y)).to.equal(118.46);
|
||||||
|
expect(round(a.paths.test.edge("right").x)).to.equal(90);
|
||||||
|
expect(round(a.paths.test.edge("right").y)).to.equal(30);
|
||||||
|
expect(round(a.paths.test.edge("top").x)).to.equal(55.97);
|
||||||
|
expect(round(a.paths.test.edge("top").y)).to.equal(0.97);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should find the edges of a path for corner cases", () => {
|
||||||
|
let pattern = new freesewing.Pattern();
|
||||||
|
pattern.parts.a = new pattern.Part();
|
||||||
|
let a = pattern.parts.a;
|
||||||
|
a.points.A = new a.Point(-45, -60);
|
||||||
|
a.points.B = new a.Point(45, 60);
|
||||||
|
a.points.C = new a.Point(-90, -160);
|
||||||
|
a.paths.test = new a.Path().move(a.points.A).line(a.points.B);
|
||||||
|
expect(round(a.paths.test.edge("top").x)).to.equal(-45);
|
||||||
|
expect(round(a.paths.test.edge("top").y)).to.equal(-60);
|
||||||
|
expect(round(a.paths.test.edge("left").x)).to.equal(-45);
|
||||||
|
expect(round(a.paths.test.edge("left").y)).to.equal(-60);
|
||||||
|
expect(round(a.paths.test.edge("bottom").x)).to.equal(45);
|
||||||
|
expect(round(a.paths.test.edge("bottom").y)).to.equal(60);
|
||||||
|
expect(round(a.paths.test.edge("right").x)).to.equal(45);
|
||||||
|
expect(round(a.paths.test.edge("right").y)).to.equal(60);
|
||||||
|
a.paths.test = new a.Path().move(a.points.B).line(a.points.A);
|
||||||
|
expect(round(a.paths.test.edge("top").x)).to.equal(-45);
|
||||||
|
expect(round(a.paths.test.edge("top").y)).to.equal(-60);
|
||||||
|
expect(round(a.paths.test.edge("left").x)).to.equal(-45);
|
||||||
|
expect(round(a.paths.test.edge("left").y)).to.equal(-60);
|
||||||
|
expect(round(a.paths.test.edge("bottom").x)).to.equal(45);
|
||||||
|
expect(round(a.paths.test.edge("bottom").y)).to.equal(60);
|
||||||
|
expect(round(a.paths.test.edge("right").x)).to.equal(45);
|
||||||
|
expect(round(a.paths.test.edge("right").y)).to.equal(60);
|
||||||
|
});
|
||||||
|
|
||||||
|
function round(value) {
|
||||||
|
return Math.round(value * 1e2) / 1e2;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue