예제 #1
0
 def test_exception(self):
     with self.assertRaises(Exception):
         build_convex_hull(((0, 0),))
     with self.assertRaises(Exception):
         build_convex_hull(((0, 0), (0, 0)))
     with self.assertRaises(Exception):
         build_convex_hull(((0, 0), (1, 1), (2, 2)))
import unittest

from offroad_routing.geometry.ch_localization import *
from offroad_routing.geometry.convex_hull import build_convex_hull

polygon1 = ((0, 0), (1, -1), (3, -1), (6, 1), (5, 3), (1, 3), (0, 0))
polygon1, _, angles1 = build_convex_hull(polygon1)
polygon2 = ((-1, -1), (6, -1), (6, 6), (-1, -1))
polygon2, _, angles2 = build_convex_hull(polygon2)
points_in = ((2, 1), (5, 1), (1, 0), (2, 0), (3, 0), (4, 0), (3, 1), (4, 1),
             (3, 2), (4, 2), (5, 2))
points_out = ((-1, 2), (3, 4), (5, -5), (10, -1), (-5, -5))
points_on = ((2, -1), (3, 3))


class TestLocalizeConvexLinear(unittest.TestCase):
    def test_polygon1(self):
        for p in points_in:
            self.assertTrue(localize_convex_linear(p, polygon1))
        for p in points_out:
            self.assertFalse(localize_convex_linear(p, polygon1))
        for p in points_on:
            self.assertFalse(localize_convex_linear(p, polygon1))

    def test_polygon2(self):
        for p in points_in:
            self.assertTrue(localize_convex_linear(p, polygon2))
        for p in points_out:
            self.assertFalse(localize_convex_linear(p, polygon2))
        for p in points_on:
            self.assertFalse(localize_convex_linear(p, polygon2))
예제 #3
0
    def prune_geometry(self,
                       epsilon_polygon=None,
                       epsilon_polyline=None,
                       bbox_comp=15,
                       remove_inner=False):
        """
        Transform retrieved map data:

        1. Transform geometry to tuple of points.
        2. Run Ramer-Douglas-Peucker (RDP) to geometry.
        3. Get rid of small objects with bbox_comp parameter.
        4. Add data about convex hull for polygons.

        Default RDP parameters will be computed for the given area to provide best performance.

        :param Optional[float] epsilon_polygon: RDP parameter for polygons
        :param Optional[float] epsilon_polyline: RDP parameter for polylines
        :param Optional[int] bbox_comp: scale polygon comparison parameter (to size of map bbox)
        :param bool remove_inner: remove inner polygons for other polygons
        """

        for param in {epsilon_polygon, epsilon_polyline, bbox_comp}:
            assert param is None or param >= 0

        # auto-compute parameters
        if epsilon_polygon is None:
            epsilon_polygon = (self.bbox_size[0]**2 +
                               self.bbox_size[1]**2)**0.5 / bbox_comp / 5

        if epsilon_polyline is None:
            epsilon_polyline = (self.bbox_size[0]**2 +
                                self.bbox_size[1]**2)**0.5 / bbox_comp / 10

        # compare to bounding box
        self.polygons.geometry = \
            self.polygons.geometry.apply(self.__compare_bbox, args=[bbox_comp, self.bbox_size])
        self.polygons = DataFrame(
            self.polygons[self.polygons['geometry'].notna()])

        # shapely.geometry.Polygon to tuple of points
        self.polygons.geometry = self.polygons.geometry.apply(
            self.__polygon_coords, args=[epsilon_polygon])
        self.polygons = self.polygons[self.polygons['geometry'].notna()]

        # remove equal polygons
        self.__remove_equal_polygons()
        self.polygons = self.polygons.reset_index().drop(columns='index')

        # remove polygons which are inner for other polygons
        if remove_inner:
            self.__remove_inner_polygons()

        # add info about convex hull
        if self.polygons.shape[0] > 0:
            self.polygons = self.polygons.join(
                DataFrame(self.polygons.geometry).apply(
                    lambda x: build_convex_hull(x[0][0]),
                    axis=1,
                    result_type='expand').rename(columns={
                        0: 'convex_hull',
                        1: 'convex_hull_points',
                        2: 'angles'
                    }))

        # compare to bounding box
        self.multilinestrings.geometry = \
            self.multilinestrings.geometry.apply(self.__compare_bbox, args=[bbox_comp, self.bbox_size])
        self.multilinestrings = DataFrame(self.multilinestrings[
            self.multilinestrings['geometry'].notna()].reset_index().drop(
                columns='index'))

        # shapely.geometry.MultiLineString to tuple of points and simplify
        self.multilinestrings.geometry = self.multilinestrings.geometry.apply(
            self.__linestring_coords, args=[epsilon_polyline])

        self.multilinestrings = self.multilinestrings.to_records(index=False)
        self.polygons = self.polygons.to_records(index=False)
예제 #4
0
 def test_non_convex(self):
     self.assertNotEqual(set(build_convex_hull(polygon2)[0]), set(polygon2))
     self.assertEqual(len(build_convex_hull(polygon2)[0]), len(polygon2) - 2)
     self.assertEqual(set(build_convex_hull(polygon2)[1]), {0, 2, 3, 5})
     self.assertEqual(len(build_convex_hull(polygon2)[2]), len(polygon2) - 2 - 2)
예제 #5
0
 def test_convex(self):
     self.assertEqual(set(build_convex_hull(polygon1)[0]), set(polygon1))
     self.assertEqual(len(build_convex_hull(polygon1)[0]), len(polygon1))
     self.assertEqual(set(build_convex_hull(polygon1)[1]), {0, 1, 2})
     self.assertEqual(len(build_convex_hull(polygon1)[2]), len(polygon1) - 2)
예제 #6
0
 def test_simple(self):
     self.assertEqual(set(build_convex_hull(polygon0)[0]), set(polygon0))
     self.assertEqual(len(build_convex_hull(polygon0)[0]), len(polygon0))
     self.assertEqual(set(build_convex_hull(polygon0)[1]), {0, 1})
     self.assertIs(build_convex_hull(polygon0)[2], None)
예제 #7
0
 def test_incorrect(self):
     with self.assertRaises(Exception):
         build_convex_hull(polygon0[:-1])