✨ 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 topLeft = new Point(Infinity, Infinity);
|
||||
let bottomRight = new Point(-Infinity, -Infinity);
|
||||
let edges = [];
|
||||
for (let i in this.ops) {
|
||||
let op = this.ops[i];
|
||||
if (op.type === "move" || op.type === "line") {
|
||||
if (op.to.x < topLeft.x) topLeft.x = op.to.x;
|
||||
if (op.to.y < topLeft.y) topLeft.y = op.to.y;
|
||||
if (op.to.x > bottomRight.x) bottomRight.x = op.to.x;
|
||||
if (op.to.y > bottomRight.y) bottomRight.y = op.to.y;
|
||||
if (op.to.x < topLeft.x) {
|
||||
topLeft.x = op.to.x;
|
||||
edges["leftOp"] = i;
|
||||
}
|
||||
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") {
|
||||
let bb = new Bezier(
|
||||
{ x: current.x, y: current.y },
|
||||
|
@ -137,10 +150,22 @@ Path.prototype.boundary = function() {
|
|||
{ x: op.cp2.x, y: op.cp2.y },
|
||||
{ x: op.to.x, y: op.to.y }
|
||||
).bbox();
|
||||
if (bb.x.min < topLeft.x) topLeft.x = bb.x.min;
|
||||
if (bb.y.min < topLeft.y) topLeft.y = bb.y.min;
|
||||
if (bb.x.max > bottomRight.x) bottomRight.x = bb.x.max;
|
||||
if (bb.y.max > bottomRight.y) bottomRight.y = bb.y.max;
|
||||
if (bb.x.min < topLeft.x) {
|
||||
topLeft.x = bb.x.min;
|
||||
edges["leftOp"] = i;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -148,6 +173,13 @@ Path.prototype.boundary = function() {
|
|||
this.topLeft = topLeft;
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -418,4 +450,74 @@ Path.prototype.reverse = function() {
|
|||
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;
|
||||
|
|
|
@ -329,3 +329,69 @@ it("Should reverse a path", () => {
|
|||
expect(rev.ops[1].type).to.equal("curve");
|
||||
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