Published
Edited
Dec 29, 2020
Fork of Star map
5 forks
Importers
44 stars
Insert cell
Insert cell
Insert cell
Insert cell
λo = 13.2322 // observer’s longitude (degrees)
Insert cell
φo = 56.0881 // observer’s latitude (degrees)
Insert cell
chart.update(date)
Insert cell
Insert cell
function solarMeanLongitude(t) { // L_0 (25.2)
return 280.46646 + t * (36000.76983 + t * 0.0003032);
}
Insert cell
function solarMeanAnomaly(t) { // M (25.3)
return 357.52911 + t * (35999.05029 + t * -0.0001537);
}
Insert cell
function orbitalEccentricity(t) { // e (25.4)
return 0.016708634 + t * (-0.000042037 + t * -0.0000001267);
}
Insert cell
function solarEquationOfCenter(t) { // C (p.164)
const m = solarMeanAnomaly(t) * deg2rad;
return (1.914602 - t * (0.004817 + t * 0.000014)) * sin(m)
+ (0.019993 - t * 0.000101) * sin(m * 2)
+ 0.000289 * sin(m * 3);
}
Insert cell
function solarTrueLongitude(t) { // ☉ = L_0 + C (p.164)
return solarMeanLongitude(t) + solarEquationOfCenter(t);
}
Insert cell
function solarTrueAnomaly(t) { // v = M + C (p.164)
return solarMeanAnomaly(t) + solarEquationOfCenter(t);
}
Insert cell
function solarApparentLongitude(t) { // λ (p.164)
const Ω = lunarLongitudeOfAscendingNode(t) * deg2rad;
return solarTrueLongitude(t) - 0.00569 - 0.00478 * sin(Ω);
}
Insert cell
function solarApparentRightAscension(t) { // α (25.6, 25.8)
const λ = solarApparentLongitude(t) * deg2rad;
const ε = obliquityOfEcliptic(t) * deg2rad;
return atan2(cos(ε) * sin(λ), cos(λ)) * rad2deg;
}
Insert cell
function solarApparentDeclination(t) { // δ (25.7, 25.8)
const λ = solarApparentLongitude(t) * deg2rad;
const ε = obliquityOfEcliptic(t) * deg2rad;
return asin(sin(ε) * sin(λ)) * rad2deg;
}
Insert cell
Insert cell
function lunarMeanLongitude(t) { // L′ (47.1)
return 218.3165 + t * 481267.8813;
}
Insert cell
function lunarLongitudeOfAscendingNode(t) { // Ω (p.144)
return 125.04452 + t * (-1934.136261 + t * (0.0020708 + t / 450000));
}
Insert cell
Insert cell
function meanObliquityOfEcliptic(t) { // ε_0 (22.2)
return 23 + (26 + (21.448 - t * (46.815 + t * (0.00059 - t * 0.001813))) / 60) / 60;
}
Insert cell
function obliquityOfEcliptic(t) { // ε (25.8) “true” obliquity
const Ω = lunarLongitudeOfAscendingNode(t) * deg2rad;
return meanObliquityOfEcliptic(t) + 0.00256 * cos(Ω);
}
Insert cell
function nutationInLongitude(t) { // Δψ (p.144)
const Ω = lunarLongitudeOfAscendingNode(t) * deg2rad;
const L = solarMeanLongitude(t) * deg2rad;
const L2 = lunarMeanLongitude(t) * deg2rad;
return (-17.20 * sin(Ω) - 1.32 * sin(2 * L) - 0.23 * sin(2 * L2) + 0.21 * sin(2 * Ω)) / 3600;
}
Insert cell
function nutationInObliquity(t) { // Δε (p.144)
const Ω = lunarLongitudeOfAscendingNode(t) * deg2rad;
const L = solarMeanLongitude(t) * deg2rad;
const L2 = lunarMeanLongitude(t) * deg2rad;
return (9.20 * cos(Ω) + 0.57 * cos(2 * L) + 0.10 * cos(2 * L2) - 0.09 * cos(2 * Ω)) / 3600;
}
Insert cell
Insert cell
function ecliptic2equatorial(t) {
const ε = obliquityOfEcliptic(t) * deg2rad;
return ([λ, β]) => {
λ *= rad2deg, β *= rad2deg;
const α = atan2(sin(λ) * cos(ε) - tan(β) * sin(ε), cos(λ)) * rad2deg; // right ascension
const δ = asin(sin(β) * cos(ε) + cos(β) * sin(ε) * sin(λ)) * rad2deg; // declination
return [α, δ];
};
}
Insert cell
function equatorial2horizontal(t, λo, ϕo) {
const Θ0 = (meanSiderealTime(t) + λo) * deg2rad;
ϕo *= deg2rad;
return ([α, δ]) => {
α *= deg2rad, δ *= deg2rad;
const h = Θ0 - α; /* local hour angle (radians) */
const A = atan2(sin(h), cos(h) * sin(ϕo) - tan(δ) * cos(ϕo)) * rad2deg; // azimuth
const a = asin(sin(ϕo) * sin(δ) + cos(ϕo) * cos(δ) * cos(h)) * rad2deg; // altitude
return [A, a];
};
}
Insert cell
function invertAzimuth([azimuth, altitude]) {
return [180 + azimuth, altitude];
}
Insert cell
Insert cell
Insert cell
function meanSiderealTime(t) {
const d = julianDate(t * 315576e7 + J2000) - 2451545;
return 280.46061837 + 360.98564736629 * d + 0.000387933 * t ** 2 - t ** 3 / 38710000;
}
Insert cell
function apparentSiderealTime(t) {
const Δψ = nutationInLongitude(t);
const ε = obliquityOfEcliptic(t) * deg2rad;
return meanSiderealTime(t) + Δψ * cos(ε);
}
Insert cell
Insert cell
julianDate = date => (date / 86400000) + 2440587.5
Insert cell
julianCentury = date => (date - J2000) / 315576e7 // J2000.0 centuries (22.1)
Insert cell
J2000 = Date.UTC(2000, 0, 1, 12)
Insert cell
hms = (h, m, s) => dms(h, m, s) * 15 // hours-minutes-seconds
Insert cell
dms = (d, m, s) => d + m / 60 + s / 3600 // degrees-minutes-seconds
Insert cell
Insert cell
τ = 2 * π
Insert cell
π = Math.PI
Insert cell
asin = Math.asin
Insert cell
atan2 = Math.atan2
Insert cell
cos = Math.cos
Insert cell
sin = Math.sin
Insert cell
tan = Math.tan
Insert cell
rad2deg = 180 / π
Insert cell
deg2rad = π / 180
Insert cell
deg360 = x => (x %= 360, x < 0 ? x + 360 : x)
Insert cell
Insert cell
path = d3.geoPath(projection)
Insert cell
projection = d3.geoStereographic()
.scale((width - 120) / 3)
.clipExtent([[0, 0], [width, height]])
.rotate([180, -90]) // use North-oriented azimuth
.translate([width / 2, height / 2])
.precision(0.1)
Insert cell
symbols = new Map([
["Sun", "☉"],
["Mercury", "☿"],
["Venus", "♀"],
["Moon", "☾"],
["Mars", "♂"],
["Jupiter", "♃"],
["Saturn", "♄"],
["Uranus", "⛢"],
["Neptune", "♆"],
["Pluto", "♇"]
])
Insert cell
xAxis = g => g
.call(g => g.append("g")
.attr("stroke", "currentColor")
.selectAll("line")
.data(d3.range(360))
.join("line")
.datum(d => [
projection([d, 0]),
projection([d, d % 10 ? -1 : -2])
])
.attr("x1", ([[x1]]) => x1)
.attr("x2", ([, [x2]]) => x2)
.attr("y1", ([[, y1]]) => y1)
.attr("y2", ([, [, y2]]) => y2))
.call(g => g.append("g")
.selectAll("text")
.data(d3.range(0, 360, 10))
.join("text")
.attr("dy", "0.35em")
.text(d => d === 0 ? "N" : d === 90 ? "E" : d === 180 ? "S" : d === 270 ? "W" : `${d}°`)
.attr("font-size", d => d % 90 ? null : 14)
.attr("font-weight", d => d % 90 ? null : "bold")
.datum(d => projection([d, -4]))
.attr("x", ([x]) => x)
.attr("y", ([, y]) => y))
Insert cell
yAxis = g => g
.call(g => g.append("g")
.selectAll("text")
.data(d3.range(10, 91, 10)) // every 10°
.join("text")
.attr("dy", "0.35em")
.text(d => `${d}°`)
.datum(d => projection([0, d]))
.attr("x", ([x]) => x)
.attr("y", ([, y]) => y))
Insert cell
circle = d3.range(5).map(i => [i / 4 * 360, 0]) // will be resampled by D3
Insert cell
outline = d3.geoCircle().radius(90).center([0, 90])()
Insert cell
graticule = d3.geoGraticule().stepMinor([15, 10])()
Insert cell
width = 960 + 28
Insert cell
height = width
Insert cell
d3 = require("d3@6")
Insert cell
ephemeris = require(await FileAttachment("ephemeris-2.0.0.js").url())
Insert cell
import {Scrubber} from "@mbostock/scrubber"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more