1 """Define the :class:`~geographiclib.geodesicline.GeodesicLine` class 3 The constructor defines the starting point of the line. Points on the 6 * :meth:`~geographiclib.geodesicline.GeodesicLine.Position` position 7 given in terms of distance 8 * :meth:`~geographiclib.geodesicline.GeodesicLine.ArcPosition` position 9 given in terms of spherical arc length 11 A reference point 3 can be defined with 13 * :meth:`~geographiclib.geodesicline.GeodesicLine.SetDistance` set 14 position of 3 in terms of the distance from the starting point 15 * :meth:`~geographiclib.geodesicline.GeodesicLine.SetArc` set 16 position of 3 in terms of the spherical arc length from the starting point 18 The object can also be constructed by 20 * :meth:`Geodesic.Line <geographiclib.geodesic.Geodesic.Line>` 21 * :meth:`Geodesic.DirectLine <geographiclib.geodesic.Geodesic.DirectLine>` 22 * :meth:`Geodesic.ArcDirectLine 23 <geographiclib.geodesic.Geodesic.ArcDirectLine>` 24 * :meth:`Geodesic.InverseLine <geographiclib.geodesic.Geodesic.InverseLine>` 26 The public attributes for this class are 28 * :attr:`~geographiclib.geodesicline.GeodesicLine.a` 29 :attr:`~geographiclib.geodesicline.GeodesicLine.f` 30 :attr:`~geographiclib.geodesicline.GeodesicLine.caps` 31 :attr:`~geographiclib.geodesicline.GeodesicLine.lat1` 32 :attr:`~geographiclib.geodesicline.GeodesicLine.lon1` 33 :attr:`~geographiclib.geodesicline.GeodesicLine.azi1` 34 :attr:`~geographiclib.geodesicline.GeodesicLine.salp1` 35 :attr:`~geographiclib.geodesicline.GeodesicLine.calp1` 36 :attr:`~geographiclib.geodesicline.GeodesicLine.s13` 37 :attr:`~geographiclib.geodesicline.GeodesicLine.a13` 64 """Points on a geodesic path""" 66 def __init__(self, geod, lat1, lon1, azi1,
67 caps = GeodesicCapability.STANDARD |
68 GeodesicCapability.DISTANCE_IN,
69 salp1 = Math.nan, calp1 = Math.nan):
70 """Construct a GeodesicLine object 72 :param geod: a :class:`~geographiclib.geodesic.Geodesic` object 73 :param lat1: latitude of the first point in degrees 74 :param lon1: longitude of the first point in degrees 75 :param azi1: azimuth at the first point in degrees 76 :param caps: the :ref:`capabilities <outmask>` 78 This creates an object allowing points along a geodesic starting at 79 (*lat1*, *lon1*), with azimuth *azi1* to be found. The default 80 value of *caps* is STANDARD | DISTANCE_IN. The optional parameters 81 *salp1* and *calp1* should not be supplied; they are part of the 88 """The equatorial radius in meters (readonly)""" 90 """The flattening (readonly)""" 94 self.
caps = (caps | Geodesic.LATITUDE | Geodesic.AZIMUTH |
96 """the capabilities (readonly)""" 99 self.
lat1 = Math.LatFix(lat1)
100 """the latitude of the first point in degrees (readonly)""" 102 """the longitude of the first point in degrees (readonly)""" 103 if Math.isnan(salp1)
or Math.isnan(calp1):
104 self.
azi1 = Math.AngNormalize(azi1)
108 """the azimuth at the first point in degrees (readonly)""" 110 """the sine of the azimuth at the first point (readonly)""" 112 """the cosine of the azimuth at the first point (readonly)""" 115 sbet1, cbet1 = Math.sincosd(Math.AngRound(lat1)); sbet1 *= self.
_f1 117 sbet1, cbet1 = Math.norm(sbet1, cbet1); cbet1 =
max(Geodesic.tiny_, cbet1)
118 self.
_dn1 = math.sqrt(1 + geod._ep2 * Math.sq(sbet1))
136 if sbet1 != 0
or self.
calp1 != 0
else 1)
143 eps = self.
_k2 / (2 * (1 + math.sqrt(1 + self.
_k2)) + self.
_k2)
145 if self.
caps & Geodesic.CAP_C1:
148 Geodesic._C1f(eps, self.
_C1a)
149 self.
_B11 = Geodesic._SinCosSeries(
151 s = math.sin(self.
_B11); c = math.cos(self.
_B11)
158 if self.
caps & Geodesic.CAP_C1p:
160 Geodesic._C1pf(eps, self.
_C1pa)
162 if self.
caps & Geodesic.CAP_C2:
165 Geodesic._C2f(eps, self.
_C2a)
166 self.
_B21 = Geodesic._SinCosSeries(
169 if self.
caps & Geodesic.CAP_C3:
171 geod._C3f(eps, self.
_C3a)
173 self.
_B31 = Geodesic._SinCosSeries(
176 if self.
caps & Geodesic.CAP_C4:
178 geod._C4f(eps, self.
_C4a)
181 self.
_B41 = Geodesic._SinCosSeries(
184 """the distance between point 1 and point 3 in meters (readonly)""" 186 """the arc length between point 1 and point 3 in degrees (readonly)""" 190 """Private: General solution of position along geodesic""" 192 a12 = lat2 = lon2 = azi2 = s12 = m12 = M12 = M21 = S12 = Math.nan
193 outmask &= self.
caps & Geodesic.OUT_MASK
195 (self.
caps & (Geodesic.OUT_MASK & Geodesic.DISTANCE_IN))):
197 return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
203 sig12 = math.radians(s12_a12)
204 ssig12, csig12 = Math.sincosd(s12_a12)
207 tau12 = s12_a12 / (self.
_b * (1 + self.
_A1m1))
208 s = math.sin(tau12); c = math.cos(tau12)
210 B12 = - Geodesic._SinCosSeries(
True,
214 sig12 = tau12 - (B12 - self.
_B11)
215 ssig12 = math.sin(sig12); csig12 = math.cos(sig12)
216 if abs(self.
f) > 0.01:
240 B12 = Geodesic._SinCosSeries(
True, ssig2, csig2, self.
_C1a)
241 serr = ((1 + self.
_A1m1) * (sig12 + (B12 - self.
_B11)) -
243 sig12 = sig12 - serr / math.sqrt(1 + self.
_k2 * Math.sq(ssig2))
244 ssig12 = math.sin(sig12); csig12 = math.cos(sig12)
252 dn2 = math.sqrt(1 + self.
_k2 * Math.sq(ssig2))
254 Geodesic.DISTANCE | Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
255 if arcmode
or abs(self.
f) > 0.01:
256 B12 = Geodesic._SinCosSeries(
True, ssig2, csig2, self.
_C1a)
257 AB1 = (1 + self.
_A1m1) * (B12 - self.
_B11)
259 sbet2 = self.
_calp0 * ssig2
264 cbet2 = csig2 = Geodesic.tiny_
268 if outmask & Geodesic.DISTANCE:
269 s12 = self.
_b * ((1 + self.
_A1m1) * sig12 + AB1)
if arcmode
else s12_a12
271 if outmask & Geodesic.LONGITUDE:
273 somg2 = self.
_salp0 * ssig2; comg2 = csig2
274 E = Math.copysign(1, self.
_salp0)
277 - (math.atan2( ssig2, csig2) -
279 + (math.atan2(E * somg2, comg2) -
281 if outmask & Geodesic.LONG_UNROLL
282 else math.atan2(somg2 * self.
_comg1 - comg2 * self.
_somg1,
284 lam12 = omg12 + self.
_A3c * (
285 sig12 + (Geodesic._SinCosSeries(
True, ssig2, csig2, self.
_C3a)
287 lon12 = math.degrees(lam12)
288 lon2 = (self.
lon1 + lon12
if outmask & Geodesic.LONG_UNROLL
else 289 Math.AngNormalize(Math.AngNormalize(self.
lon1) +
290 Math.AngNormalize(lon12)))
292 if outmask & Geodesic.LATITUDE:
293 lat2 = Math.atan2d(sbet2, self.
_f1 * cbet2)
295 if outmask & Geodesic.AZIMUTH:
296 azi2 = Math.atan2d(salp2, calp2)
298 if outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
299 B22 = Geodesic._SinCosSeries(
True, ssig2, csig2, self.
_C2a)
300 AB2 = (1 + self.
_A2m1) * (B22 - self.
_B21)
301 J12 = (self.
_A1m1 - self.
_A2m1) * sig12 + (AB1 - AB2)
302 if outmask & Geodesic.REDUCEDLENGTH:
305 m12 = self.
_b * (( dn2 * (self.
_csig1 * ssig2) -
307 - self.
_csig1 * csig2 * J12)
308 if outmask & Geodesic.GEODESICSCALE:
311 M12 = csig12 + (t * ssig2 - csig2 * J12) * self.
_ssig1 / self.
_dn1 312 M21 = csig12 - (t * self.
_ssig1 - self.
_csig1 * J12) * ssig2 / dn2
314 if outmask & Geodesic.AREA:
315 B42 = Geodesic._SinCosSeries(
False, ssig2, csig2, self.
_C4a)
319 salp12 = salp2 * self.
calp1 - calp2 * self.
salp1 320 calp12 = calp2 * self.
calp1 + salp2 * self.
salp1 331 self.
_csig1 * (1 - csig12) + ssig12 * self.
_ssig1 if csig12 <= 0
332 else ssig12 * (self.
_csig1 * ssig12 / (1 + csig12) + self.
_ssig1))
333 calp12 = (Math.sq(self.
_salp0) +
335 S12 = (self.
_c2 * math.atan2(salp12, calp12) +
338 a12 = s12_a12
if arcmode
else math.degrees(sig12)
339 return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
341 def Position(self, s12, outmask = GeodesicCapability.STANDARD):
342 """Find the position on the line given *s12* 344 :param s12: the distance from the first point to the second in 346 :param outmask: the :ref:`output mask <outmask>` 347 :return: a :ref:`dict` 349 The default value of *outmask* is STANDARD, i.e., the *lat1*, 350 *lon1*, *azi1*, *lat2*, *lon2*, *azi2*, *s12*, *a12* entries are 351 returned. The :class:`~geographiclib.geodesicline.GeodesicLine` 352 object must have been constructed with the DISTANCE_IN capability. 357 result = {
'lat1': self.
lat1,
358 'lon1': self.
lon1 if outmask & Geodesic.LONG_UNROLL
else 359 Math.AngNormalize(self.
lon1),
360 'azi1': self.
azi1,
's12': s12}
361 a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.
_GenPosition(
363 outmask &= Geodesic.OUT_MASK
365 if outmask & Geodesic.LATITUDE: result[
'lat2'] = lat2
366 if outmask & Geodesic.LONGITUDE: result[
'lon2'] = lon2
367 if outmask & Geodesic.AZIMUTH: result[
'azi2'] = azi2
368 if outmask & Geodesic.REDUCEDLENGTH: result[
'm12'] = m12
369 if outmask & Geodesic.GEODESICSCALE:
370 result[
'M12'] = M12; result[
'M21'] = M21
371 if outmask & Geodesic.AREA: result[
'S12'] = S12
374 def ArcPosition(self, a12, outmask = GeodesicCapability.STANDARD):
375 """Find the position on the line given *a12* 377 :param a12: spherical arc length from the first point to the second 379 :param outmask: the :ref:`output mask <outmask>` 380 :return: a :ref:`dict` 382 The default value of *outmask* is STANDARD, i.e., the *lat1*, 383 *lon1*, *azi1*, *lat2*, *lon2*, *azi2*, *s12*, *a12* entries are 389 result = {
'lat1': self.
lat1,
390 'lon1': self.
lon1 if outmask & Geodesic.LONG_UNROLL
else 391 Math.AngNormalize(self.
lon1),
392 'azi1': self.
azi1,
'a12': a12}
393 a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.
_GenPosition(
395 outmask &= Geodesic.OUT_MASK
396 if outmask & Geodesic.DISTANCE: result[
's12'] = s12
397 if outmask & Geodesic.LATITUDE: result[
'lat2'] = lat2
398 if outmask & Geodesic.LONGITUDE: result[
'lon2'] = lon2
399 if outmask & Geodesic.AZIMUTH: result[
'azi2'] = azi2
400 if outmask & Geodesic.REDUCEDLENGTH: result[
'm12'] = m12
401 if outmask & Geodesic.GEODESICSCALE:
402 result[
'M12'] = M12; result[
'M21'] = M21
403 if outmask & Geodesic.AREA: result[
'S12'] = S12
407 """Specify the position of point 3 in terms of distance 409 :param s13: distance from point 1 to point 3 in meters 414 self.
a13, _, _, _, _, _, _, _, _ = self.
_GenPosition(
False, self.
s13, 0)
417 """Specify the position of point 3 in terms of arc length 419 :param a13: spherical arc length from point 1 to point 3 in degrees 425 _, _, _, _, self.
s13, _, _, _, _ = self.
_GenPosition(
True, self.
a13,
def Position(self, s12, outmask=GeodesicCapability.STANDARD)
def ArcPosition(self, a12, outmask=GeodesicCapability.STANDARD)
def _GenPosition(self, arcmode, s12_a12, outmask)
def SetDistance(self, s13)
def __init__(self, geod, lat1, lon1, azi1, caps=GeodesicCapability.STANDARD|GeodesicCapability.DISTANCE_IN, salp1=Math.nan, calp1=Math.nan)