Class: When::Coordinates::Spatial

Inherits:
BasicTypes::Object show all
Includes:
Ephemeris
Defined in:
lib/when_exe/coordinates.rb,
lib/when_exe/ephemeris/eclipse.rb

Overview

Copyright © 2014 Takashi SUGA

You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.

Defined Under Namespace

Modules: Normalize

Constant Summary collapse

LabelProperty =
'label'
HashProperty =
[:label, [:alt, 0.0], [:datum, When::Ephemeris::Earth], :ref]
DEGREE =

Degree / Internal Location Unit(16“)

(3600 を 2 の因数で割りつくした値を単位とする)
225
ECLIPTIC =

黄道座標 (ecliptic coordinate system)

0
EQUATORIAL =

赤道座標 (equatorial coordinate system)

1
EQUATORIAL_HA =

赤道座標 (equatorial coordinate system with hour angle)

2
HORIZONTAL =

地平座標 (horizontal coordinate system)

3
CENTER =

惑星中心の高度

:center
EclipseHalfYear =
(346 + (14*3600+52*60+54.965) / 86400) / 2
EclipseRange =
(75.0..120.0)

Constants included from Ephemeris

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

Constants included from Parts::Resource

Parts::Resource::ConstList, Parts::Resource::ConstTypes, Parts::Resource::IRIHeader

Instance Attribute Summary collapse

Attributes inherited from BasicTypes::Object

#label

Attributes included from Parts::Resource

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

Class Method Summary collapse

Instance Method Summary collapse

Methods included from 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::Resource

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

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

#method_missing(name, *args, &block) ⇒ Object (private)

その他のメソッド

When::Coordinates::Spatial で定義されていないメソッドは
処理を @datum (type: When::Ephemeris::Datum) に委譲する


1552
1553
1554
1555
1556
1557
1558
1559
# File 'lib/when_exe/coordinates.rb', line 1552

def method_missing(name, *args, &block)
  self.class.module_eval %Q{
    def #{name}(*args, &block)
      @datum.send("#{name}", *args, &block)
    end
  } unless When::Parts::MethodCash.escape(name)
  @datum.send(name, *args, &block)
end

Instance Attribute Details

#altNumeric, :Center (readonly)

高度 / m

Returns:

  • (Numeric)
  • (:Center)

    天体の中心の場合



1370
1371
1372
# File 'lib/when_exe/coordinates.rb', line 1370

def alt
  @alt
end

#datumWhen::Ephemeris::Datum (readonly)

座標系



1376
1377
1378
# File 'lib/when_exe/coordinates.rb', line 1376

def datum
  @datum
end

#latNumeric (readonly)

北緯を正とする緯度 / 16秒

Returns:



1357
1358
1359
# File 'lib/when_exe/coordinates.rb', line 1357

def lat
  @lat
end

#longNumeric (readonly)

東経を正とする経度 / 16秒

Returns:



1363
1364
1365
# File 'lib/when_exe/coordinates.rb', line 1363

def long
  @long
end

#refString (readonly)

参照

Returns:



1382
1383
1384
# File 'lib/when_exe/coordinates.rb', line 1382

def ref
  @ref
end

#tzTZInfo::CountryTimezone (readonly)

時間帯(オプショナル)

Returns:

  • (TZInfo::CountryTimezone)

    TZInfoライブラリから経緯度を取得して使用する



1390
1391
1392
# File 'lib/when_exe/coordinates.rb', line 1390

def tz
  @tz
end

Class Method Details

._setup_(location = nil) ⇒ void

Note:

本メソッドでマルチスレッド対応の管理変数の初期化を行っている。 このため、本メソッド自体はスレッドセーフでない。

This method returns an undefined value.

When::Coordinates::Spatial のグローバルな設定を行う

Parameters:



1265
1266
1267
1268
1269
# File 'lib/when_exe/coordinates.rb', line 1265

def _setup_(location=nil)
  @_lock_ = Mutex.new if When.multi_thread
  @_pool  = {}
  @default_location = location
end

._setup_infoHash

設定情報を取得する

Returns:

  • (Hash)

    設定情報



1293
1294
1295
# File 'lib/when_exe/coordinates.rb', line 1293

def _setup_info
  {:location => @default_location}
end

.default_locationWhen::Coordinates::Spatial

デフォルトの空間位置を読みだす



1301
1302
1303
# File 'lib/when_exe/coordinates.rb', line 1301

def default_location
  _default_location[1]
end

.default_location=(local) ⇒ When::Coordinates::Spatial, String

Note:

@default_locationは、原則、ライブラリ立ち上げ時に setup で初期化する。 以降、@default_locationに代入を行っても、すでに生成した When::TM::TemporalPosition 等には反映されない。

デフォルトの空間位置

Parameters:

Returns:



1281
1282
1283
1284
1285
1286
1287
# File 'lib/when_exe/coordinates.rb', line 1281

def default_location=(local)
  if @_pool
    @default_location = local
  else
    _setup_(local)
  end
end

.is_default_location_derived?true, false

デフォルトの空間位置が When::TM::Clock のローカルタイムから生成されたか?

Returns:

  • (true, false)


1309
1310
1311
1312
# File 'lib/when_exe/coordinates.rb', line 1309

def is_default_location_derived?
  location = _default_location
  location[0] && location[1]
end

Instance Method Details

#_coords(t) ⇒ Numeric

観測地の日心三次元座標(黄道座標)

Parameters:

Returns:



1469
1470
1471
1472
# File 'lib/when_exe/coordinates.rb', line 1469

def _coords(t)
  t   = +t
  @datum._coords(t) + _coords_diff(t)
end

#eclipse_info(date, location, target, base, l_for_h = [location, base]) ⇒ Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>

食の情報

Parameters:

Returns:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/when_exe/ephemeris/eclipse.rb', line 103

def eclipse_info(date, location, target, base, l_for_h=[location, base])

  tc  = When::Ephemeris.root(+date) {|t|            # 離角最小日時
          base.elongation(t, target, location)**2
        }
  mag = base.phase_of_eclipse(tc, target, location) # 食分
  return nil unless mag >= 0                        # 食なし

  t1, t4 = [-0.1, +0.1].map {|dt|                   # 第1, 第4接触
    When::Ephemeris.root(tc+dt, 0) {|t|
      base.phase_of_eclipse(t, target, location)
    }
  }

  if mag >= 1
    category = 'T'
    t2, t3 = [-0.01, +0.01].map {|dt|               # 第2, 第3接触
      When::Ephemeris.root(tc+dt, 1.0) {|t|
        base.phase_of_eclipse(t, target, location)
      }
    }
  elsif target.phase_of_eclipse(tc, base, location) >= 1
    category = 'A'
    t2, t3 = [-0.01, +0.01].map {|dt|               # 第2, 第3接触
      When::Ephemeris.root(tc+dt, 1.0) {|t|
        target.phase_of_eclipse(t, base, location)
      }
    }
  else
    category = 'P'
  end
  ts = [t1,t2,tc,t3,t4].compact

  form = When::Ephemeris::Formula.new(:location=>l_for_h[0])
  height, azimuth = ts.map {|t|                     # 基準天体の高度・方位角
     coord = form._coords(t, HORIZONTAL, l_for_h[1])
    [coord.theta * 360, ((0.5-coord.phi)-(0.5-coord.phi).floor) * 360]
  }.transpose
  return nil  unless height.max >= 0                # 見えない食
  category += 'B' if height.min <  0                # 地平線下で食が始まる/終わる

  [category, mag, [ts.map {|t| form._to_seed_type(t, date)}, height, azimuth].transpose]

rescue RangeError
  nil
end

#horizonNumeric

観測地での‘大地’の視半径

Returns:



1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
# File 'lib/when_exe/coordinates.rb', line 1432

def horizon
  # 地面以下なら 90度とみなす
  return 0.25 if @alt == :Center || @alt <= 0

  # 観測地の地心距離 / m
  r = obserber_distance * 1000.0

  # 大気効果
  air_effect = @datum.air[1] * @alt / (@datum.air[2] * @alt + r)

  # ‘大地’の視半径
  asin((1.0+air_effect) * r / (r+@alt)) / CIRCLE
end

#lat_sString

緯度文字列

Parameters:

  • round (Integer)

    秒の小数点以下最大桁数

Returns:



1398
1399
1400
# File 'lib/when_exe/coordinates.rb', line 1398

def lat_s
  When::Coordinates.to_dms(lat / When::Coordinates::Spatial::DEGREE, 'NS', round=6)
end

#local_sidereal_time(t) ⇒ Numeric

観測地の地方恒星時 / 時を返します。

Parameters:

Returns:



1453
1454
1455
1456
1457
1458
1459
1460
# File 'lib/when_exe/coordinates.rb', line 1453

def local_sidereal_time(t)
  t = +t
  c = julian_century_from_2000(t)
  result  = @datum.sid[0] + c * (@datum.sid[1] + c * @datum.sid[2]) + @long / (15.0 * DEGREE)
  result += (cosc(obl(c)) * delta_p(c) +
             (t-When::TimeStandard.delta_t_observed(t)/86400+0.5) % 1) * 24 if @datum.kind_of?(Earth)
  result
end

#long_sString

経度文字列

Parameters:

  • round (Integer)

    秒の小数点以下最大桁数

Returns:



1408
1409
1410
# File 'lib/when_exe/coordinates.rb', line 1408

def long_s
  When::Coordinates.to_dms(long / When::Coordinates::Spatial::DEGREE, 'EW', round=6)
end

#lunar_eclipse(date, &block) ⇒ Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>

月食の情報

Parameters:

Returns:



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/when_exe/ephemeris/eclipse.rb', line 61

def lunar_eclipse(date, &block)
  if date.kind_of?(Range)
    last  = date.last.to_i
    last -= 1 if date.exclude_end?
    first = date.first.to_i
    date  = date.first
  end
  clock = date.clock && (date.clock.tz_prop || date.clock.label)
  cn    = (@mean.time_to_cn(date)+0.25).floor+0.5
  list  = []
  loop do
    unless @ecls.key?([cn,clock.to_s])
      time = @mean.cn_to_time(cn)
      data = EclipseRange.include?(time % EclipseHalfYear) ?
               eclipse_info(@mean._to_seed_type(time, date), When.Resource('_ep:Earth'), When.Resource('_ep:Moon'),
                 When.Resource('_ep:Shadow'), [self, When.Resource('_ep:Moon')]) : nil
      @ecls[[cn,clock.to_s]] = data ? [(data[2][data[2].size / 2][0]-When::PT6H).to_i, data] : nil
    end
    key, info = @ecls[[cn,clock.to_s]]
    return info unless first
    list << (block_given? ? yield(info) : info) if key && first <= key && key <= last
    break if (key || first) >= last
    cn += 1
  end
  return list
end

#obserber_distanceNumeric

観測地の地心距離 / kmを返します。

Returns:



1423
1424
1425
1426
# File 'lib/when_exe/coordinates.rb', line 1423

def obserber_distance
  l = PI / (90 * DEGREE) * @lat
  @datum.surface_radius * (@datum.shape[0]+@datum.shape[1]*cos(l)+@datum.shape[2]*cos(2*l))
end

#solar_eclipse(date, &block) ⇒ Array<String, Numeric, Array<Array<Numeric or When::TM::TemporalPosition, String>>>

日食の情報

Parameters:

Returns:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/when_exe/ephemeris/eclipse.rb', line 25

def solar_eclipse(date, &block)
  if date.kind_of?(Range)
    last  = date.last.to_i
    last -= 1 if date.exclude_end?
    first = date.first.to_i
    date  = date.first
  end
  clock = date.clock && (date.clock.tz_prop || date.clock.label)
  cn    = @mean.time_to_cn(date).round
  list  = []
  loop do
    unless @ecls.key?([cn,clock.to_s])
      time = @mean.cn_to_time(cn)
      data = EclipseRange.include?(time % EclipseHalfYear) ?
              eclipse_info(@mean._to_seed_type(time, date), self, When.Resource('_ep:Sun'), When.Resource('_ep:Moon')) : nil
      @ecls[[cn,clock.to_s]] = data ? [data[2][data[2].size / 2][0].to_i, data] : nil
    end
    key, info = @ecls[[cn,clock.to_s]]
    return info unless first
    list << (block_given? ? yield(info) : info) if key && first <= key && key <= last
    break if (key || first) >= last
    cn += 1
  end
  return list
end