source: node_modules/d3-geo/src/centroid.js@ a762898

Last change on this file since a762898 was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 3.8 KB
RevLine 
[e4c61dd]1import {Adder} from "d3-array";
2import {asin, atan2, cos, degrees, epsilon, epsilon2, hypot, radians, sin, sqrt} from "./math.js";
3import noop from "./noop.js";
4import stream from "./stream.js";
5
6var W0, W1,
7 X0, Y0, Z0,
8 X1, Y1, Z1,
9 X2, Y2, Z2,
10 lambda00, phi00, // first point
11 x0, y0, z0; // previous point
12
13var centroidStream = {
14 sphere: noop,
15 point: centroidPoint,
16 lineStart: centroidLineStart,
17 lineEnd: centroidLineEnd,
18 polygonStart: function() {
19 centroidStream.lineStart = centroidRingStart;
20 centroidStream.lineEnd = centroidRingEnd;
21 },
22 polygonEnd: function() {
23 centroidStream.lineStart = centroidLineStart;
24 centroidStream.lineEnd = centroidLineEnd;
25 }
26};
27
28// Arithmetic mean of Cartesian vectors.
29function centroidPoint(lambda, phi) {
30 lambda *= radians, phi *= radians;
31 var cosPhi = cos(phi);
32 centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi));
33}
34
35function centroidPointCartesian(x, y, z) {
36 ++W0;
37 X0 += (x - X0) / W0;
38 Y0 += (y - Y0) / W0;
39 Z0 += (z - Z0) / W0;
40}
41
42function centroidLineStart() {
43 centroidStream.point = centroidLinePointFirst;
44}
45
46function centroidLinePointFirst(lambda, phi) {
47 lambda *= radians, phi *= radians;
48 var cosPhi = cos(phi);
49 x0 = cosPhi * cos(lambda);
50 y0 = cosPhi * sin(lambda);
51 z0 = sin(phi);
52 centroidStream.point = centroidLinePoint;
53 centroidPointCartesian(x0, y0, z0);
54}
55
56function centroidLinePoint(lambda, phi) {
57 lambda *= radians, phi *= radians;
58 var cosPhi = cos(phi),
59 x = cosPhi * cos(lambda),
60 y = cosPhi * sin(lambda),
61 z = sin(phi),
62 w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
63 W1 += w;
64 X1 += w * (x0 + (x0 = x));
65 Y1 += w * (y0 + (y0 = y));
66 Z1 += w * (z0 + (z0 = z));
67 centroidPointCartesian(x0, y0, z0);
68}
69
70function centroidLineEnd() {
71 centroidStream.point = centroidPoint;
72}
73
74// See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
75// J. Applied Mechanics 42, 239 (1975).
76function centroidRingStart() {
77 centroidStream.point = centroidRingPointFirst;
78}
79
80function centroidRingEnd() {
81 centroidRingPoint(lambda00, phi00);
82 centroidStream.point = centroidPoint;
83}
84
85function centroidRingPointFirst(lambda, phi) {
86 lambda00 = lambda, phi00 = phi;
87 lambda *= radians, phi *= radians;
88 centroidStream.point = centroidRingPoint;
89 var cosPhi = cos(phi);
90 x0 = cosPhi * cos(lambda);
91 y0 = cosPhi * sin(lambda);
92 z0 = sin(phi);
93 centroidPointCartesian(x0, y0, z0);
94}
95
96function centroidRingPoint(lambda, phi) {
97 lambda *= radians, phi *= radians;
98 var cosPhi = cos(phi),
99 x = cosPhi * cos(lambda),
100 y = cosPhi * sin(lambda),
101 z = sin(phi),
102 cx = y0 * z - z0 * y,
103 cy = z0 * x - x0 * z,
104 cz = x0 * y - y0 * x,
105 m = hypot(cx, cy, cz),
106 w = asin(m), // line weight = angle
107 v = m && -w / m; // area weight multiplier
108 X2.add(v * cx);
109 Y2.add(v * cy);
110 Z2.add(v * cz);
111 W1 += w;
112 X1 += w * (x0 + (x0 = x));
113 Y1 += w * (y0 + (y0 = y));
114 Z1 += w * (z0 + (z0 = z));
115 centroidPointCartesian(x0, y0, z0);
116}
117
118export default function(object) {
119 W0 = W1 =
120 X0 = Y0 = Z0 =
121 X1 = Y1 = Z1 = 0;
122 X2 = new Adder();
123 Y2 = new Adder();
124 Z2 = new Adder();
125 stream(object, centroidStream);
126
127 var x = +X2,
128 y = +Y2,
129 z = +Z2,
130 m = hypot(x, y, z);
131
132 // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
133 if (m < epsilon2) {
134 x = X1, y = Y1, z = Z1;
135 // If the feature has zero length, fall back to arithmetic mean of point vectors.
136 if (W1 < epsilon) x = X0, y = Y0, z = Z0;
137 m = hypot(x, y, z);
138 // If the feature still has an undefined ccentroid, then return.
139 if (m < epsilon2) return [NaN, NaN];
140 }
141
142 return [atan2(y, x) * degrees, asin(z / m) * degrees];
143}
Note: See TracBrowser for help on using the repository browser.