def _rhumb3(self, other): '''(INTERNAL) Rhumb_ helper function. @param other: The other point (spherical C{LatLon}). ''' self.others(other) a1, b1 = self.to2ab() a2, b2 = other.to2ab() # if |db| > 180 take shorter rhumb # line across the anti-meridian db = wrapPI(b2 - b1) dp = log(tanPI_2_2(a2) / tanPI_2_2(a1)) return (a2 - a1), db, dp
def rhumbMidpointTo(self, other, height=None): '''Return the (loxodromic) midpoint between this and an other point. @param other: The other point (spherical LatLon). @keyword height: Optional height, overriding the mean height (C{meter}). @return: The midpoint (spherical C{LatLon}). @raise TypeError: The I{other} point is not spherical. @example: >>> p = LatLon(51.127, 1.338) >>> q = LatLon(50.964, 1.853) >>> m = p.rhumb_midpointTo(q) >>> m.toStr() # '51.0455°N, 001.5957°E' ''' self.others(other) # see <https://MathForum.org/library/drmath/view/51822.html> a1, b1 = self.to2ab() a2, b2 = other.to2ab() if abs(b2 - b1) > PI: b1 += PI2 # crossing anti-meridian a3 = favg(a1, a2) b3 = favg(b1, b2) f1 = tanPI_2_2(a1) if abs(f1) > EPS: f2 = tanPI_2_2(a2) f = f2 / f1 if abs(f) > EPS: f = log(f) if abs(f) > EPS: f3 = tanPI_2_2(a3) b3 = fsum_(b1 * log(f2), -b2 * log(f1), (b2 - b1) * log(f3)) / f h = self._havg(other) if height is None else height return self.classof(degrees90(a3), degrees180(b3), height=h)
def rhumbDestination(self, distance, bearing, radius=R_M, height=None): '''Return the destination point having travelled along a rhumb (loxodrome) line from this point the given distance on the given bearing. @param distance: Distance travelled (C{meter}, same units as I{radius}). @param bearing: Bearing from this point (compass C{degrees360}). @keyword radius: Optional, mean earth radius (C{meter}). @keyword height: Optional height, overriding the default height (C{meter}, same unit as I{radius}). @return: The destination point (spherical C{LatLon}). @example: >>> p = LatLon(51.127, 1.338) >>> q = p.rhumbDestination(40300, 116.7) # 50.9642°N, 001.8530°E @JSname: I{rhumbDestinationPoint} ''' a1, b1 = self.to2ab() r = float(distance) / float(radius) # angular distance in radians sb, cb = sincos2d(bearing) da = r * cb a2 = a1 + da # normalize latitude if past pole if a2 > PI_2: a2 = PI - a2 elif a2 < -PI_2: a2 = -PI - a2 dp = log(tanPI_2_2(a2) / tanPI_2_2(a1)) # E-W course becomes ill-conditioned with 0/0 q = (da / dp) if abs(dp) > EPS else cos(a1) b2 = (b1 + r * sb / q) if abs(q) > EPS else b1 h = self.height if height is None else height return self.classof(degrees90(a2), degrees180(b2), height=h)
def _tdef(self, lat): '''(INTERNAL) Compute t(lat). ''' return max(0, tanPI_2_2(-lat) / self._pdef(lat))