def testSeparationValueGeneric(self):
        """Test if separation() returns the correct value.
        """
        # This should cover arcs over the meridian, across the pole, etc.
        # Do not use sphgeom as an oracle, in case SpherePoint uses it
        # internally.
        for lon1, lat1 in self._dataset:
            point1 = SpherePoint(lon1, lat1)
            x1, y1, z1 = SpherePointTestSuite.toVector(lon1, lat1)
            for lon2, lat2 in self._dataset:
                point2 = SpherePoint(lon2, lat2)
                if lon1 != lon2 or lat1 != lat2:
                    # Numerically unstable at small angles, but that's ok.
                    x2, y2, z2 = SpherePointTestSuite.toVector(lon2, lat2)
                    expected = math.acos(x1 * x2 + y1 * y2 + z1 * z2)
                else:
                    expected = 0.0

                sep = point1.separation(point2)
                self.assertIsInstance(sep, afwGeom.Angle)
                if point1.isFinite() and point2.isFinite():
                    self.assertGreaterEqual(sep.asDegrees(), 0.0)
                    self.assertLessEqual(sep.asDegrees(), 180.0)
                    self.assertAlmostEqual(expected, sep.asRadians())
                    self.assertAnglesAlmostEqual(sep,
                                                 point2.separation(point1))
                else:
                    self.assertTrue(math.isnan(sep.asRadians()))
                    self.assertTrue(
                        math.isnan(point2.separation(point1).asRadians()))
Beispiel #2
0
    def testBearingToValue(self):
        """Test if bearingTo() returns the expected value.
        """
        lon0 = 90.0
        lat0 = 0.0   # These tests only work from the equator.
        arcLen = 10.0

        trials = [
            # Along celestial equator
            dict(lon=lon0, lat=lat0, bearing=0.0,
                 lonEnd=lon0+arcLen, latEnd=lat0),
            # Along a meridian
            dict(lon=lon0, lat=lat0, bearing=90.0,
                 lonEnd=lon0, latEnd=lat0+arcLen),
            # 180 degree arc (should go to antipodal point)
            dict(lon=lon0, lat=lat0, bearing=45.0,
                 lonEnd=lon0+180.0, latEnd=-lat0),
            #
            dict(lon=lon0, lat=lat0, bearing=45.0,
                 lonEnd=lon0+90.0, latEnd=lat0 + 45.0),
            dict(lon=lon0, lat=lat0, bearing=225.0,
                 lonEnd=lon0-90.0, latEnd=lat0 - 45.0),
            dict(lon=lon0, lat=np.nextafter(-90.0, inf),
                 bearing=90.0, lonEnd=lon0, latEnd=0.0),
            dict(lon=lon0, lat=np.nextafter(-90.0, inf),
                 bearing=0.0, lonEnd=lon0 + 90.0, latEnd=0.0),
            # Argument at a pole should work
            dict(lon=lon0, lat=lat0, bearing=270.0, lonEnd=lon0, latEnd=-90.0),
            # Support for non-finite values
            dict(lon=lon0, lat=nan, bearing=nan, lonEnd=lon0, latEnd=45.0),
            dict(lon=lon0, lat=lat0, bearing=nan, lonEnd=nan, latEnd=90.0),
            dict(lon=inf, lat=lat0, bearing=nan, lonEnd=lon0, latEnd=42.0),
            dict(lon=lon0, lat=lat0, bearing=nan, lonEnd=-inf, latEnd=42.0),
        ]

        for trial in trials:
            origin = SpherePoint(trial['lon']*degrees, trial['lat']*degrees)
            end = SpherePoint(trial['lonEnd']*degrees, trial['latEnd']*degrees)
            bearing = origin.bearingTo(end)

            self.assertIsInstance(bearing, afwGeom.Angle)
            if origin.isFinite() and end.isFinite():
                self.assertGreaterEqual(bearing.asDegrees(), 0.0)
                self.assertLess(bearing.asDegrees(), 360.0)
            if origin.separation(end).asDegrees() != 180.0:
                if not math.isnan(trial['bearing']):
                    self.assertAlmostEqual(
                        trial['bearing'], bearing.asDegrees(), 12)
                else:
                    self.assertTrue(math.isnan(bearing.asRadians()))
    def testEquality(self):
        """Test if tests for equality treat SpherePoints as values.
        """
        # (In)equality is determined by value, not identity.
        # See DM-2347, DM-2465. These asserts are testing the
        # functionality of `==` and `!=` and should not be changed.
        for lon1, lat1 in self._dataset:
            point1 = SpherePoint(lon1, lat1)
            self.assertIsInstance(point1 == point1, bool)
            self.assertIsInstance(point1 != point1, bool)
            if point1.isFinite():
                self.assertTrue(point1 == point1)
                self.assertFalse(point1 != point1)

                pointCopy = copy.deepcopy(point1)
                self.assertIsNot(pointCopy, point1)
                self.assertEqual(pointCopy, point1)
                self.assertEqual(point1, pointCopy)
                self.assertFalse(pointCopy != point1)
                self.assertFalse(point1 != pointCopy)
            else:
                self.assertFalse(point1 == point1)
                self.assertTrue(point1 != point1)

            for lon2, lat2 in self._dataset:
                point2 = SpherePoint(lon2, lat2)
                if lon1 == lon2 and lat1 == lat2 and point1.isFinite(
                ) and point2.isFinite():
                    # note: the isFinite checks are needed because if longitude is infinite
                    # then the resulting SpherePoint has nan as its longitude, due to wrapping
                    self.assertFalse(point2 != point1)
                    self.assertFalse(point1 != point2)
                    self.assertTrue(point2 == point1)
                    self.assertTrue(point1 == point2)
                else:
                    self.assertTrue(point2 != point1)
                    self.assertTrue(point1 != point2)
                    self.assertFalse(point2 == point1)
                    self.assertFalse(point1 == point2)

        # Test for transitivity (may be assumed by algorithms).
        for delta in [10.0**(0.1 * x) for x in range(-150, -49, 5)]:
            self.checkTransitive(delta * radians)
Beispiel #4
0
 def testGetLatitudeValue(self):
     """Test if getLatitude() returns the expected value.
     """
     for lon, lat in self._dataset:
         point = SpherePoint(lon, lat)
         self.assertIsInstance(point.getLatitude(), afwGeom.Angle)
         # Behavior for non-finite points is undefined; depends on internal
         # data representation
         if point.isFinite():
             self.assertGreaterEqual(point.getLatitude().asDegrees(), -90.0)
             self.assertLessEqual(point.getLatitude().asDegrees(), 90.0)
             self.assertAnglesAlmostEqual(lat, point.getLatitude())
Beispiel #5
0
    def testOffsetValue(self):
        """Test if offset() returns the expected value.
        """
        # This should cover arcs over the meridian, across the pole, etc.
        for lon1, lat1 in self._dataset:
            point1 = SpherePoint(lon1, lat1)
            if point1.atPole():
                continue
            for lon2, lat2 in self._dataset:
                if lon1 == lon2 and lat1 == lat2:
                    continue
                point2 = SpherePoint(lon2, lat2)
                bearing = point1.bearingTo(point2)
                distance = point1.separation(point2)

                newPoint = point1.offset(bearing, distance)
                self.assertIsInstance(newPoint, SpherePoint)
                if point1.isFinite() and point2.isFinite():
                    if not point2.atPole():
                        self.assertAnglesAlmostEqual(
                            point2.getLongitude(), newPoint.getLongitude())
                    self.assertAnglesAlmostEqual(
                        point2.getLatitude(), newPoint.getLatitude())
                else:
                    self.assertTrue(math.isnan(
                        newPoint.getLongitude().asRadians()))
                    self.assertTrue(math.isnan(
                        newPoint.getLatitude().asRadians()))

        # Test precision near the poles
        lon = 123.0*degrees
        almostPole = SpherePoint(lon, self.nextDown(90.0*degrees))
        goSouth = almostPole.offset(-90.0*degrees, 90.0*degrees)
        self.assertAnglesAlmostEqual(lon, goSouth.getLongitude())
        self.assertAnglesAlmostEqual(0.0*degrees, goSouth.getLatitude())
        goEast = almostPole.offset(0.0*degrees, 90.0*degrees)
        self.assertAnglesAlmostEqual(lon + 90.0*degrees, goEast.getLongitude())
        self.assertAnglesAlmostEqual(0.0*degrees, goEast.getLatitude())
Beispiel #6
0
    def testIterResult(self):
        """Test if iteration returns the expected values.
        """
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            if point.isFinite():
                # Test mechanics directly
                it = iter(point)
                self.assertEqual(point.getLongitude(), next(it))
                self.assertEqual(point.getLatitude(), next(it))
                with self.assertRaises(StopIteration):
                    next(it)

                # Intended use case
                lon, lat = point
                self.assertEqual(point.getLongitude(), lon)
                self.assertEqual(point.getLatitude(), lat)
Beispiel #7
0
    def testGetLongitudeValue(self):
        """Test if getLongitude() returns the expected value.
        """
        for lon, lat in self._dataset:
            point = SpherePoint(lon, lat)
            self.assertIsInstance(point.getLongitude(), afwGeom.Angle)
            # Behavior for non-finite points is undefined; depends on internal
            # data representation
            if point.isFinite():
                self.assertGreaterEqual(point.getLongitude().asDegrees(), 0.0)
                self.assertLess(point.getLongitude().asDegrees(), 360.0)

                # Longitude not guaranteed to match input at pole
                if not point.atPole():
                    # assertAnglesAlmostEqual handles angle wrapping internally
                    self.assertAnglesAlmostEqual(lon, point.getLongitude())

        # Vector construction should return valid longitude even in edge cases.
        point = SpherePoint(afwGeom.Point3D(0.0, 0.0, -1.0))
        self.assertGreaterEqual(point.getLongitude().asDegrees(), 0.0)
        self.assertLess(point.getLongitude().asDegrees(), 360.0)
    def testOffsetValue(self):
        """Test if offset() returns the expected value.
        """
        # This should cover arcs over the meridian, across the pole, etc.
        for lon1, lat1 in self._dataset:
            point1 = SpherePoint(lon1, lat1)
            for lon2, lat2 in self._dataset:
                if lon1 == lon2 and lat1 == lat2:
                    continue
                point2 = SpherePoint(lon2, lat2)
                bearing = point1.bearingTo(point2)
                distance = point1.separation(point2)

                # offsetting point1 by bearing and distance should produce the same result as point2
                newPoint = point1.offset(bearing, distance)
                self.assertIsInstance(newPoint, SpherePoint)
                self.assertSpherePointsAlmostEqual(point2, newPoint)
                if newPoint.atPole():
                    self.assertAnglesAlmostEqual(newPoint.getLongitude(),
                                                 0 * degrees)

                # measuring the separation and bearing from point1 to the new point
                # should produce the requested separation and bearing
                measuredDistance = point1.separation(newPoint)
                self.assertAnglesAlmostEqual(measuredDistance, distance)
                if abs(measuredDistance.asDegrees() - 180) > 1e-5:
                    # The two points are not opposite each other on the sphere,
                    # so the bearing has a well defined value
                    measuredBearing = point1.bearingTo(newPoint)
                    self.assertAnglesAlmostEqual(measuredBearing, bearing)

                # offset by a negative amount in the opposite direction should produce the same result
                newPoint2 = point1.offset(bearing + 180 * degrees, -distance)
                self.assertIsInstance(newPoint2, SpherePoint)
                # check angular separation (longitude is checked below)
                self.assertSpherePointsAlmostEqual(newPoint, newPoint2)

                if point1.isFinite() and point2.isFinite():
                    if not point2.atPole():
                        self.assertAnglesAlmostEqual(point2.getLongitude(),
                                                     newPoint.getLongitude())
                        self.assertAnglesAlmostEqual(point2.getLongitude(),
                                                     newPoint2.getLongitude())
                    self.assertAnglesAlmostEqual(point2.getLatitude(),
                                                 newPoint.getLatitude())
                    self.assertAnglesAlmostEqual(point2.getLatitude(),
                                                 newPoint2.getLatitude())
                else:
                    self.assertTrue(
                        math.isnan(newPoint.getLongitude().asRadians()))
                    self.assertTrue(
                        math.isnan(newPoint2.getLongitude().asRadians()))
                    self.assertTrue(
                        math.isnan(newPoint.getLatitude().asRadians()))
                    self.assertTrue(
                        math.isnan(newPoint2.getLatitude().asRadians()))

        # Test precision near the poles
        lon = 123.0 * degrees
        almostPole = SpherePoint(lon, self.nextDown(90.0 * degrees))
        goSouth = almostPole.offset(-90.0 * degrees, 90.0 * degrees)
        self.assertAnglesAlmostEqual(lon, goSouth.getLongitude())
        self.assertAnglesAlmostEqual(0.0 * degrees, goSouth.getLatitude())
        goEast = almostPole.offset(0.0 * degrees, 90.0 * degrees)
        self.assertAnglesAlmostEqual(lon + 90.0 * degrees,
                                     goEast.getLongitude())
        self.assertAnglesAlmostEqual(0.0 * degrees, goEast.getLatitude())
 def testDefaultConstructor(self):
     sp = SpherePoint()
     self.assertTrue(math.isnan(sp.getLongitude()))
     self.assertTrue(math.isnan(sp.getLatitude()))
     self.assertFalse(sp.isFinite())