UNPKG

9.15 kBJavaScriptView Raw
1/**
2 * @copyright 2013 Sonia Keys
3 * @copyright 2016 commenthol
4 * @license MIT
5 * @module sundial
6 */
7/**
8 * Sundial: Chapter 58, Calculation of a Planar Sundial.
9 */
10
11import base from './base';
12
13/**
14 * Point return type represents a point to be used in constructing the sundial.
15 */
16function Point(x, y) {
17 this.x = x || 0;
18 this.y = y || 0;
19}
20
21/**
22 * Line holds data to draw an hour line on the sundial.
23 */
24function Line(hour, points) {
25 this.hour = hour; // 0 to 24
26 this.points = points || []; // One or more points corresponding to the hour.
27}
28
29var m = [-23.44, -20.15, -11.47, 0, 11.47, 20.15, 23.44];
30
31/**
32 * General computes data for the general case of a planar sundial.
33 *
34 * Argument φ is geographic latitude at which the sundial will be located.
35 * D is gnomonic declination, the azimuth of the perpendicular to the plane
36 * of the sundial, measured from the southern meridian towards the west.
37 * Argument a is the length of a straight stylus perpendicular to the plane
38 * of the sundial, z is zenithal distance of the direction defined by the
39 * stylus. Angles φ, D, and z are in radians. Units of stylus length a
40 * are arbitrary.
41 *
42 * Results consist of a set of lines, a center point, u, the length of a
43 * polar stylus, and ψ, the angle which the polar stylus makes with the plane
44 * of the sundial. The center point, the points defining the hour lines, and
45 * u are in units of a, the stylus length. ψ is in radians.
46 */
47export function general(φ, D, a, z) {
48 // (φ, D, a, z float64) (lines []Line, center Point, u, ψ float64)
49 var _base$sincos = base.sincos(φ),
50 sφ = _base$sincos[0],
51 cφ = _base$sincos[1];
52
53 var tφ = sφ / cφ;
54
55 var _base$sincos2 = base.sincos(D),
56 sD = _base$sincos2[0],
57 cD = _base$sincos2[1];
58
59 var _base$sincos3 = base.sincos(z),
60 sz = _base$sincos3[0],
61 cz = _base$sincos3[1];
62
63 var P = sφ * cz - cφ * sz * cD;
64 var lines = [];
65 for (var i = 0; i < 24; i++) {
66 var l = new Line(i);
67 var H = (i - 12) * 15 * Math.PI / 180;
68 var aH = Math.abs(H);
69
70 var _base$sincos4 = base.sincos(H),
71 sH = _base$sincos4[0],
72 cH = _base$sincos4[1];
73
74 for (var _iterator = m, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
75 var _ref;
76
77 if (_isArray) {
78 if (_i >= _iterator.length) break;
79 _ref = _iterator[_i++];
80 } else {
81 _i = _iterator.next();
82 if (_i.done) break;
83 _ref = _i.value;
84 }
85
86 var d = _ref;
87
88 var tδ = Math.tan(d * Math.PI / 180);
89 var H0 = Math.acos(-tφ * tδ);
90 if (aH > H0) {
91 continue; // sun below horizon
92 }
93 var Q = sD * sz * sH + (cφ * cz + sφ * sz * cD) * cH + P * tδ;
94 if (Q < 0) {
95 continue; // sun below plane of sundial
96 }
97 var Nx = cD * sH - sD * (sφ * cH - cφ * tδ);
98 var Ny = cz * sD * sH - (cφ * sz - sφ * cz * cD) * cH - (sφ * sz + cφ * cz * cD) * tδ;
99 l.points.push(new Point(a * Nx / Q, a * Ny / Q));
100 }
101 if (l.points.length > 0) {
102 lines.push(l);
103 }
104 }
105 var center = new Point();
106 center.x = a / P * cφ * sD;
107 center.y = -a / P * (sφ * sz + cφ * cz * cD);
108 var aP = Math.abs(P);
109 var u = a / aP;
110 var ψ = Math.asin(aP);
111 return {
112 lines: lines,
113 center: center,
114 length: u,
115 angle: ψ
116 };
117}
118
119/**
120 * Equatorial computes data for a sundial level with the equator.
121 *
122 * Argument φ is geographic latitude at which the sundial will be located;
123 * a is the length of a straight stylus perpendicular to the plane of the
124 * sundial.
125 *
126 * The sundial will have two sides, north and south. Results n and s define
127 * lines on the north and south sides of the sundial. Result coordinates
128 * are in units of a, the stylus length.
129 */
130export function equatorial(φ, a) {
131 // (φ, a float64) (n, s []Line)
132 var tφ = Math.tan(φ);
133 var n = [];
134 var s = [];
135 for (var i = 0; i < 24; i++) {
136 var nl = new Line(i);
137 var sl = new Line(i);
138 var H = (i - 12) * 15 * Math.PI / 180;
139 var aH = Math.abs(H);
140
141 var _base$sincos5 = base.sincos(H),
142 sH = _base$sincos5[0],
143 cH = _base$sincos5[1];
144
145 for (var _iterator2 = m, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
146 var _ref2;
147
148 if (_isArray2) {
149 if (_i2 >= _iterator2.length) break;
150 _ref2 = _iterator2[_i2++];
151 } else {
152 _i2 = _iterator2.next();
153 if (_i2.done) break;
154 _ref2 = _i2.value;
155 }
156
157 var d = _ref2;
158
159 var tδ = Math.tan(d * Math.PI / 180);
160 var H0 = Math.acos(-tφ * tδ);
161 if (aH > H0) {
162 continue;
163 }
164 var x = -a * sH / tδ;
165 var yy = a * cH / tδ;
166 if (tδ < 0) {
167 sl.points.push(new Point(x, yy));
168 } else {
169 nl.points.push(new Point(x, -yy));
170 }
171 }
172 if (nl.points.length > 0) {
173 n.push(nl);
174 }
175 if (sl.points.length > 0) {
176 s.push(sl);
177 }
178 }
179 return {
180 north: n,
181 south: s
182 };
183}
184
185/**
186 * Horizontal computes data for a horizontal sundial.
187 *
188 * Argument φ is geographic latitude at which the sundial will be located,
189 * a is the length of a straight stylus perpendicular to the plane of the
190 * sundial.
191 *
192 * Results consist of a set of lines, a center point, and u, the length of a
193 * polar stylus. They are in units of a, the stylus length.
194 */
195export function horizontal(φ, a) {
196 // (φ, a float64) (lines []Line, center Point, u float64)
197 var _base$sincos6 = base.sincos(φ),
198 sφ = _base$sincos6[0],
199 cφ = _base$sincos6[1];
200
201 var tφ = sφ / cφ;
202 var lines = [];
203 for (var i = 0; i < 24; i++) {
204 var l = new Line(i);
205 var H = (i - 12) * 15 * Math.PI / 180;
206 var aH = Math.abs(H);
207
208 var _base$sincos7 = base.sincos(H),
209 sH = _base$sincos7[0],
210 cH = _base$sincos7[1];
211
212 for (var _iterator3 = m, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
213 var _ref3;
214
215 if (_isArray3) {
216 if (_i3 >= _iterator3.length) break;
217 _ref3 = _iterator3[_i3++];
218 } else {
219 _i3 = _iterator3.next();
220 if (_i3.done) break;
221 _ref3 = _i3.value;
222 }
223
224 var d = _ref3;
225
226 var tδ = Math.tan(d * Math.PI / 180);
227 var H0 = Math.acos(-tφ * tδ);
228 if (aH > H0) {
229 continue; // sun below horizon
230 }
231 var Q = cφ * cH + sφ * tδ;
232 var x = a * sH / Q;
233 var y = a * (sφ * cH - cφ * tδ) / Q;
234 l.points.push(new Point(x, y));
235 }
236 if (l.points.length > 0) {
237 lines.push(l);
238 }
239 }
240 var center = new Point(0, -a / tφ);
241 var u = a / Math.abs(sφ);
242 return {
243 lines: lines,
244 center: center,
245 length: u
246 };
247}
248
249/**
250 * Vertical computes data for a vertical sundial.
251 *
252 * Argument φ is geographic latitude at which the sundial will be located.
253 * D is gnomonic declination, the azimuth of the perpendicular to the plane
254 * of the sundial, measured from the southern meridian towards the west.
255 * Argument a is the length of a straight stylus perpendicular to the plane
256 * of the sundial.
257 *
258 * Results consist of a set of lines, a center point, and u, the length of a
259 * polar stylus. They are in units of a, the stylus length.
260 */
261export function vertical(φ, D, a) {
262 // (φ, D, a float64) (lines []Line, center Point, u float64)
263 var _base$sincos8 = base.sincos(φ),
264 sφ = _base$sincos8[0],
265 cφ = _base$sincos8[1];
266
267 var tφ = sφ / cφ;
268
269 var _base$sincos9 = base.sincos(D),
270 sD = _base$sincos9[0],
271 cD = _base$sincos9[1];
272
273 var lines = [];
274 for (var i = 0; i < 24; i++) {
275 var l = new Line(i);
276 var H = (i - 12) * 15 * Math.PI / 180;
277 var aH = Math.abs(H);
278
279 var _base$sincos10 = base.sincos(H),
280 sH = _base$sincos10[0],
281 cH = _base$sincos10[1];
282
283 for (var _iterator4 = m, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {
284 var _ref4;
285
286 if (_isArray4) {
287 if (_i4 >= _iterator4.length) break;
288 _ref4 = _iterator4[_i4++];
289 } else {
290 _i4 = _iterator4.next();
291 if (_i4.done) break;
292 _ref4 = _i4.value;
293 }
294
295 var d = _ref4;
296
297 var tδ = Math.tan(d * Math.PI / 180);
298 var H0 = Math.acos(-tφ * tδ);
299 if (aH > H0) {
300 continue; // sun below horizon
301 }
302 var Q = sD * sH + sφ * cD * cH - cφ * cD * tδ;
303 if (Q < 0) {
304 continue; // sun below plane of sundial
305 }
306 var x = a * (cD * sH - sφ * sD * cH + cφ * sD * tδ) / Q;
307 var y = -a * (cφ * cH + sφ * tδ) / Q;
308 l.points.push(new Point(x, y));
309 }
310 if (l.points.length > 0) {
311 lines.push(l);
312 }
313 }
314 var center = new Point();
315 center.x = -a * sD / cD;
316 center.y = a * tφ / cD;
317 var u = a / Math.abs(cφ * cD);
318 return {
319 lines: lines,
320 center: center,
321 length: u
322 };
323}
324
325export default {
326 general: general,
327 equatorial: equatorial,
328 horizontal: horizontal,
329 vertical: vertical
330};
\No newline at end of file