111 lines
2.2 KiB
JavaScript
111 lines
2.2 KiB
JavaScript
export default class PatternedLine {
|
|
constructor(pattern = null, phase = 0) {
|
|
this.pattern = pattern;
|
|
this.dw = pattern && pattern.partWidth;
|
|
this.points = [];
|
|
this.phase = phase;
|
|
this.x = null;
|
|
this.y = null;
|
|
this.disconnect = 0;
|
|
}
|
|
|
|
_nextDelta() {
|
|
return this.pattern.getDelta(this.phase ++);
|
|
}
|
|
|
|
_link() {
|
|
if(this.disconnect === 2) {
|
|
this.points.push(this.x + ' ' + this.y);
|
|
this.disconnect = 0;
|
|
}
|
|
}
|
|
|
|
cap() {
|
|
if(this.disconnect > 0) {
|
|
this.points.push(this.x + ' ' + this.y);
|
|
this.disconnect = 0;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
move(x, y) {
|
|
this.cap();
|
|
this.x = x;
|
|
this.y = y;
|
|
this.disconnect = 2;
|
|
return this;
|
|
}
|
|
|
|
line(x, y, {patterned = true} = {}) {
|
|
if(this.pattern && patterned) {
|
|
const len = Math.sqrt(
|
|
(x - this.x) * (x - this.x) +
|
|
(y - this.y) * (y - this.y)
|
|
);
|
|
const dx1 = (x - this.x) / len;
|
|
const dy1 = (y - this.y) / len;
|
|
const dx2 = -dy1;
|
|
const dy2 = dx1;
|
|
|
|
for(let pos = 0; pos + this.dw <= len; pos += this.dw) {
|
|
const delta = this._nextDelta();
|
|
this.points.push(
|
|
(this.x + pos * dx1 + delta * dx2) + ' ' +
|
|
(this.y + pos * dy1 + delta * dy2)
|
|
);
|
|
}
|
|
this.disconnect = 1;
|
|
} else {
|
|
this._link();
|
|
this.disconnect = 2;
|
|
}
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
|
|
arc(cx, cy, theta) {
|
|
const radius = Math.sqrt(
|
|
(cx - this.x) * (cx - this.x) +
|
|
(cy - this.y) * (cy - this.y)
|
|
);
|
|
const theta1 = Math.atan2(this.x - cx, cy - this.y);
|
|
const nextX = cx + Math.sin(theta1 + theta) * radius;
|
|
const nextY = cy - Math.cos(theta1 + theta) * radius;
|
|
|
|
if(this.pattern) {
|
|
const dir = (theta < 0 ? 1 : -1);
|
|
const dt = this.dw / radius;
|
|
|
|
for(let t = theta1; t + dt <= theta1 + theta; t += dt) {
|
|
const delta = this._nextDelta() * dir;
|
|
this.points.push(
|
|
(cx + Math.sin(t) * (radius + delta)) + ' ' +
|
|
(cy - Math.cos(t) * (radius + delta))
|
|
);
|
|
}
|
|
this.disconnect = 1;
|
|
} else {
|
|
this.points.push(
|
|
this.x + ' ' + this.y +
|
|
'A' + radius + ' ' + radius + ' 0 ' +
|
|
((Math.abs(theta) >= Math.PI) ? '1 ' : '0 ') +
|
|
((theta < 0) ? '0 ' : '1 ') +
|
|
nextX + ' ' + nextY
|
|
);
|
|
this.disconnect = 0;
|
|
}
|
|
|
|
this.x = nextX;
|
|
this.y = nextY;
|
|
|
|
return this;
|
|
}
|
|
|
|
asPath() {
|
|
this._link();
|
|
return 'M' + this.points.join('L');
|
|
}
|
|
}
|