package basic import ( "math" . "b612.me/astro/tools" ) const ( VENUS_S_PERIOD = 1 / ((1 / 224.701) - (1 / 365.256363004)) venusEventSearchN = 16 ) func venusSunLongitudeDelta(jde float64) float64 { sub := Limit360(VenusApparentLo(jde) - HSunApparentLo(jde)) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub } func venusSunLongitudeDeltaN(jde float64, n int) float64 { sub := Limit360(VenusApparentLoN(jde, n) - HSunApparentLoN(jde, n)) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub } func venusSunRADelta(jde float64) float64 { sub := Limit360(VenusApparentRa(jde) - SunApparentRa(jde)) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub } func venusRADerivative(jde, val float64) float64 { sub := VenusApparentRa(jde+val) - VenusApparentRa(jde-val) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub / (2 * val) } func venusRADerivativeN(jde, val float64, n int) float64 { sub := VenusApparentRaN(jde+val, n) - VenusApparentRaN(jde-val, n) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub / (2 * val) } func venusSunElongationN(jde float64, n int) float64 { lo1, bo1 := VenusApparentLoBoN(jde, n) lo2 := SunApparentLo(jde) bo2 := HSunTrueBoN(jde, n) return StarAngularSeparation(lo1, bo1, lo2, bo2) } func venusElongationDerivative(jde, val float64) float64 { sub := VenusSunElongation(jde+val) - VenusSunElongation(jde-val) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub / (2 * val) } func venusElongationDerivativeN(jde, val float64, n int) float64 { sub := venusSunElongationN(jde+val, n) - venusSunElongationN(jde-val, n) if sub > 180 { sub -= 360 } if sub < -180 { sub += 360 } return sub / (2 * val) } func venusConjunction(jde float64, next uint8) float64 { //0=last 1=next nowSub := venusSunLongitudeDeltaN(jde, venusEventSearchN) pos := math.Abs(venusSunLongitudeDeltaN(jde+1/86400.0, venusEventSearchN)) - math.Abs(nowSub) if pos >= 0 && next == 1 && nowSub > 0 { jde += VENUS_S_PERIOD/8.0 + 2 } if pos >= 0 && next == 1 && nowSub < 0 { jde += VENUS_S_PERIOD/6.0 + 2 } if pos <= 0 && next == 0 && nowSub < 0 { jde -= VENUS_S_PERIOD/8.0 + 2 } if pos <= 0 && next == 0 && nowSub > 0 { jde -= VENUS_S_PERIOD/6.0 + 2 } for { nowSub := venusSunLongitudeDeltaN(jde, venusEventSearchN) pos := math.Abs(venusSunLongitudeDeltaN(jde+1/86400.0, venusEventSearchN)) - math.Abs(nowSub) if math.Abs(nowSub) > 24 || (pos > 0 && next == 1) || (pos < 0 && next == 0) { if next == 1 { jde += 8 } else { jde -= 8 } continue } break } JD1 := jde for { JD0 := JD1 stDegree := venusSunLongitudeDelta(JD0) stDegreep := (venusSunLongitudeDelta(JD0+0.000005) - venusSunLongitudeDelta(JD0-0.000005)) / 0.00001 JD1 = JD0 - stDegree/stDegreep if math.Abs(JD1-JD0) <= 0.00001 { break } } return TD2UT(JD1, false) } func LastVenusConjunction(jde float64) float64 { return venusConjunction(jde, 0) } func NextVenusConjunction(jde float64) float64 { return venusConjunction(jde, 1) } func NextVenusInferiorConjunction(jde float64) float64 { date := NextVenusConjunction(jde) if EarthVenusAway(date) > EarthAway(date) { return NextVenusConjunction(date + 2) } return date } func NextVenusSuperiorConjunction(jde float64) float64 { date := NextVenusConjunction(jde) if EarthVenusAway(date) < EarthAway(date) { return NextVenusConjunction(date + 2) } return date } func LastVenusInferiorConjunction(jde float64) float64 { date := LastVenusConjunction(jde) if EarthVenusAway(date) > EarthAway(date) { return LastVenusConjunction(date - 2) } return date } func LastVenusSuperiorConjunction(jde float64) float64 { date := LastVenusConjunction(jde) if EarthVenusAway(date) < EarthAway(date) { return LastVenusConjunction(date - 2) } return date } func venusRetrograde(jde float64) float64 { //0=last 1=next lastHe := LastVenusConjunction(jde) nextHe := NextVenusConjunction(jde) nowSub := venusSunRADelta(jde) if nowSub > 0 { jde = lastHe + ((nextHe - lastHe) / 5.0 * 3.5) } else { jde = lastHe + 10 } for { nowSub := venusRADerivativeN(jde, 1.0/86400.0, venusEventSearchN) if math.Abs(nowSub) > 0.5 { jde += 5 continue } break } JD1 := jde for { JD0 := JD1 stDegree := venusRADerivative(JD0, 0.5/86400.0) stDegreep := (venusRADerivative(JD0+10.0/86400.0, 0.5/86400.0) - venusRADerivative(JD0-10.0/86400.0, 0.5/86400.0)) / (20.0 / 86400.0) JD1 = JD0 - stDegree/stDegreep if math.Abs(JD1-JD0) <= 20.0/86400.0 { break } } min := eventZeroRefine(JD1, 10.0/86400.0, 0.5/86400.0, func(jd float64) float64 { return venusRADerivative(jd, 0.5/86400.0) }) //fmt.Println((min - lastHe) / (nextHe - lastHe)) return TD2UT(min, false) } func NextVenusRetrograde(jde float64) float64 { date := venusRetrograde(jde) if date < jde { nextHe := NextVenusConjunction(jde) return venusRetrograde(nextHe + 2) } return date } func LastVenusRetrograde(jde float64) float64 { lastHe := LastVenusConjunction(jde) date := venusRetrograde(lastHe + 2) if date > jde { lastLastHe := LastVenusConjunction(lastHe - 2) return venusRetrograde(lastLastHe + 2) } return date } func NextVenusProgradeToRetrograde(jde float64) float64 { date := NextVenusRetrograde(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub > 180 { return NextVenusRetrograde(date + VENUS_S_PERIOD/2) } return date } func NextVenusRetrogradeToPrograde(jde float64) float64 { date := NextVenusRetrograde(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub < 180 { return NextVenusRetrograde(date + 12) } return date } func LastVenusProgradeToRetrograde(jde float64) float64 { date := LastVenusRetrograde(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub > 180 { return LastVenusRetrograde(date - 12) } return date } func LastVenusRetrogradeToPrograde(jde float64) float64 { date := LastVenusRetrograde(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub < 180 { return LastVenusRetrograde(date - VENUS_S_PERIOD/2) } return date } func VenusSunElongation(jde float64) float64 { lo1, bo1 := VenusApparentLoBo(jde) lo2 := SunApparentLo(jde) bo2 := HSunTrueBo(jde) return StarAngularSeparation(lo1, bo1, lo2, bo2) } func venusGreatestElongation(jde float64) float64 { lastHe := LastVenusConjunction(jde) nextHe := NextVenusConjunction(jde) nowSub := venusSunRADelta(jde) if nowSub > 0 { jde = lastHe + ((nextHe - lastHe) / 5.0 * 2.5) } else { jde = lastHe + ((nextHe - lastHe) / 5.0) } for { nowSub := venusElongationDerivativeN(jde, 1.0/86400.0, venusEventSearchN) if math.Abs(nowSub) > 0.15 { jde += 5 continue } break } JD1 := jde for { JD0 := JD1 stDegree := venusElongationDerivative(JD0, 2.0/86400.0) stDegreep := (venusElongationDerivative(JD0+15.0/86400.0, 2.0/86400.0) - venusElongationDerivative(JD0-15.0/86400.0, 2.0/86400.0)) / (30.0 / 86400.0) JD1 = JD0 - stDegree/stDegreep if math.Abs(JD1-JD0) <= 30.0/86400.0 { break } } min := eventZeroRefine(JD1, 15.0/86400.0, 0.5/86400.0, func(jd float64) float64 { return venusElongationDerivative(jd, 0.5/86400.0) }) //fmt.Println((min - lastHe) / (nextHe - lastHe)) return TD2UT(min, false) } func NextVenusGreatestElongation(jde float64) float64 { date := venusGreatestElongation(jde) if date < jde { nextHe := NextVenusConjunction(jde) return venusGreatestElongation(nextHe + 2) } return date } func LastVenusGreatestElongation(jde float64) float64 { lastHe := LastVenusConjunction(jde) date := venusGreatestElongation(lastHe + 2) if date > jde { lastLastHe := LastVenusConjunction(lastHe - 2) return venusGreatestElongation(lastLastHe + 2) } return date } func NextVenusGreatestElongationEast(jde float64) float64 { date := NextVenusGreatestElongation(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub > 180 { return NextVenusGreatestElongation(date + 1) } return date } func NextVenusGreatestElongationWest(jde float64) float64 { date := NextVenusGreatestElongation(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub < 180 { return NextVenusGreatestElongation(date + 1) } return date } func LastVenusGreatestElongationEast(jde float64) float64 { date := LastVenusGreatestElongation(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub > 180 { return LastVenusGreatestElongation(date - 1) } return date } func LastVenusGreatestElongationWest(jde float64) float64 { date := LastVenusGreatestElongation(jde) sub := Limit360(VenusApparentRa(date) - SunApparentRa(date)) if sub < 180 { return LastVenusGreatestElongation(date - 1) } return date }