More PatternedLine testing and fixes for minor quirks
This commit is contained in:
parent
4eb9ec21d6
commit
d1bab06bcc
|
@ -5229,26 +5229,24 @@ define('svg/PatternedLine',[],() => {
|
|||
this.phase = phase;
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.disconnect = false;
|
||||
}
|
||||
|
||||
_link() {
|
||||
if(this.disconnect) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = false;
|
||||
}
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
_nextDelta() {
|
||||
return this.pattern.getDelta(this.phase ++);
|
||||
}
|
||||
|
||||
cap() {
|
||||
if(this.x !== null) {
|
||||
_link() {
|
||||
if(this.disconnect === 2) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.disconnect = false;
|
||||
this.disconnect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cap() {
|
||||
if(this.disconnect > 0) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -5257,13 +5255,11 @@ define('svg/PatternedLine',[],() => {
|
|||
this.cap();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.disconnect = true;
|
||||
this.disconnect = 2;
|
||||
return this;
|
||||
}
|
||||
|
||||
line(x, y) {
|
||||
this._link();
|
||||
|
||||
if(this.pattern) {
|
||||
const len = Math.sqrt(
|
||||
(x - this.x) * (x - this.x) +
|
||||
|
@ -5281,8 +5277,10 @@ define('svg/PatternedLine',[],() => {
|
|||
(this.y + pos * dy1 + delta * dy2)
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this.disconnect = true;
|
||||
this._link();
|
||||
this.disconnect = 2;
|
||||
}
|
||||
|
||||
this.x = x;
|
||||
|
@ -5291,15 +5289,13 @@ define('svg/PatternedLine',[],() => {
|
|||
}
|
||||
|
||||
arc(cx, cy, theta) {
|
||||
this._link();
|
||||
|
||||
const radius = Math.sqrt(
|
||||
(cx - this.x) * (cx - this.x) +
|
||||
(cy - this.y) * (cy - this.y)
|
||||
);
|
||||
const theta1 = Math.atan2(cx - this.x, cy - this.y);
|
||||
this.x = cx + Math.sin(theta1 + theta) * radius;
|
||||
this.y = cy - Math.cos(theta1 + theta) * radius;
|
||||
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);
|
||||
|
@ -5312,17 +5308,21 @@ define('svg/PatternedLine',[],() => {
|
|||
(cy - Math.cos(t) * (radius + delta))
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this.points.push(
|
||||
(cx + Math.sin(theta1) * radius) + ' ' +
|
||||
(cy - Math.cos(theta1) * radius) +
|
||||
this.x + ' ' + this.y +
|
||||
'A' + radius + ' ' + radius + ' 0 ' +
|
||||
((theta < 0) ? '0 ' : '1 ') +
|
||||
'1 ' +
|
||||
this.x + ' ' + this.y
|
||||
nextX + ' ' + nextY
|
||||
);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
this.x = nextX;
|
||||
this.y = nextY;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -9,26 +9,24 @@ define(() => {
|
|||
this.phase = phase;
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.disconnect = false;
|
||||
}
|
||||
|
||||
_link() {
|
||||
if(this.disconnect) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = false;
|
||||
}
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
_nextDelta() {
|
||||
return this.pattern.getDelta(this.phase ++);
|
||||
}
|
||||
|
||||
cap() {
|
||||
if(this.x !== null) {
|
||||
_link() {
|
||||
if(this.disconnect === 2) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.x = null;
|
||||
this.y = null;
|
||||
this.disconnect = false;
|
||||
this.disconnect = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cap() {
|
||||
if(this.disconnect > 0) {
|
||||
this.points.push(this.x + ' ' + this.y);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -37,13 +35,11 @@ define(() => {
|
|||
this.cap();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.disconnect = true;
|
||||
this.disconnect = 2;
|
||||
return this;
|
||||
}
|
||||
|
||||
line(x, y) {
|
||||
this._link();
|
||||
|
||||
if(this.pattern) {
|
||||
const len = Math.sqrt(
|
||||
(x - this.x) * (x - this.x) +
|
||||
|
@ -61,8 +57,10 @@ define(() => {
|
|||
(this.y + pos * dy1 + delta * dy2)
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this.disconnect = true;
|
||||
this._link();
|
||||
this.disconnect = 2;
|
||||
}
|
||||
|
||||
this.x = x;
|
||||
|
@ -71,15 +69,13 @@ define(() => {
|
|||
}
|
||||
|
||||
arc(cx, cy, theta) {
|
||||
this._link();
|
||||
|
||||
const radius = Math.sqrt(
|
||||
(cx - this.x) * (cx - this.x) +
|
||||
(cy - this.y) * (cy - this.y)
|
||||
);
|
||||
const theta1 = Math.atan2(cx - this.x, cy - this.y);
|
||||
this.x = cx + Math.sin(theta1 + theta) * radius;
|
||||
this.y = cy - Math.cos(theta1 + theta) * radius;
|
||||
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);
|
||||
|
@ -92,17 +88,21 @@ define(() => {
|
|||
(cy - Math.cos(t) * (radius + delta))
|
||||
);
|
||||
}
|
||||
this.disconnect = 1;
|
||||
} else {
|
||||
this.points.push(
|
||||
(cx + Math.sin(theta1) * radius) + ' ' +
|
||||
(cy - Math.cos(theta1) * radius) +
|
||||
this.x + ' ' + this.y +
|
||||
'A' + radius + ' ' + radius + ' 0 ' +
|
||||
((theta < 0) ? '0 ' : '1 ') +
|
||||
'1 ' +
|
||||
this.x + ' ' + this.y
|
||||
nextX + ' ' + nextY
|
||||
);
|
||||
this.disconnect = 0;
|
||||
}
|
||||
|
||||
this.x = nextX;
|
||||
this.y = nextY;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
defineDescribe('PatternedLine', ['./PatternedLine'], (PatternedLine) => {
|
||||
'use strict';
|
||||
|
||||
function simplify(path, dp) {
|
||||
return path.replace(/[0-9.]+/g, (v) => Number(v).toFixed(dp));
|
||||
}
|
||||
|
||||
describe('unpatterned', () => {
|
||||
describe('line', () => {
|
||||
it('connects points with lines', () => {
|
||||
it('connects points with simple lines', () => {
|
||||
const ln = new PatternedLine()
|
||||
.move(10, 20)
|
||||
.line(30, 50)
|
||||
.line(1, 2)
|
||||
.cap();
|
||||
.line(1, 2);
|
||||
|
||||
expect(ln.asPath()).toEqual(
|
||||
'M10 20' +
|
||||
|
@ -16,6 +18,133 @@ defineDescribe('PatternedLine', ['./PatternedLine'], (PatternedLine) => {
|
|||
'L1 2'
|
||||
);
|
||||
});
|
||||
|
||||
it('supports simple (circular) arcs', () => {
|
||||
const ln = new PatternedLine()
|
||||
.move(10, 20)
|
||||
.arc(10, 30, Math.PI);
|
||||
|
||||
expect(simplify(ln.asPath(), 0)).toEqual(
|
||||
'M10 20' +
|
||||
'A10 10 0 1 1 10 40'
|
||||
);
|
||||
});
|
||||
|
||||
it('can combine lines and arcs', () => {
|
||||
const ln = new PatternedLine()
|
||||
.move(10, 20)
|
||||
.line(20, 20)
|
||||
.arc(20, 30, Math.PI)
|
||||
.line(10, 40);
|
||||
|
||||
expect(simplify(ln.asPath(), 0)).toEqual(
|
||||
'M10 20' +
|
||||
'L20 20' +
|
||||
'A10 10 0 1 1 20 40' +
|
||||
'L10 40'
|
||||
);
|
||||
});
|
||||
|
||||
it('ignores cap()', () => {
|
||||
const ln1 = new PatternedLine()
|
||||
.move(10, 20)
|
||||
.line(10, 40)
|
||||
.cap();
|
||||
|
||||
expect(ln1.asPath()).toEqual(
|
||||
'M10 20' +
|
||||
'L10 40'
|
||||
);
|
||||
|
||||
const ln2 = new PatternedLine()
|
||||
.move(10, 20)
|
||||
.arc(10, 30, Math.PI)
|
||||
.cap();
|
||||
|
||||
expect(simplify(ln2.asPath(), 0)).toEqual(
|
||||
'M10 20' +
|
||||
'A10 10 0 1 1 10 40'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('patterned', () => {
|
||||
const patternDeltas = [-1, 1, -2];
|
||||
const pattern = {
|
||||
partWidth: 5,
|
||||
getDelta: (p) => {
|
||||
return patternDeltas[p % 3];
|
||||
},
|
||||
};
|
||||
|
||||
it('draws lines using the given pattern', () => {
|
||||
const ln = new PatternedLine(pattern)
|
||||
.move(10, 20)
|
||||
.line(30, 20);
|
||||
|
||||
// last segment of line is not rendered to avoid high frequencies
|
||||
// near line segment joins
|
||||
expect(ln.asPath()).toEqual(
|
||||
'M10 19' +
|
||||
'L15 21' +
|
||||
'L20 18' +
|
||||
'L25 19'
|
||||
);
|
||||
});
|
||||
|
||||
it('maintains phase between line segments', () => {
|
||||
const ln = new PatternedLine(pattern)
|
||||
.move(10, 20)
|
||||
.line(30, 20)
|
||||
.line(30, 33);
|
||||
|
||||
expect(ln.asPath()).toEqual(
|
||||
'M10 19' +
|
||||
'L15 21' +
|
||||
'L20 18' +
|
||||
'L25 19' +
|
||||
|
||||
'L29 20' +
|
||||
'L32 25'
|
||||
);
|
||||
});
|
||||
|
||||
it('completes the line beyond the pattern with cap()', () => {
|
||||
const ln = new PatternedLine(pattern)
|
||||
.move(10, 20)
|
||||
.line(30, 20)
|
||||
.line(30, 33)
|
||||
.cap();
|
||||
|
||||
expect(ln.asPath()).toEqual(
|
||||
'M10 19' +
|
||||
'L15 21' +
|
||||
'L20 18' +
|
||||
'L25 19' +
|
||||
|
||||
'L29 20' +
|
||||
'L32 25' +
|
||||
'L30 33'
|
||||
);
|
||||
});
|
||||
|
||||
it('supports simple (circular) arcs using straight segments', () => {
|
||||
const ln = new PatternedLine(pattern)
|
||||
.move(10, 20)
|
||||
.arc(10, 30, Math.PI)
|
||||
.line(0, 40);
|
||||
|
||||
expect(simplify(ln.asPath(), 1)).toEqual(
|
||||
'M10.0 19.0' +
|
||||
'L14.3 22.1' +
|
||||
'L20.1 23.5' +
|
||||
'L21.0 29.2' +
|
||||
'L18.2 33.7' +
|
||||
'L17.2 39.6' +
|
||||
'L10.0 41.0' +
|
||||
'L5.0 39.0'
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue