Class: When::Ephemeris::Formula

Inherits:
BasicTypes::Object show all
Includes:
When::Ephemeris, Parts::MethodCash
Defined in:
lib/when_exe/ephemeris.rb

Overview

暦法オブジェクトに天体暦機能を提供する

Direct Known Subclasses

Hindu, MeanLunation, VariableYearLengthMethod

Defined Under Namespace

Modules: Methods

Constant Summary collapse

CYCLE_0M =

Seed

0
CYCLE_1M =
1000000
Sgn =

Year Event

[[-1,+1],[-1,-1],[+1,-1],[+1,+1]]
Bs =
[[11.0,  7.0, 11.0,  7.0],
[11.0,  7.0, 11.0,  7.0],
[11.0,  7.0, 11.0,  7.0],
[14.0,  8.5, 14.0,  8.5],
[16.0, 10.0, 16.0, 10.0],
[17.0, 14.0, 17.0, 14.0],
[17.0, 17.0, 17.0, 17.0]]

Constants included from When::Ephemeris

AU, AcS, BCENT, C0, CIRCLE, COS, COSL, COSLT, COST, DAY, DEG, EPOCH1800, EPOCH1900, EPOCH1975, EPOCH2000, FARAWAY, JCENT, JYEAR, Jupiter, LIN, Mars, Mercury, Neptune, P0B, P0L, P0P, P0dB, P0dL, P1B, P1L, P1R, P2B, P2L, P2Q, P2dL, P3L, P3Q, P4B, P4L, P4Q, P4dL, P5B, P5L, P5Q, P5dL, P5l, P5n, P5r, P5t, P6B, P6L, P6Q, P6dL, P6l, P6n, P6r, P6t, P7B, P7L, P7R, P8B, P8L, P8R, P9B, P9L, P9R, PSEC, Pluto, SIN, SINL, SINLT, SINT, Saturn, Uranus, Venus

Constants included from Parts::MethodCash

Parts::MethodCash::Escape

Constants included from Parts::Resource

Parts::Resource::LabelProperty

Instance Attribute Summary collapse

Attributes inherited from BasicTypes::Object

#label

Attributes included from Parts::Resource

#_pool, #child, #keys, #locale, #namespace

Instance Method Summary collapse

Methods included from When::Ephemeris

_adjust, _rot, _to_p2, _to_p3, _to_r3, acos, asin, cosc, cosd, delta_e, delta_p, julian_century_from_2000, julian_year_from_1975, obl, polynomial, root, sinc, sind, tanc, tand, trigonometric

Methods included from Parts::MethodCash

_setup_, escape, #method_missing, #method_missing_

Methods included from Parts::Resource

#[], #^, _decode, _encode, _extract_prefix, _instance, _parse, _path_with_prefix, _replace_tags, _setup_, #each, #enum_for, #hierarchy, #include?, #included?, #iri, #leaf?, #m17n, #map, #next, #parent, #prev, #registered?

Methods included from Parts::Resource::Pool

#[], #[]=, #_pool, #_setup_, #pool_keys

Methods included from Parts::Resource::Synchronize

#synchronize

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class When::Parts::MethodCash

Instance Attribute Details

#altNumeric (readonly)

観測地の高度 / m


1213
1214
1215
# File 'lib/when_exe/ephemeris.rb', line 1213

def alt
  @alt
end

#formulaString, Hash (readonly)

計算対象 - 公式の指定


1197
1198
1199
# File 'lib/when_exe/ephemeris.rb', line 1197

def formula
  @formula
end

#grahaHash<Symbol=>When::Ephemeris::Datum> (readonly)

天体オブジェクトを保持するハッシュ


1225
1226
1227
# File 'lib/when_exe/ephemeris.rb', line 1225

def graha
  @graha
end

#is_dynamicalBoolean (readonly)

時刻系が dynamical か


1221
1222
1223
# File 'lib/when_exe/ephemeris.rb', line 1221

def is_dynamical
  @is_dynamical
end

#latNumeric (readonly)

観測地の基準緯度 / 度


1209
1210
1211
# File 'lib/when_exe/ephemeris.rb', line 1209

def lat
  @lat
end

#locationWhen::Coordinates::Spatial (readonly)

観測地


1201
1202
1203
# File 'lib/when_exe/ephemeris.rb', line 1201

def location
  @location
end

#longNumeric (readonly)

観測地の基準経度 / 度


1205
1206
1207
# File 'lib/when_exe/ephemeris.rb', line 1205

def long
  @long
end

#time_standardString (readonly)

時刻系('universal' or 'dynamical')


1217
1218
1219
# File 'lib/when_exe/ephemeris.rb', line 1217

def time_standard
  @time_standard
end

Instance Method Details

#_coords(t, system, target) ⇒ When::Ephemeris::Coords

天体の位置情報


1311
1312
1313
1314
1315
1316
1317
# File 'lib/when_exe/ephemeris.rb', line 1311

def _coords(t, system, target)
  pos = target.coords(t, @location)
  pos = pos.y_to_r(t, @location)  if system >= When::Coordinates::Spatial::EQUATORIAL
  pos = pos.r_to_rh(t, @location) if system >= When::Coordinates::Spatial::EQUATORIAL_HA
  pos = pos.rh_to_h(t, @location) if system >= When::Coordinates::Spatial::HORIZONTAL
  return pos
end

#_to_seed_type(d, seed) ⇒ Numeric, When::TM::TemporalPosotion

ユリウス日(Numeric)を seed と同じ型に変換して返します。


1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
# File 'lib/when_exe/ephemeris.rb', line 1562

def _to_seed_type(d, seed)
  case seed
  when Numeric         ; return d
  when When::TimeValue ; seed = seed._attr
  else                 ; seed = seed.dup
  end
  seed[:precision] = nil
  seed[:clock]   ||= When::TM::Clock.local_time
  t = When::TM::JulianDate._d_to_t(d)
  seed[:frame].jul_trans(@is_dynamical ? When::TM::JulianDate.dynamical_time(t) :
                                         When::TM::JulianDate.universal_time(t), seed)
end

#cn_to_time_(cn, time0 = nil) ⇒ Numeric

周期番号 -> 日時


1260
1261
1262
1263
# File 'lib/when_exe/ephemeris.rb', line 1260

def cn_to_time_(cn, time0=nil)
  time0 ||= (cn - @cycle_number_0m) / @cycle_number_1m
  root(time0, cn) {|t| time_to_cn(t)}
end

#day_event(t, event, target = When.Resource('_ep:Sun'), height = nil) ⇒ Numeric, When::TM::TemporalPosotion

天体の出没最大高度日時


1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
# File 'lib/when_exe/ephemeris.rb', line 1369

def day_event(t, event, target=When.Resource('_ep:Sun'), height=nil)
  # 時刻の初期値
  dl  = @location.long / (360.0 * When::Coordinates::Spatial::DEGREE)
  t0  = (+t + dl).round - dl
  dt  = _coords(t0, When::Coordinates::Spatial::EQUATORIAL, target).phi -
        @location.local_sidereal_time(t0) / 24.0 + 0.25 * (event||0)
  t0 += dt - dt.round

  # 天体の地平座標での高度または方位角
  case event
  when 0
    meridian = _coords(t0, When::Coordinates::Spatial::EQUATORIAL_HA, target).phi.round
  when +1, -1
    height ||= target.instance_of?(When::Ephemeris::Sun) ? '0' : 'A'
    if height.kind_of?(String)
      height = @location.datum.zeros[height.upcase]
      raise ArgumentError, 'invalid height string' unless height
    end
    height = height / 360.0 - (0.25 - @location.horizon) +
           [@location.alt / (1000.0 * @location.datum.air[0]), 1].min * @location.datum.zeros['A'] / 360.0
  else
    height = nil # 極値検索のため
  end

  # イベントの時刻
  _to_seed_type(
    event == 0 ? (root(t0, meridian, 1) {|t1| _coords(t1, When::Coordinates::Spatial::EQUATORIAL_HA, target).phi}) :
                 (root(t0, height     ) {|t1| _coords(t1, When::Coordinates::Spatial::HORIZONTAL, target).theta }),
   t)
end

#meridian_passage_of_moon(t) ⇒ Numeric, When::TM::TemporalPosotion

月の南中の日時


1502
1503
1504
# File 'lib/when_exe/ephemeris.rb', line 1502

def meridian_passage_of_moon(t)
  day_event_in_the_day(t, 0, When.Resource('_ep:Moon'))
end

#meridian_passage_of_sun(t) ⇒ Numeric, When::TM::TemporalPosotion

太陽の南中の日時


1448
1449
1450
# File 'lib/when_exe/ephemeris.rb', line 1448

def meridian_passage_of_sun(t)
  day_event(t, 0, When.Resource('_ep:Sun'))
end

#moon_noon(t) ⇒ Numeric, When::TM::TemporalPosotion

月の最大高度の日時


1490
1491
1492
# File 'lib/when_exe/ephemeris.rb', line 1490

def moon_noon(t)
  day_event_in_the_day(t, nil, When.Resource('_ep:Moon'))
end

#moon_visibility(t) ⇒ Numeric

Note:

満月に近い場合は考慮されていません。主に新月の初見の確認に用います。

日没時に月が見えるか否か


1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
# File 'lib/when_exe/ephemeris.rb', line 1330

def moon_visibility(t)
  sun  = When.Resource('_ep:Sun')
  moon = When.Resource('_ep:Moon')

  # 日没時刻
  t = day_event(+t, +1, sun, 'Z')

  # 月の地平線からの高度
  h = _coords(t, When::Coordinates::Spatial::HORIZONTAL, moon).theta * 360.0

  # 月と太陽の離角
  p = moon.elongation(t, sun, @location) * 360.0

  # 指標の計算
  n = 4.0 - 0.1*p
  f = p < 40.0 ? 4.0 + n*(n+1)/2 : 4.0
  return (h / f - 1.0)
end

#moonrise(t, height = 'A') ⇒ Numeric, When::TM::TemporalPosotion

月の出の日時


1463
1464
1465
# File 'lib/when_exe/ephemeris.rb', line 1463

def moonrise(t, height='A')
  day_event_in_the_day(t, -1, When.Resource('_ep:Moon'), height)
end

#moonset(t, height = 'A') ⇒ Numeric, When::TM::TemporalPosotion

月の入りの日時


1478
1479
1480
# File 'lib/when_exe/ephemeris.rb', line 1478

def moonset(t, height='A')
  day_event_in_the_day(t, +1, When.Resource('_ep:Moon'), height)
end

#nearest_past(date, n = 0, d = 1) ⇒ Numeric, When::TM::TemporalPosition

指定の周期番号パターンになる最も近い過去の日時


1288
1289
1290
1291
1292
1293
1294
# File 'lib/when_exe/ephemeris.rb', line 1288

def nearest_past(date, n=0, d=1)
  i, f = n.divmod(d)
  t0   = @is_dynamical ? +date : date.to_f
  cn   = time_to_cn(date).divmod(d)[0] * d + f
  cn  -= d while (t1 = cn_to_time(cn)) > t0
  _to_seed_type((i == 0) ? t1 : cn_to_time(cn+i*d), date)
end

#sun_noon(t) ⇒ Numeric, When::TM::TemporalPosotion

太陽の最大高度の日時


1437
1438
1439
# File 'lib/when_exe/ephemeris.rb', line 1437

def sun_noon(t)
  day_event(t, nil, When.Resource('_ep:Sun'))
end

#sunrise(t, height = '0') ⇒ Numeric, When::TM::TemporalPosotion

日の出の日時


1411
1412
1413
# File 'lib/when_exe/ephemeris.rb', line 1411

def sunrise(t, height='0')
  day_event(t, -1, When.Resource('_ep:Sun'), height)
end

#sunset(t, height = '0') ⇒ Numeric, When::TM::TemporalPosotion

日の入りの日時


1426
1427
1428
# File 'lib/when_exe/ephemeris.rb', line 1426

def sunset(t, height='0')
  day_event(t, +1, When.Resource('_ep:Sun'), height)
end

#thiti_range(date) ⇒ Range

当該日付のthiti の変化範囲


1271
1272
1273
1274
1275
1276
1277
# File 'lib/when_exe/ephemeris.rb', line 1271

def thiti_range(date)
  date   = date.floor
  p0, p1 = [date, date.succ].map {|d|
    (30.0 * time_to_cn(d)) % 30.0
  }
  p0 >= p1 ? nil : p0...p1
end

#time_to_cn(t) ⇒ Numeric

日時 -> 周期番号


1250
1251
1252
# File 'lib/when_exe/ephemeris.rb', line 1250

def time_to_cn(t)
  @proc.call(t)
end

#year_event(t, event, target, hs = @location.datum.zeros['A'], bs = nil) ⇒ Numeric, When::TM::TemporalPosotion

恒星の出没と太陽の位置関係に関するイベントの日時


1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
# File 'lib/when_exe/ephemeris.rb', line 1521

def year_event(t, event, target, hs= @location.datum.zeros['A'], bs=nil)
  # difference of ecliptic longitude between zenith and target star 
  # when the event happens
  pos  = _coords(+t, When::Coordinates::Spatial::EQUATORIAL, target)
  long = @location.long / When::Coordinates::Spatial::DEGREE
  lat  = @location.lat  / When::Coordinates::Spatial::DEGREE
  dp   = (sind(hs) - sind(lat) * sinc(pos.theta)) / 
                    (cosd(lat) * cosc(pos.theta))

  return nil if dp.abs >= 1
  dp  = acos(dp) / CIRCLE

  # The Sun's height when the event happens
  unless bs
    mag = target.luminosity
    bs  = Bs[mag<-0.5 ?  0 : (mag<4.5 ? mag.round+1 : 6)][event]
  end

  # イベントの時刻
  zenith = Coords.polar(pos.phi+Sgn[event][0]*dp, lat/360.0).r_to_y(+t, @location)
  s   = sind(bs)/cosc(zenith.theta)
  arc = asin(s) / CIRCLE + 0.25
  lam = _true_sun(+t).floor+(zenith.phi+Sgn[event][1]*arc).divmod(1)[1]
  tt  = nil
  loop do
    tt = root(+t, lam) {|t1| _true_sun(t1)}
    break if tt >= +t
    lam += 1
  end
  _to_seed_type(day_event((tt+long/360.0).round, Sgn[event][0], When.Resource('_ep:Sun'), bs), t)
end