package basic import ( "math" "b612.me/astro/planet" . "b612.me/astro/tools" ) type planetGeocentricPosition struct { x float64 y float64 z float64 lo float64 bo float64 } func planetHeliocentricXYZN(planetIndex int, jd float64, n int) (float64, float64, float64) { l := planet.WherePlanetN(planetIndex, 0, jd, n) b := planet.WherePlanetN(planetIndex, 1, jd, n) r := planet.WherePlanetN(planetIndex, 2, jd, n) return sphericalToRectangular(l, b, r) } func earthHeliocentricXYZN(jd float64, n int) (float64, float64, float64) { l := planet.WherePlanetN(-1, 0, jd, n) b := planet.WherePlanetN(-1, 1, jd, n) r := planet.WherePlanetN(-1, 2, jd, n) return sphericalToRectangular(l, b, r) } func sphericalToRectangular(lo, bo, radius float64) (float64, float64, float64) { cosBo := math.Cos(bo * math.Pi / 180) return radius * cosBo * math.Cos(lo*math.Pi/180), radius * cosBo * math.Sin(lo*math.Pi/180), radius * math.Sin(bo*math.Pi/180) } func geocentricPositionFromRectangular(x, y, z float64) planetGeocentricPosition { lo := math.Atan2(y, x) * 180 / math.Pi bo := math.Atan2(z, math.Sqrt(x*x+y*y)) * 180 / math.Pi return planetGeocentricPosition{ x: x, y: y, z: z, lo: Limit360(lo), bo: bo, } } func planetGeocentricPositionN(planetIndex int, planetJD, earthJD float64, n int) planetGeocentricPosition { px, py, pz := planetHeliocentricXYZN(planetIndex, planetJD, n) ex, ey, ez := earthHeliocentricXYZN(earthJD, n) return geocentricPositionFromRectangular(px-ex, py-ey, pz-ez) } func planetGeocentricPositionWithEarthN(planetIndex int, planetJD float64, ex, ey, ez float64, n int) planetGeocentricPosition { px, py, pz := planetHeliocentricXYZN(planetIndex, planetJD, n) return geocentricPositionFromRectangular(px-ex, py-ey, pz-ez) } func planetApparentGeocentricPositionN(planetIndex int, jd float64, n int) (planetGeocentricPosition, float64) { ex, ey, ez := earthHeliocentricXYZN(jd, n) geoNow := planetGeocentricPositionWithEarthN(planetIndex, jd, ex, ey, ez, n) tau := 0.0057755183 * math.Sqrt(geoNow.x*geoNow.x+geoNow.y*geoNow.y+geoNow.z*geoNow.z) geo := planetGeocentricPositionWithEarthN(planetIndex, jd-tau, ex, ey, ez, n) baseLo := geo.lo baseBo := geo.bo geo.lo = Limit360(baseLo + GXCLo(baseLo, baseBo, jd)/3600.0 + Nutation2000Bi(jd)) geo.bo = baseBo + GXCBo(baseLo, baseBo, jd)/3600.0 return geo, tau } func planetTrueGeocentricPositionN(planetIndex int, jd float64, n int) (planetGeocentricPosition, float64) { ex, ey, ez := earthHeliocentricXYZN(jd, n) geoNow := planetGeocentricPositionWithEarthN(planetIndex, jd, ex, ey, ez, n) tau := 0.0057755183 * math.Sqrt(geoNow.x*geoNow.x+geoNow.y*geoNow.y+geoNow.z*geoNow.z) return planetGeocentricPositionWithEarthN(planetIndex, jd-tau, ex, ey, ez, n), tau } func planetEarthAwayExplicitN(planetIndex int, jd float64, n int) float64 { geoNow := planetGeocentricPositionN(planetIndex, jd, jd, n) return math.Sqrt(geoNow.x*geoNow.x + geoNow.y*geoNow.y + geoNow.z*geoNow.z) }