Class: When::Coordinates::Spatial

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

Overview

Copyright © 2014-2015 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 Classes: Range

Constant Summary collapse

LabelProperty =
'label'
HashProperty =
[:label, :longitude, :latitude, [:altitude, 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::IRIDecode, Parts::Resource::IRIDecodeTable, Parts::Resource::IRIEncode, Parts::Resource::IRIEncodeTable, Parts::Resource::IRIHeader

Constants included from Namespace

Namespace::DC, Namespace::DCQ, Namespace::DCT, Namespace::FOAF, Namespace::OWL, Namespace::RDF, Namespace::RDFC, Namespace::RDFS, Namespace::RSS, Namespace::XSD

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, #parent, #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) に委譲する


327
328
329
330
331
332
333
334
# File 'lib/when_exe/spatial.rb', line 327

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) Also known as: altitude

高度 / m

Returns:

  • (Numeric)
  • (:Center)

    天体の中心の場合



146
147
148
# File 'lib/when_exe/spatial.rb', line 146

def alt
  @alt
end

#datumWhen::Ephemeris::Datum (readonly)

座標系



153
154
155
# File 'lib/when_exe/spatial.rb', line 153

def datum
  @datum
end

#degreeNumeric (readonly)

角度の単位 (1 => 1度, 225=> 1/225 度)

Returns:



127
128
129
# File 'lib/when_exe/spatial.rb', line 127

def degree
  @degree
end

#latNumeric (readonly)

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

Returns:



133
134
135
# File 'lib/when_exe/spatial.rb', line 133

def lat
  @lat
end

#longNumeric (readonly)

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

Returns:



139
140
141
# File 'lib/when_exe/spatial.rb', line 139

def long
  @long
end

#refString (readonly)

参照

Returns:



159
160
161
# File 'lib/when_exe/spatial.rb', line 159

def ref
  @ref
end

#tzTZInfo::CountryTimezone (readonly)

時間帯(オプショナル)

Returns:

  • (TZInfo::CountryTimezone)

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



167
168
169
# File 'lib/when_exe/spatial.rb', line 167

def tz
  @tz
end

Class Method Details

._setup_(location = nil) ⇒ void

Note:

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

This method returns an undefined value.

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

Parameters:



35
36
37
38
39
# File 'lib/when_exe/spatial.rb', line 35

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

._setup_infoHash

設定情報を取得する

Returns:

  • (Hash)

    設定情報



63
64
65
# File 'lib/when_exe/spatial.rb', line 63

def _setup_info
  {:location => @default_location}
end

.default_locationWhen::Coordinates::Spatial

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



71
72
73
# File 'lib/when_exe/spatial.rb', line 71

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:



51
52
53
54
55
56
57
# File 'lib/when_exe/spatial.rb', line 51

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)


79
80
81
82
# File 'lib/when_exe/spatial.rb', line 79

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

Instance Method Details

#_coords(t) ⇒ Numeric

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

Parameters:

Returns:



248
249
250
251
# File 'lib/when_exe/spatial.rb', line 248

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:



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
149
# File 'lib/when_exe/ephemeris/eclipse.rb', line 104

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:



211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/when_exe/spatial.rb', line 211

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_s(round = 6) ⇒ String Also known as: latitude

緯度文字列

Parameters:

  • round (Integer) (defaults to: 6)

    秒の小数点以下最大桁数

Returns:



175
176
177
# File 'lib/when_exe/spatial.rb', line 175

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

#local_sidereal_time(t) ⇒ Numeric

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

Parameters:

Returns:



232
233
234
235
236
237
238
239
# File 'lib/when_exe/spatial.rb', line 232

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_s(round = 6) ⇒ String Also known as: longitude

経度文字列

Parameters:

  • round (Integer) (defaults to: 6)

    秒の小数点以下最大桁数

Returns:



186
187
188
# File 'lib/when_exe/spatial.rb', line 186

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

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

月食の情報

Parameters:

Returns:



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
87
# File 'lib/when_exe/ephemeris/eclipse.rb', line 62

def lunar_eclipse(date, margin=When::PT6H, &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]-margin).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:



202
203
204
205
# File 'lib/when_exe/spatial.rb', line 202

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