106 lines
2.4 KiB
JavaScript
106 lines
2.4 KiB
JavaScript
import "../core/subclass";
|
|
import "geom";
|
|
|
|
d3.geom.polygon = function(coordinates) {
|
|
d3_subclass(coordinates, d3_geom_polygonPrototype);
|
|
return coordinates;
|
|
};
|
|
|
|
var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
|
|
|
|
d3_geom_polygonPrototype.area = function() {
|
|
var i = -1,
|
|
n = this.length,
|
|
a,
|
|
b = this[n - 1],
|
|
area = 0;
|
|
|
|
while (++i < n) {
|
|
a = b;
|
|
b = this[i];
|
|
area += a[1] * b[0] - a[0] * b[1];
|
|
}
|
|
|
|
return area * 0.5;
|
|
};
|
|
|
|
d3_geom_polygonPrototype.centroid = function(k) {
|
|
var i = -1,
|
|
n = this.length,
|
|
x = 0,
|
|
y = 0,
|
|
a,
|
|
b = this[n - 1],
|
|
c;
|
|
|
|
if (!arguments.length) k = -1 / (6 * this.area());
|
|
|
|
while (++i < n) {
|
|
a = b;
|
|
b = this[i];
|
|
c = a[0] * b[1] - b[0] * a[1];
|
|
x += (a[0] + b[0]) * c;
|
|
y += (a[1] + b[1]) * c;
|
|
}
|
|
|
|
return [x * k, y * k];
|
|
};
|
|
|
|
// The Sutherland-Hodgman clipping algorithm.
|
|
// Note: requires the clip polygon to be counterclockwise and convex.
|
|
d3_geom_polygonPrototype.clip = function(subject) {
|
|
var input,
|
|
closed = d3_geom_polygonClosed(subject),
|
|
i = -1,
|
|
n = this.length - d3_geom_polygonClosed(this),
|
|
j,
|
|
m,
|
|
a = this[n - 1],
|
|
b,
|
|
c,
|
|
d;
|
|
|
|
while (++i < n) {
|
|
input = subject.slice();
|
|
subject.length = 0;
|
|
b = this[i];
|
|
c = input[(m = input.length - closed) - 1];
|
|
j = -1;
|
|
while (++j < m) {
|
|
d = input[j];
|
|
if (d3_geom_polygonInside(d, a, b)) {
|
|
if (!d3_geom_polygonInside(c, a, b)) {
|
|
subject.push(d3_geom_polygonIntersect(c, d, a, b));
|
|
}
|
|
subject.push(d);
|
|
} else if (d3_geom_polygonInside(c, a, b)) {
|
|
subject.push(d3_geom_polygonIntersect(c, d, a, b));
|
|
}
|
|
c = d;
|
|
}
|
|
if (closed) subject.push(subject[0]);
|
|
a = b;
|
|
}
|
|
|
|
return subject;
|
|
};
|
|
|
|
function d3_geom_polygonInside(p, a, b) {
|
|
return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
|
|
}
|
|
|
|
// Intersect two infinite lines cd and ab.
|
|
function d3_geom_polygonIntersect(c, d, a, b) {
|
|
var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3,
|
|
y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3,
|
|
ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
|
|
return [x1 + ua * x21, y1 + ua * y21];
|
|
}
|
|
|
|
// Returns true if the polygon is closed.
|
|
function d3_geom_polygonClosed(coordinates) {
|
|
var a = coordinates[0],
|
|
b = coordinates[coordinates.length - 1];
|
|
return !(a[0] - b[0] || a[1] - b[1]);
|
|
}
|