def test_geoscore_0(self): "Test scoring a non-matching LRP candidate line" lrp = LocationReferencePoint(0.0, 0.0, None, None, None, None, None) node1 = DummyNode(Coordinates(0.0, 0.0)) node2 = DummyNode(Coordinates(0.0, 90.0)) pal = PointOnLine(DummyLine(None, node1, node2), 1.0) score = score_geolocation(lrp, pal, 1.0) self.assertEqual(score, 0.0)
def test_projection_and_angle(self): "Test re-projecting existing point" geo1 = Coordinates(13.41, 52.525) geo2 = Coordinates(13.414, 52.525) dist = distance(geo1, geo2) angle = bearing(geo1, geo2) geo3 = extrapolate(geo1, dist, angle) self.assertAlmostEqual(geo2.lon, geo3.lon) self.assertAlmostEqual(geo2.lat, geo3.lat)
def test_bearingscore_4(self): "Test bearing difference of -90°" node1 = DummyNode(Coordinates(0.0, 0.0)) node2 = DummyNode(Coordinates(0.0, 90.0)) node3 = DummyNode(Coordinates(-1.0, 0.0)) wanted_bearing = degrees(bearing(node1.coordinates, node2.coordinates)) wanted = LocationReferencePoint(13.416, 52.525, FRC.FRC2, FOW.SINGLE_CARRIAGEWAY, wanted_bearing, None, None) line = DummyLine(1, node1, node3) score = score_bearing(wanted, PointOnLine(line, 1.0), True, self.config.bear_dist) self.assertAlmostEqual(score, 0.5)
def test_point_along_path(self): "Test point projection along path" path = [ Coordinates(0.0, 0.0), Coordinates(0.0, 1.0), Coordinates(0.0, 2.0) ] part_lengths = [ distance(path[i], path[i + 1]) for i in range(len(path) - 1) ] length = sum(part_lengths) projected = interpolate(path, 0.75 * length) self.assertAlmostEqual(projected.lon, 0.0, places=3) self.assertAlmostEqual(projected.lat, 1.5, places=3)
def test_split_line(self): start = Coordinates(13.0, 52.0) middle = Coordinates(13.1, 52.0) end = Coordinates(13.1, 52.1) line = LineString([Point(*start), Point(*middle), Point(*end)]) length = distance(start, middle) + distance(middle, end) (first, second) = split_line(line, 0.0) self.assertIsNone(first) self.assertEqual(second, line) (first, second) = split_line(line, 1.0 * length) self.assertIsNone(second) self.assertEqual(first, line) (first, second) = split_line(line, 0.5 * length) self.assertAlmostEqual(first.length + second.length, line.length)
def test_decode_3_lrps(self): "Decode a line location of 3 LRPs" reference = get_test_linelocation_1() location = decode(reference, self.reader) self.assertTrue(isinstance(location, LineLocation)) lines = [l.line_id for l in location.lines] self.assertListEqual([1, 3, 4], lines) for (a, b) in zip(location.coordinates(), [ Coordinates(13.41, 52.525), Coordinates(13.414, 52.525), Coordinates(13.4145, 52.529), Coordinates(13.416, 52.525) ]): self.assertAlmostEqual(a.lon, b.lon, delta=0.00001) self.assertAlmostEqual(a.lat, b.lat, delta=0.00001)
def test_bearingscore_5(self): "Test perfect/worst possible bearing" node1 = DummyNode(Coordinates(1.0, 0.0)) node2 = DummyNode(Coordinates(0.0, 0.0)) wanted_bearing = degrees(bearing(node1.coordinates, node2.coordinates)) wanted = LocationReferencePoint(13.416, 52.525, FRC.FRC2, FOW.SINGLE_CARRIAGEWAY, wanted_bearing, None, None) line = DummyLine(1, node1, node2) score = score_bearing(wanted, PointOnLine(line, 0.0), False, self.config.bear_dist) self.assertAlmostEqual(score, 1.0) score = score_bearing(wanted, PointOnLine(line, 1.0), True, self.config.bear_dist) self.assertAlmostEqual(score, 0.0)
def test_decode_poi(self): "Test decoding a valid POI with access point location" reference = get_test_poi() poi: PoiWithAccessPoint = decode(reference, self.reader) coords = poi.access_point_coordinates() self.assertAlmostEqual(coords.lon, 13.4153, delta=0.0001) self.assertAlmostEqual(coords.lat, 52.5270, delta=0.0001) self.assertEqual(poi.poi, Coordinates(13.414, 52.526))
def extrapolate(point: Coordinates, dist: float, angle: float) -> Coordinates: "Creates a new point that is `dist` meters away in direction `angle`" lon, lat = point.lon, point.lat geod = Geodesic.WGS84 line = geod.Direct(lat, lon, degrees(angle), dist) # According to https://geographiclib.sourceforge.io/1.50/python/, the attributes `lon2` # and `lat2` store the second point. return Coordinates(line["lon2"], line["lat2"])
def point_n(self, index) -> Coordinates: "Returns the `n` th point in the path geometry, starting at 0" stmt = "SELECT X(PointN(path, ?)), Y(PointN(path, ?)) FROM lines WHERE lines.rowid = ?" (lon, lat) = self.map_reader.connection.execute( stmt, (index, index, self.line_id)).fetchone() if lon is None or lat is None: raise Exception(f"line {self.line_id} has no point {index}!") return Coordinates(lon, lat)
def test_remove_offsets_raises(self): "Remove too big offsets" node0 = DummyNode(Coordinates(13.128987, 52.494595)) node1 = DummyNode(extrapolate(node0.coord, 10, 180.0)) line = DummyLine(0, node0, node1) route = Route(PointOnLine(line, 0.0), [], PointOnLine(line, 1.0)) with self.assertRaises(LRDecodeError): remove_offsets(route, 11, 0) with self.assertRaises(LRDecodeError): remove_offsets(route, 0, 11)
def test_remove_offsets(self): "Remove offsets containing lines" node0 = DummyNode(Coordinates(13.128987, 52.494595)) node1 = DummyNode(extrapolate(node0.coord, 20, 180.0)) node2 = DummyNode(extrapolate(node1.coord, 90, 90.0)) node3 = DummyNode(extrapolate(node2.coord, 20, 180.0)) lines = [ DummyLine(0, node0, node1), DummyLine(1, node1, node2), DummyLine(2, node2, node3) ] route = Route(PointOnLine(lines[0], 0.5), [lines[1]], PointOnLine(lines[2], 0.5)) route = remove_offsets(route, 40, 40) self.assertListEqual(route.lines, [lines[1]]) self.assertAlmostEqual(route.length(), 30, delta=1)
def decode_poi_with_accesspoint( reference: PoiWithAccessPointLocationReference, reader: MapReader, config: Config, observer: Optional[DecoderObserver] ) -> PoiWithAccessPoint: "Decodes a poi with access point location reference into a PoiWithAccessPoint" path = combine_routes(dereference_path(reference.points, reader, config, observer)) absolute_offset = path_length(get_lines([path])) * reference.poffs line, line_offset = point_along_linelocation(path, absolute_offset) return PoiWithAccessPoint( line, line_offset, reference.sideOfRoad, reference.orientation, Coordinates(reference.lon, reference.lat), )
def test_projection_90(self): "Test point projection into 90° direction" geo1 = Coordinates(0.0, 0.0) (lon, lat) = extrapolate(geo1, 20037508.0, pi * 90.0 / 180) self.assertAlmostEqual(lon, 180.0, delta=0.1) self.assertAlmostEqual(lat, 0.0)
def coordinates(self) -> Coordinates: stmt = "SELECT X(coord), Y(coord) FROM nodes WHERE id = ?" geo = self.map_reader.connection.execute(stmt, (self.node_id, )).fetchone() return Coordinates(lon=geo[0], lat=geo[1])
def linestring_coords(line: LineString) -> List[Coordinates]: "Returns the edges of the line geometry as Coordinate list" return [Coordinates(*point) for point in line.coords]
def coords(lrp: LocationReferencePoint) -> Coordinates: "Return the coordinates of an LRP" return Coordinates(lrp.lon, lrp.lat)
def test_line_distance(self): "Test if a point on a line has zero distance from it" line = self.reader.get_line(1) point = Coordinates(13.41, 52.525) self.assertEqual(line.distance_to(point), 0.0)
def test_nearest(self): "Test find_nodes_close_to with a manually chosen location" nodes = [] nodes = [node.node_id for node \ in self.reader.find_nodes_close_to(Coordinates(13.411, 52.525), 100)] self.assertSequenceEqual(nodes, [0, 14])
def coordinates(self) -> Sequence[Coordinates]: """Returns the shape of the line as list of Coordinates""" return [Coordinates(*point) for point in self.geometry.coords]
def coordinates(self) -> List[Coordinates]: "Returns all Coordinates of this line location" return [Coordinates(lon, lat) for (lon, lat) in self.shape.coords]
def test_bearing_90_2(self): "Test bearing function where it should be 90°" geo1 = Coordinates(-1.0, 0.0) geo2 = Coordinates(-2.0, 0.0) bear = bearing(geo1, geo2) self.assertEqual(bear, -pi / 2)
def test_decode_coord(self): coord = Coordinates(13.0, 51.0) reference = GeoCoordinateLocationReference(coord) location = decode(reference, self.reader) self.assertAlmostEqual(coord.lon, location.lon) self.assertAlmostEqual(coord.lat, location.lat)
def test_bearing_180(self): "Test bearing function where it should be 180°" geo1 = Coordinates(0.0, -10.0) geo2 = Coordinates(0.0, -20.0) bear = bearing(geo1, geo2) self.assertEqual(bear, pi)
def test_distance_2(self): "Compare a WGS84 distance to an expected value" geo1 = Coordinates(13.1759576, 52.4218989) geo2 = Coordinates(13.147999, 52.4515114) dist = distance(geo1, geo2) self.assertAlmostEqual(3800, dist, delta=10)
def test_bearing_zero(self): "Test bearing function where it should be zero" geo1 = Coordinates(0.0, 10.0) geo2 = Coordinates(0.0, 20.0) bear = bearing(geo1, geo2) self.assertEqual(bear, 0.0)