- 新增时标、ΔT 模型、质心时间与 UT1 支持 - 改进日月食、月掩、行星事件及路径边界计算 - 完善恒星三维自行与动态距离传播 - 扩展 SVG、GeoJSON、KML 输出与底层距离换算工具 - 整理中英文手册、示例资源及回归测试
17 KiB
Stars
Full examples in this manual run from the repository root.
The library ships a catalog of 9100 stars (BSC / HR numbers 1-9110, apparent magnitudes -1.46 to 7.96) and propagates proper motion automatically. The catalog stores J2000 right ascension and declination (InnerStarData.Ra/Dec); to get the position at a given instant you must apply proper motion, precession and nutation through StarData.RaDecByDate(date). Rise/set, topocentric quantities and constellation lookup all expect the corrected coordinates.
Contents
- Finding Sirius and its rise time
- API Reference
- Usage examples
- Parameter and result conventions
- Related manuals
Finding Sirius and its rise time
package main
import (
"fmt"
"log"
"time"
"b612.me/astro/star"
)
func main() {
cst := time.FixedZone("CST", 8*3600)
date := time.Date(2020, 1, 1, 8, 8, 8, 0, cst)
lon, lat, height := 115.0, 40.0, 0.0
sirius, err := star.StarDataByName("天狼")
if err != nil {
log.Fatal(err)
}
ra, dec := sirius.RaDecByDate(date)
rise, err := star.RiseTime(date, ra, dec, lon, lat, height, true)
if err != nil {
log.Fatal(err)
}
fmt.Println(star.Constellation(ra, dec, date))
fmt.Printf("RA=%.6f Dec=%.6f deg\n", ra, dec)
fmt.Println(rise.Format(time.RFC3339))
}
Catalog coordinates have epoch J2000. RaDecByDate applies proper motion, precession and nutation before date-specific rise/set, altitude or constellation calculations.
Proper motion is propagated in Julian years (365.25 days), and RaDecByDate converts the civil instant to TT before taking the epoch difference. Whenever a record carries a distance (Pc > 0), RaDecByJde advances a full three-dimensional space motion: proper motion supplies the tangential velocity and RadVel the line-of-sight component, the position vector is extrapolated linearly and its direction is taken. Records without a distance fall back to two dimensions, advancing only the two angular components, which is equivalent to treating the star as infinitely distant. The two differ by second-order terms only — the curvature of the great-circle path and the change in angular scale as radial motion alters the distance; even the fastest bright star moves less than about 0.09 arcseconds from it within 26 years.
API Reference
| Group | Entry points | Purpose | Units and convention |
|---|---|---|---|
| Constellation | Constellation / ConstellationEN / ConstellationCode |
Chinese name / English name / IAU three-letter code | Corrected RA/Dec in degrees plus the instant |
| Star catalog | InitStarDatabase / StarDataByHR / StarDataByName / TopBrightStars |
Initialise the embedded catalog, look up by HR number or Chinese name, fetch the bright-star sample | HR 1-9110; Mag is apparent magnitude |
| Coordinate correction | StarData.RaDecByDate (RaDecByJde on the basic side) |
Correct a J2000 position to the given instant | Returns RA/Dec in degrees |
| Rise, set, culmination | RiseTime / SetTime / CulminationTime (DownTime is a deprecated alias of SetTime) |
Rise, set and culmination instants | Civil instants; polar cases return sentinel errors |
| Topocentric quantities | Altitude / ApparentAltitude / Azimuth / Zenith / ApparentZenith |
(Apparent) altitude, azimuth, (apparent) zenith distance | Degrees |
| Hour angle and parallactic angle | HourAngle / ParallacticAngle |
Stellar hour angle, zenith-direction parallactic angle | Degrees |
| Sidereal time | MeanSiderealTime / ApparentSiderealTime |
Mean and apparent sidereal time | Hours |
The star package has no ...N truncated entry points; truncated analytical series live on the matching functions of sun, moon, the planets and coord, where n < 0 uses every built-in term and n >= 0 truncates the series (see those manuals).
The snippets below omit shared preamble variables: date (observation instant, civil time scale), lon/lat (observer longitude/latitude, east/north positive, degrees), height (observer height, ellipsoidal, metres), aero (whether refraction and apparent-radius corrections are applied).
Constellation lookup
sirius, _ := star.StarDataByName("天狼")
ra, dec := sirius.RaDecByDate(date)
fmt.Println(star.Constellation(ra, dec, date)) // 大犬座
fmt.Println(star.ConstellationEN(ra, dec, date)) // Canis Major
fmt.Println(star.ConstellationCode(ra, dec, date)) // CMA
All three share one boundary table and differ only in output convention. The lookup uses the apparent position of the day, so pass the result of RaDecByDate, never the J2000 coordinates from the catalog.
Star catalog
_ = star.InitStarDatabase()
s, _ := star.StarDataByHR(2491)
fmt.Println(s.HR, s.ChineseName, s.CommonName, s.Mag) // 2491 天狼 Sirius -1.46
bright, _ := star.TopBrightStars()
fmt.Println(len(bright), bright[0].HR) // size of the bright-star sample and the leading HR number
The catalog loads lazily behind sync.Once; InitStarDatabase() only warms it up. It is idempotent and surfaces the load error explicitly, and skipping it still works because the first lookup loads the catalog automatically.
TopBrightStars() returns 169 built-in entries around magnitude 3 or brighter, roughly ordered from brighter to dimmer.
basic.StarData adds naming fields on top of InnerStarData, whose conventions are:
| Field | Meaning |
|---|---|
HR / HD / HIP |
Bright Star number (1-9110) / Henry Draper number / Hipparcos number |
Ra / Dec |
J2000 right ascension and declination in degrees (run RaDecByDate for the apparent position) |
Mag |
Apparent magnitude |
PmRA / PmDec |
Annual proper motion cos(dec)*dRA/dt and in declination, arcseconds per year |
RadVel / RotVel |
Radial and proper-motion velocity, km/s |
Pc |
Distance in parsecs; > 0 propagates proper motion as a 3D space motion |
ChineseName / ChineseAlias / ChineseBayerName |
Chinese name, alias and Bayer designation |
CommonName / CommonAliasName |
Common English name and alias |
Cst / CstChinese |
Constellation name in English and Chinese |
Lookup by name matches the catalog's Chinese names only (天狼 for Sirius, 织女一 for Vega); English names are not matched. Use StarDataByHR to look up by number.
Rise, set and culmination
ra, dec := 101.28715533, -16.71611586 // Sirius-like sample coordinates near J2000
rise, _ := star.RiseTime(date, ra, dec, lon, lat, height, true)
set, _ := star.SetTime(date, ra, dec, lon, lat, height, true)
fmt.Println(rise, set)
fmt.Println(star.CulminationTime(date, ra, lon))
With aero true the rise/set solution uses the horizon corrected by refraction and apparent radius; false uses the geometric horizon. CulminationTime needs only right ascension and longitude.
Under a polar night or midnight sun, RiseTime/SetTime return sentinel errors instead of an instant, see below.
Topocentric quantities
fmt.Println(star.Altitude(date, ra, dec, lon, lat))
fmt.Println(star.ApparentAltitude(date, ra, dec, lon, lat, 1010, 10))
fmt.Println(star.Azimuth(date, ra, dec, lon, lat), star.Zenith(date, ra, dec, lon, lat))
fmt.Println(star.HourAngle(date, ra, lon), star.ParallacticAngle(date, ra, dec, lon, lat))
ApparentAltitude/ApparentZenith take two extra arguments, pressure (hPa) and temperature (C), for the refraction correction. ParallacticAngle is the usual input for rotating a camera or a spectrograph slit.
Sidereal time
fmt.Println(star.MeanSiderealTime(date), star.ApparentSiderealTime(date))
Both return hours; the relation between sidereal time, hour angle and horizontal transforms is documented in the coord manual.
Calculating observing quantities for bright stars
bright, _ := star.TopBrightStars()
for _, s := range bright[:3] {
ra, dec := s.RaDecByDate(date)
alt := star.ApparentAltitude(date, ra, dec, lon, lat, 1010, 10)
fmt.Printf("%-6s %-10s mag=%.2f alt=%.3f\n", s.ChineseName, star.ConstellationEN(ra, dec, date), s.Mag, alt)
}
Run at date = 2020-01-01 08:08:08 CST from 115 E, 40 N with pressure 1010 hPa and temperature 10 C, this prints:
天狼 Canis Major mag=-1.46 alt=-30.180
老人 Carina mag=-0.72 alt=-48.661
大角 Bootes mag=-0.04 alt=68.926
Complete example
package main
import (
"fmt"
"time"
"b612.me/astro/star"
"b612.me/astro/tools"
)
func main() {
cst := time.FixedZone("CST", 8*3600)
// Observation instant.
date := time.Date(2020, 1, 1, 8, 8, 8, 8, cst)
// Initialise the star catalog.
_ = star.InitStarDatabase()
sirius, _ := star.StarDataByName("天狼")
ra, dec := sirius.RaDecByDate(date)
// Sirius rising.
riseDate, _ := star.RiseTime(date, ra, dec, 115, 40, 0, true)
fmt.Println(riseDate)
// Sirius setting.
setDate, _ := star.SetTime(date, ra, dec, 115, 40, 0, true)
fmt.Println(setDate)
fmt.Println(star.Constellation(ra, dec, date))
// Vega.
vega, _ := star.StarDataByName("织女一")
ra, dec = vega.RaDecByDate(time.Date(13600, 1, 1, 0, 0, 0, 0, time.Local))
// Vega right ascension in 13600 CE.
fmt.Println(tools.Format(ra/15, 1))
// Vega declination in 13600 CE.
fmt.Println(tools.Format(dec, 0))
bright, _ := star.TopBrightStars()
fmt.Println(bright[0].ChineseName, bright[0].CommonName, bright[0].Mag)
}
Output:
2019-12-31 19:22:56.144202053 +0800 CST // Sirius rising
2020-01-01 05:30:39.802506566 +0800 CST // Sirius setting
大犬座 // constellation of Sirius
6h3m46.61s // Vega right ascension in 13600 CE
84°18′27.15″ // Vega declination in 13600 CE
天狼 Sirius -1.46 // first bright-star entry: Chinese name, common name, magnitude
The printed constellation name is the Chinese one because Constellation is the Chinese-name entry point; use ConstellationEN for Canis Major and ConstellationCode for CMA.
Bulk lookups and caching
for _, hr := range []int{2491, 2326, 5340} {
s, err := star.StarDataByHR(hr)
if err != nil {
continue
}
ra, dec := s.RaDecByDate(date)
fmt.Println(s.ChineseName, star.ConstellationCode(ra, dec, date), s.Mag)
}
The catalog loads once on first access and is then a read-only cache, so share it across calls and goroutine-free request paths instead of caching it yourself. Unknown numbers or names return an error; in bulk code it is enough to skip on err != nil without classifying the error.
Usage examples
Can I see this star tonight?
ra, dec := sirius.RaDecByDate(date)
fmt.Println(star.RiseTime(date, ra, dec, lon, lat, height, true)) // rise
fmt.Println(star.SetTime(date, ra, dec, lon, lat, height, true)) // set
fmt.Println(star.CulminationTime(date, ra, lon)) // culmination
fmt.Println(star.ApparentAltitude(date, ra, dec, lon, lat, 1010, 10), star.Azimuth(date, ra, dec, lon, lat))
aero = true solves rise/set against the horizon corrected for refraction and apparent radius, which sits closer to the visual "just above the horizon" moment; false uses the geometric horizon, and the two differ on the order of 2-3 minutes.
Use the apparent altitude to decide whether the star is visible now, with 1010 hPa / 10 C as the usual default weather values. height is ellipsoidal height in metres; when you only have orthometric height, add the geoid undulation first, see Observer height conventions in the README.
Using a J2000 position at a given instant
ra, dec := sirius.RaDecByDate(date) // J2000 -> instant (proper motion + precession + nutation)
fmt.Println(star.ApparentSiderealTime(date)) // apparent sidereal time, hours
fmt.Println(star.HourAngle(date, ra, lon)) // hour angle, degrees
The catalog stores J2000 positions, so skipping RaDecByDate puts rise/set and constellation lookups off by degrees. Sidereal time, horizontal transforms, precession and nutation are covered in Coordinate tools; every time argument is a civil instant (a UTC label, equal to UT1 before 1972-01-01), see Time Scale Declaration.
Constellation lookup and the bright-star catalog
bright, _ := star.TopBrightStars()
for _, s := range bright[:3] {
ra, dec := s.RaDecByDate(date)
fmt.Println(s.ChineseName, star.ConstellationCode(ra, dec, date), s.Mag, s.CommonName)
}
天狼 CMA -1.46 Sirius
老人 CAR -0.72 Canopus
大角 BOO -0.04 Arcturus
All three constellation entry points share one boundary table and differ only in output: Constellation gives the Chinese name, ConstellationEN the English name and ConstellationCode the IAU three-letter code; the lookup uses the apparent position of the day. Catalog fields (HR/HD/HIP, J2000 RA/Dec, magnitude, proper motion, parallax distance and the naming fields) are listed as a table under API Reference.
Polar edges and catalog conventions
_, err := star.RiseTime(date, ra, dec, 0, 89, 0, true)
if errors.Is(err, star.ERR_STAR_NEVER_RISE) || errors.Is(err, star.ERR_STAR_NEVER_SET) {
fmt.Println("该日无升落:", err)
}
-
Polar sentinel errors:
RiseTimereturnsstar.ERR_STAR_NEVER_RISEduring a polar night (below the horizon all day) andSetTimereturnsstar.ERR_STAR_NEVER_SETduring a midnight sun (above it all day); branch witherrors.Is.ERR_STAR_NEVER_DOWNis a deprecated alias ofERR_STAR_NEVER_SET, andDownTimeis a deprecated alias ofSetTime. -
Refraction range: the Saemundsson approximation only applies for true altitudes inside
(-5, 90)degrees and contributes zero outside, so well below the horizon the apparent altitude equals the geometric one. -
Catalog conventions: BSC / HR
1-9110, apparent magnitudes-1.46to7.96; name lookup matches the built-in Chinese names only (天狼,织女一), never English names. -
Cross-checking against external catalogs: positions here are J2000 mean places with proper motion plus precession and nutation; when comparing term by term, bring both sides to the same instant with
RaDecByDatefirst.
Parameter and result conventions
-
Units: right ascension, declination, altitude, zenith distance, azimuth, hour angle, parallactic angle are in degrees; sidereal time is in hours;
tools.Formatrenders them as degrees-minutes-seconds or hours-minutes-seconds.In the catalog
PmRA/PmDecare arcseconds per year,RadVel/RotVelare km/s andPcis parsecs. -
Time scale: every public time argument and return value is a civil instant (a UTC label, equal to UT1 before 1972-01-01); see Time Scale Declaration.
-
Coordinate convention: the catalog is J2000;
RaDecByDateadds proper motion, precession and nutation. Skipping it puts rise/set and constellation lookups off by a large margin (a century of precession is a degree-level shift). -
Polar sentinel errors:
RiseTimereturnsstar.ERR_STAR_NEVER_RISEduring a polar night (the star stays below the horizon all day) andSetTimereturnsstar.ERR_STAR_NEVER_SETduring a midnight sun (it stays above it); test witherrors.Is.ERR_STAR_NEVER_DOWNis a deprecated alias ofERR_STAR_NEVER_SET. -
Observer height:
heightis ellipsoidal height in metres; when you only have orthometric height, add the geoid undulation first, as described under "Observer Height Convention" in the README. -
Refraction range: the Saemundsson approximation behind
ApparentAltitude/ApparentZenithonly applies for true altitudes inside(-5, 90)degrees and contributes zero outside that range, so well below the horizon the apparent altitude equals the geometric one (thealt=-30.180above is the same valueAltitudereturns).Pressure must be positive and temperature above absolute zero, otherwise the result is
NaN. -
aerosemantics: a true value solves rise/set against the horizon corrected by standard refraction, a false value uses the geometric horizon; the difference is about 2-3 minutes at low latitudes and grows noticeably at high latitudes. -
Catalog range: HR
1-9110, apparent magnitudes-1.46to7.96; name lookup matches the built-in Chinese names only.
Related manuals
- Sidereal time, horizontal transforms, precession/nutation and parallactic angle: Coordinate tools
- Rise/set semantics next to the Sun and Moon: Sun and Moon
- Time scale in figures: Time Scale Declaration