Skip to content

Commit 7b1c410

Browse files
committed
Add d3.pathFixed. Fixes #10.
1 parent b2295e5 commit 7b1c410

3 files changed

Lines changed: 41 additions & 14 deletions

File tree

index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export {default as path} from "./src/path";
1+
export {default as path, pathFixed} from "./src/path";

src/path.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ function path() {
1515

1616
Path.prototype = path.prototype = {
1717
constructor: Path,
18+
_format: function(x) {
19+
return x;
20+
},
1821
moveTo: function(x, y) {
19-
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y);
22+
this._ += "M" + this._format(this._x0 = this._x1 = +x) + "," + this._format(this._y0 = this._y1 = +y);
2023
},
2124
closePath: function() {
2225
if (this._x1 !== null) {
@@ -25,13 +28,13 @@ Path.prototype = path.prototype = {
2528
}
2629
},
2730
lineTo: function(x, y) {
28-
this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y);
31+
this._ += "L" + this._format(this._x1 = +x) + "," + this._format(this._y1 = +y);
2932
},
3033
quadraticCurveTo: function(x1, y1, x, y) {
31-
this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
34+
this._ += "Q" + this._format(+x1) + "," + this._format(+y1) + "," + this._format(this._x1 = +x) + "," + this._format(this._y1 = +y);
3235
},
3336
bezierCurveTo: function(x1, y1, x2, y2, x, y) {
34-
this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y);
37+
this._ += "C" + this._format(+x1) + "," + this._format(+y1) + "," + this._format(+x2) + "," + this._format(+y2) + "," + this._format(this._x1 = +x) + "," + this._format(this._y1 = +y);
3538
},
3639
arcTo: function(x1, y1, x2, y2, r) {
3740
x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
@@ -48,7 +51,7 @@ Path.prototype = path.prototype = {
4851

4952
// Is this path empty? Move to (x1,y1).
5053
if (this._x1 === null) {
51-
this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1);
54+
this._ += "M" + this._format(this._x1 = x1) + "," + this._format(this._y1 = y1);
5255
}
5356

5457
// Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
@@ -58,7 +61,7 @@ Path.prototype = path.prototype = {
5861
// Equivalently, is (x1,y1) coincident with (x2,y2)?
5962
// Or, is the radius zero? Line to (x1,y1).
6063
else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
61-
this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1);
64+
this._ += "L" + this._format(this._x1 = x1) + "," + this._format(this._y1 = y1);
6265
}
6366

6467
// Otherwise, draw an arc!
@@ -75,10 +78,10 @@ Path.prototype = path.prototype = {
7578

7679
// If the start tangent is not coincident with (x0,y0), line to.
7780
if (Math.abs(t01 - 1) > epsilon) {
78-
this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01);
81+
this._ += "L" + this._format(x1 + t01 * x01) + "," + this._format(y1 + t01 * y01);
7982
}
8083

81-
this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21);
84+
this._ += "A" + this._format(r) + "," + this._format(r) + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + this._format(this._x1 = x1 + t21 * x21) + "," + this._format(this._y1 = y1 + t21 * y21);
8285
}
8386
},
8487
arc: function(x, y, r, a0, a1, ccw) {
@@ -95,34 +98,41 @@ Path.prototype = path.prototype = {
9598

9699
// Is this path empty? Move to (x0,y0).
97100
if (this._x1 === null) {
98-
this._ += "M" + x0 + "," + y0;
101+
this._ += "M" + this._format(x0) + "," + this._format(y0);
99102
}
100103

101104
// Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
102105
else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
103-
this._ += "L" + x0 + "," + y0;
106+
this._ += "L" + this._format(x0) + "," + this._format(y0);
104107
}
105108

106109
// Is this arc empty? We’re done.
107110
if (!r) return;
108111

109112
// Is this a complete circle? Draw two arcs to complete the circle.
110113
if (da > tauEpsilon) {
111-
this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0);
114+
this._ += "A" + this._format(r) + "," + this._format(r) + ",0,1," + cw + "," + this._format(x - dx) + "," + this._format(y - dy) + "A" + this._format(r) + "," + this._format(r) + ",0,1," + cw + "," + this._format(this._x1 = x0) + "," + this._format(this._y1 = y0);
112115
}
113116

114117
// Otherwise, draw an arc!
115118
else {
116119
if (da < 0) da = da % tau + tau;
117-
this._ += "A" + r + "," + r + ",0," + (+(da >= pi)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1));
120+
this._ += "A" + this._format(r) + "," + this._format(r) + ",0," + (+(da >= pi)) + "," + cw + "," + this._format(this._x1 = x + r * Math.cos(a1)) + "," + this._format(this._y1 = y + r * Math.sin(a1));
118121
}
119122
},
120123
rect: function(x, y, w, h) {
121-
this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z";
124+
this._ += "M" + this._format(this._x0 = this._x1 = +x) + "," + this._format(this._y0 = this._y1 = +y) + "h" + this._format(+w) + "v" + this._format(+h) + "h" + this._format(-w) + "Z";
122125
},
123126
toString: function() {
124127
return this._;
125128
}
126129
};
127130

128131
export default path;
132+
133+
export function pathFixed(digits) {
134+
var path = new Path;
135+
(digits = +digits).toFixed(digits); // Validate digits.
136+
path._format = function(x) { return +x.toFixed(digits); };
137+
return path;
138+
}

test/pathFixed-test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
var tape = require("tape"),
2+
path = require("../");
3+
4+
tape("pathFixed.moveTo(x, y) limits the precision of x and y", function(test) {
5+
var p = path.pathFixed(1);
6+
p.moveTo(123.456, 789.012);
7+
test.strictEqual(p + "", "M123.5,789");
8+
test.end();
9+
});
10+
11+
tape("pathFixed.lineTo(x, y) limits the precision of x and y", function(test) {
12+
var p = path.pathFixed(1);
13+
p.moveTo(0, 0);
14+
p.lineTo(123.456, 789.012);
15+
test.strictEqual(p + "", "M0,0L123.5,789");
16+
test.end();
17+
});

0 commit comments

Comments
 (0)