'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var base = require('./base.cjs'); /** * @copyright 2013 Sonia Keys * @copyright 2016 commenthol * @license MIT * @module sundial */ /** * Point return type represents a point to be used in constructing the sundial. */ function Point (x, y) { this.x = x || 0; this.y = y || 0; } /** * Line holds data to draw an hour line on the sundial. */ function Line (hour, points) { this.hour = hour; // 0 to 24 this.points = points || []; // One or more points corresponding to the hour. } const m = [-23.44, -20.15, -11.47, 0, 11.47, 20.15, 23.44]; /** * General computes data for the general case of a planar sundial. * * Argument φ is geographic latitude at which the sundial will be located. * D is gnomonic declination, the azimuth of the perpendicular to the plane * of the sundial, measured from the southern meridian towards the west. * Argument a is the length of a straight stylus perpendicular to the plane * of the sundial, z is zenithal distance of the direction defined by the * stylus. Angles φ, D, and z are in radians. Units of stylus length a * are arbitrary. * * Results consist of a set of lines, a center point, u, the length of a * polar stylus, and ψ, the angle which the polar stylus makes with the plane * of the sundial. The center point, the points defining the hour lines, and * u are in units of a, the stylus length. ψ is in radians. */ function general (φ, D, a, z) { // (φ, D, a, z float64) (lines []Line, center Point, u, ψ float64) const [sφ, cφ] = base["default"].sincos(φ); const tφ = sφ / cφ; const [sD, cD] = base["default"].sincos(D); const [sz, cz] = base["default"].sincos(z); const P = sφ * cz - cφ * sz * cD; const lines = []; for (let i = 0; i < 24; i++) { const l = new Line(i); const H = (i - 12) * 15 * Math.PI / 180; const aH = Math.abs(H); const [sH, cH] = base["default"].sincos(H); for (const d of m) { const tδ = Math.tan(d * Math.PI / 180); const H0 = Math.acos(-tφ * tδ); if (aH > H0) { continue // sun below horizon } const Q = sD * sz * sH + (cφ * cz + sφ * sz * cD) * cH + P * tδ; if (Q < 0) { continue // sun below plane of sundial } const Nx = cD * sH - sD * (sφ * cH - cφ * tδ); const Ny = cz * sD * sH - (cφ * sz - sφ * cz * cD) * cH - (sφ * sz + cφ * cz * cD) * tδ; l.points.push(new Point(a * Nx / Q, a * Ny / Q)); } if (l.points.length > 0) { lines.push(l); } } const center = new Point(); center.x = a / P * cφ * sD; center.y = -a / P * (sφ * sz + cφ * cz * cD); const aP = Math.abs(P); const u = a / aP; const ψ = Math.asin(aP); return { lines, center, length: u, angle: ψ } } /** * Equatorial computes data for a sundial level with the equator. * * Argument φ is geographic latitude at which the sundial will be located; * a is the length of a straight stylus perpendicular to the plane of the * sundial. * * The sundial will have two sides, north and south. Results n and s define * lines on the north and south sides of the sundial. Result coordinates * are in units of a, the stylus length. */ function equatorial (φ, a) { // (φ, a float64) (n, s []Line) const tφ = Math.tan(φ); const n = []; const s = []; for (let i = 0; i < 24; i++) { const nl = new Line(i); const sl = new Line(i); const H = (i - 12) * 15 * Math.PI / 180; const aH = Math.abs(H); const [sH, cH] = base["default"].sincos(H); for (const d of m) { const tδ = Math.tan(d * Math.PI / 180); const H0 = Math.acos(-tφ * tδ); if (aH > H0) { continue } const x = -a * sH / tδ; const yy = a * cH / tδ; if (tδ < 0) { sl.points.push(new Point(x, yy)); } else { nl.points.push(new Point(x, -yy)); } } if (nl.points.length > 0) { n.push(nl); } if (sl.points.length > 0) { s.push(sl); } } return { north: n, south: s } } /** * Horizontal computes data for a horizontal sundial. * * Argument φ is geographic latitude at which the sundial will be located, * a is the length of a straight stylus perpendicular to the plane of the * sundial. * * Results consist of a set of lines, a center point, and u, the length of a * polar stylus. They are in units of a, the stylus length. */ function horizontal (φ, a) { // (φ, a float64) (lines []Line, center Point, u float64) const [sφ, cφ] = base["default"].sincos(φ); const tφ = sφ / cφ; const lines = []; for (let i = 0; i < 24; i++) { const l = new Line(i); const H = (i - 12) * 15 * Math.PI / 180; const aH = Math.abs(H); const [sH, cH] = base["default"].sincos(H); for (const d of m) { const tδ = Math.tan(d * Math.PI / 180); const H0 = Math.acos(-tφ * tδ); if (aH > H0) { continue // sun below horizon } const Q = cφ * cH + sφ * tδ; const x = a * sH / Q; const y = a * (sφ * cH - cφ * tδ) / Q; l.points.push(new Point(x, y)); } if (l.points.length > 0) { lines.push(l); } } const center = new Point(0, -a / tφ); const u = a / Math.abs(sφ); return { lines, center, length: u } } /** * Vertical computes data for a vertical sundial. * * Argument φ is geographic latitude at which the sundial will be located. * D is gnomonic declination, the azimuth of the perpendicular to the plane * of the sundial, measured from the southern meridian towards the west. * Argument a is the length of a straight stylus perpendicular to the plane * of the sundial. * * Results consist of a set of lines, a center point, and u, the length of a * polar stylus. They are in units of a, the stylus length. */ function vertical (φ, D, a) { // (φ, D, a float64) (lines []Line, center Point, u float64) const [sφ, cφ] = base["default"].sincos(φ); const tφ = sφ / cφ; const [sD, cD] = base["default"].sincos(D); const lines = []; for (let i = 0; i < 24; i++) { const l = new Line(i); const H = (i - 12) * 15 * Math.PI / 180; const aH = Math.abs(H); const [sH, cH] = base["default"].sincos(H); for (const d of m) { const tδ = Math.tan(d * Math.PI / 180); const H0 = Math.acos(-tφ * tδ); if (aH > H0) { continue // sun below horizon } const Q = sD * sH + sφ * cD * cH - cφ * cD * tδ; if (Q < 0) { continue // sun below plane of sundial } const x = a * (cD * sH - sφ * sD * cH + cφ * sD * tδ) / Q; const y = -a * (cφ * cH + sφ * tδ) / Q; l.points.push(new Point(x, y)); } if (l.points.length > 0) { lines.push(l); } } const center = new Point(); center.x = -a * sD / cD; center.y = a * tφ / cD; const u = a / Math.abs(cφ * cD); return { lines, center, length: u } } var sundial = { general, equatorial, horizontal, vertical }; exports["default"] = sundial; exports.equatorial = equatorial; exports.general = general; exports.horizontal = horizontal; exports.vertical = vertical;