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 
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 


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

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)

    天体の中心の場合



1368
1369
1370
# File 'lib/when_exe/coordinates.rb', line 1368

def alt
  @alt
end

#datumWhen::Ephemeris::Datum (readonly)

座標系



1374
1375
1376
# File 'lib/when_exe/coordinates.rb', line 1374

def datum
  @datum
end

#latNumeric (readonly)

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

Returns:



1355
1356
1357
# File 'lib/when_exe/coordinates.rb', line 1355

def lat
  @lat
end

#longNumeric (readonly)

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

Returns:



1361
1362
1363
# File 'lib/when_exe/coordinates.rb', line 1361

def long
  @long
end

#refString (readonly)

参照

Returns:



1380
1381
1382
# File 'lib/when_exe/coordinates.rb', line 1380

def ref
  @ref
end

#tzTZInfo::CountryTimezone (readonly)

時間帯(オプショナル)

Returns:

  • (TZInfo::CountryTimezone)

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



1388
1389
1390
# File 'lib/when_exe/coordinates.rb', line 1388

def tz
  @tz
end

Class Method Details

._setup_(location = nil) ⇒ void

Note:

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

This method returns an undefined value.

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

Parameters:



1263
1264
1265
1266
1267
# File 'lib/when_exe/coordinates.rb', line 1263

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

._setup_infoHash

設定情報を取得する

Returns:

  • (Hash)

    設定情報



1291
1292
1293
# File 'lib/when_exe/coordinates.rb', line 1291

def _setup_info
  {:location => @default_location}
end

.default_locationWhen::Coordinates::Spatial

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



1299
1300
1301
# File 'lib/when_exe/coordinates.rb', line 1299

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:



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

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)


1307
1308
1309
1310
# File 'lib/when_exe/coordinates.rb', line 1307

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

Instance Method Details

#_coords(t) ⇒ Numeric

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

Parameters:

Returns:



1467
1468
1469
1470
# File 'lib/when_exe/coordinates.rb', line 1467

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:



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

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:



1396
1397
1398
# File 'lib/when_exe/coordinates.rb', line 1396

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

#local_sidereal_time(t) ⇒ Numeric

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

Parameters:

Returns:



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

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:



1406
1407
1408
# File 'lib/when_exe/coordinates.rb', line 1406

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:



1421
1422
1423
1424
# File 'lib/when_exe/coordinates.rb', line 1421

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