-
Notifications
You must be signed in to change notification settings - Fork 160
/
centroid.js
100 lines (85 loc) · 1.99 KB
/
centroid.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import {sqrt} from "../math.js";
// TODO Enforce positive area for exterior, negative area for interior?
var X0 = 0,
Y0 = 0,
Z0 = 0,
X1 = 0,
Y1 = 0,
Z1 = 0,
X2 = 0,
Y2 = 0,
Z2 = 0,
x00,
y00,
x0,
y0;
var centroidStream = {
point: centroidPoint,
lineStart: centroidLineStart,
lineEnd: centroidLineEnd,
polygonStart: function() {
centroidStream.lineStart = centroidRingStart;
centroidStream.lineEnd = centroidRingEnd;
},
polygonEnd: function() {
centroidStream.point = centroidPoint;
centroidStream.lineStart = centroidLineStart;
centroidStream.lineEnd = centroidLineEnd;
},
result: function() {
var centroid = Z2 ? [X2 / Z2, Y2 / Z2]
: Z1 ? [X1 / Z1, Y1 / Z1]
: Z0 ? [X0 / Z0, Y0 / Z0]
: [NaN, NaN];
X0 = Y0 = Z0 =
X1 = Y1 = Z1 =
X2 = Y2 = Z2 = 0;
return centroid;
}
};
function centroidPoint(x, y) {
X0 += x;
Y0 += y;
++Z0;
}
function centroidLineStart() {
centroidStream.point = centroidPointFirstLine;
}
function centroidPointFirstLine(x, y) {
centroidStream.point = centroidPointLine;
centroidPoint(x0 = x, y0 = y);
}
function centroidPointLine(x, y) {
var dx = x - x0, dy = y - y0, z = sqrt(dx * dx + dy * dy);
X1 += z * (x0 + x) / 2;
Y1 += z * (y0 + y) / 2;
Z1 += z;
centroidPoint(x0 = x, y0 = y);
}
function centroidLineEnd() {
centroidStream.point = centroidPoint;
}
function centroidRingStart() {
centroidStream.point = centroidPointFirstRing;
}
function centroidRingEnd() {
centroidPointRing(x00, y00);
}
function centroidPointFirstRing(x, y) {
centroidStream.point = centroidPointRing;
centroidPoint(x00 = x0 = x, y00 = y0 = y);
}
function centroidPointRing(x, y) {
var dx = x - x0,
dy = y - y0,
z = sqrt(dx * dx + dy * dy);
X1 += z * (x0 + x) / 2;
Y1 += z * (y0 + y) / 2;
Z1 += z;
z = y0 * x - x0 * y;
X2 += z * (x0 + x);
Y2 += z * (y0 + y);
Z2 += z * 3;
centroidPoint(x0 = x, y0 = y);
}
export default centroidStream;