def greatCircle(self, bearing):
        '''Compute the n-vector normal to great circle obtained by
           heading on given compass bearing from this point as its
           n-vector.

           Direction of vector is such that initial bearing vector
           b = c × p.

           @arg bearing: Initial compass bearing (C{degrees}).

           @return: N-vector representing great circle (L{Nvector}).

           @raise Valuerror: Polar coincidence.

           @example:

           >>> n = LatLon(53.3206, -1.7297).toNvector()
           >>> gc = n.greatCircle(96.0)  # [-0.794, 0.129, 0.594]
        '''
        s, c = sincos2d(Bearing(bearing))

        e = NorthPole.cross(self, raiser=_pole_)  # easting
        n = self.cross(e, raiser=_point_)  # northing

        e = e.times(c / e.length)
        n = n.times(s / n.length)
        return n.minus(e)
    def destination(self, distance, bearing, radius=R_M, height=None):
        '''Locate the destination from this point after having
           travelled the given distance on the given bearing.

           @param distance: Distance travelled (C{meter}, same units
                            as B{C{radius}}).
           @param bearing: Bearing from this point (compass C{degrees360}).
           @keyword radius: Mean earth radius (C{meter}).
           @keyword height: Optional height at destination, overriding
                            the default height (C{meter}, same units as
                            B{C{radius}}).

           @return: Destination point (L{LatLon}).

           @raise Valuerror: Polar coincidence.

           @example:

           >>> p = LatLon(51.4778, -0.0015)
           >>> q = p.destination(7794, 300.7)
           >>> q.toStr()  # 51.513546°N, 000.098345°W

           @JSname: I{destinationPoint}.
        '''
        p = self.toNvector()

        e = NorthPole.cross(p, raiser='pole').unit()  # east vector at p
        n = p.cross(e)  # north vector at p

        s, c = sincos2d(bearing)
        q = n.times(c).plus(e.times(s))  # direction vector @ p

        s, c = sincos2(float(distance) / float(radius))  # angular distance in radians
        n = p.times(c).plus(q.times(s))
        return n.toLatLon(height=height, LatLon=self.classof)  # Nvector(n.x, n.y, n.z).toLatLon(...)
    def destination(self, distance, bearing, radius=R_M, height=None):
        '''Locate the destination from this point after having
           travelled the given distance on the given bearing.

           @arg distance: Distance travelled (C{meter}, same units
                          as B{C{radius}}).
           @arg bearing: Bearing from this point (compass C{degrees360}).
           @kwarg radius: Mean earth radius (C{meter}).
           @kwarg height: Optional height at destination, overriding the
                          default height (C{meter}, same units as B{C{radius}}).

           @return: Destination point (L{LatLon}).

           @raise Valuerror: Polar coincidence ior invalid B{C{distance}},
                             B{C{bearing}}, B{C{radius}} or B{C{height}}.

           @example:

           >>> p = LatLon(51.4778, -0.0015)
           >>> q = p.destination(7794, 300.7)
           >>> q.toStr()  # 51.513546°N, 000.098345°W

           @JSname: I{destinationPoint}.
        '''
        a = _angular(distance, radius)
        sa, ca, sb, cb = sincos2(a, Bearing_(bearing))

        p = self.toNvector()
        e = NorthPole.cross(p, raiser=_pole_).unit()  # east vector at p
        n = p.cross(e)  # north vector at p
        q = n.times(cb).plus(e.times(sb))  # direction vector @ p
        n = p.times(ca).plus(q.times(sa))
        return n.toLatLon(height=height, LatLon=self.classof)  # Nvector(n.x, n.y, n.z).toLatLon(...)
 def _gc(p, b):
     n = p.toNvector()
     de = NorthPole.cross(n, raiser='pole').unit()  # east vector @ n
     dn = n.cross(de)  # north vector @ n
     s, c = sincos2d(b)
     dest = de.times(s)
     dnct = dn.times(c)
     d = dnct.plus(dest)  # direction vector @ n
     return n.cross(d)  # great circle point + bearing
    def _rotation3(self):
        '''(INTERNAL) Build the rotation matrix from n-vector
           coordinate frame axes.
        '''
        if self._r3 is None:
            nv = self.toNvector()  # local (n-vector) coordinate frame

            d = nv.negate()  # down (opposite to n-vector)
            e = NorthPole.cross(nv, raiser=_pole_).unit()  # east (pointing perpendicular to the plane)
            n = e.cross(d)  # north (by right hand rule)

            self._r3 = n, e, d  # matrix rows
        return self._r3