Example #1
0
 def test_point_equality(self):
     assert self.point_a == Point(0.0, 1.0)
     assert self.point_a != Point(1.0, 0.0)
     assert self.edge_a == self.edge_b
     assert self.edge_a == self.edge_a
     assert self.edge_a == self.edge_c
     assert self.edge_a == self.edge_d
Example #2
0
 def setup_method(self, method):
     self.g = vg.VisGraph()
     self.point_a = Point(0, 0)
     self.point_b = Point(4, 0)
     self.point_c = Point(2, 4)
     self.point_d = Point(1, 0.5)
     self.g.build([[self.point_a, self.point_b, self.point_c]])
Example #3
0
 def test_collin2(self):
     self.point_g = Point(2, 5)
     self.point_h = Point(3, 5)
     graph = Graph([[self.point_g, self.point_h, self.point_c],
                    [self.point_d, self.point_e, self.point_f]])
     visible = visible_vertices(Point(1, 4), graph, None, None)
     assert visible == [self.point_g, self.point_e, self.point_c]
Example #4
0
def intersect_point(p1, p2, edge):
    """Return intersect Point where the edge from p1, p2 intersects edge"""
    if p1 in edge: return p1
    if p2 in edge: return p2
    if edge.p1.x == edge.p2.x:
        if p1.x == p2.x:
            return None
        pslope = (p1.y - p2.y) / (p1.x - p2.x)
        intersect_x = edge.p1.x
        intersect_y = pslope * (intersect_x - p1.x) + p1.y
        return Point(intersect_x, intersect_y)

    if p1.x == p2.x:
        eslope = (edge.p1.y - edge.p2.y) / (edge.p1.x - edge.p2.x)
        intersect_x = p1.x
        intersect_y = eslope * (intersect_x - edge.p1.x) + edge.p1.y
        return Point(intersect_x, intersect_y)

    pslope = (p1.y - p2.y) / (p1.x - p2.x)
    eslope = (edge.p1.y - edge.p2.y) / (edge.p1.x - edge.p2.x)
    if eslope == pslope:
        return None
    intersect_x = (eslope * edge.p1.x - pslope * p1.x + p1.y - edge.p1.y) / (eslope - pslope)
    intersect_y = eslope * (intersect_x - edge.p1.x) + edge.p1.y
    return Point(intersect_x, intersect_y)
Example #5
0
def test_point_in_polygon():
    g = vg.VisGraph()
    point_a = Point(0, 0)
    point_b = Point(4, 0)
    point_c = Point(2, 4)
    point_d = Point(1, 0.5)
    g.build([[point_a, point_b, point_c]])
    assert g.point_in_polygon(point_d) != -1
Example #6
0
 def test_collin3(self):
     point_g = Point(2.0, 2.0)
     point_h = Point(3.5, 5.0)
     point_i = Point(2.5, 2.0)
     graph = Graph([[self.point_a, self.point_b, self.point_c],
                    [point_g, point_h, point_i],
                    [self.point_d, self.point_e, self.point_f]])
     visible = visible_vertices(Point(1, 4), graph, None, None)
     assert visible == [point_h, self.point_a, self.point_c]
Example #7
0
 def test_closest_point_edge_point(self):
     """Test where the cp is a end-point of a polygon edge. Can end up with
     cp extending into polygon instead of outside it."""
     g = vg.VisGraph()
     g.build([[Point(0, 1), Point(2, 0), Point(1, 1), Point(2, 2)]])
     p = Point(1, 0.9)
     pid = g.point_in_polygon(p)
     cp = g.closest_point(p, pid, length=0.001)
     assert g.point_in_polygon(cp) == -1
Example #8
0
 def setup_method(self, method):
     self.point_a = Point(0.0, 1.0)
     self.point_b = Point(1.0, 2.0)
     self.point_c = Point(0.0, 1.0)
     self.point_d = Point(1.0, 2.0)
     self.edge_a = Edge(self.point_a, self.point_b)
     self.edge_b = Edge(self.point_b, self.point_a)
     self.edge_c = Edge(self.point_c, self.point_d)
     self.edge_d = Edge(self.point_d, self.point_c)
Example #9
0
 def test_collin4(self):
     graph = Graph([[Point(1, 1),
                     Point(2, 3),
                     Point(3, 1),
                     Point(2, 2)], [Point(2, 4)]])
     visible = visible_vertices(Point(2, 1), graph, None, None)
     assert visible == [Point(3, 1), Point(2, 2), Point(1, 1)]
Example #10
0
 def test_collin1(self):
     graph = Graph([[self.point_a, self.point_b, self.point_c],
                    [self.point_d, self.point_e, self.point_f]])
     visible = visible_vertices(Point(1, 4), graph, None, None)
     assert visible == [
         self.point_a, self.point_c, self.point_d, self.point_f
     ]
Example #11
0
def polygon_crossing(p1, poly_edges):
    """Returns True if Point p1 is internal to the polygon The polygon is
    defined by the Edges in poly_edges. Uses crossings algorithm and takes into
    account edges that are collinear to p1."""
    p2 = Point(INF, p1.y)
    intersect_count = 0
    co_flag = False
    co_dir = 0
    for edge in poly_edges:
        if p1.y < edge.p1.y and p1.y < edge.p2.y: continue
        if p1.y > edge.p1.y and p1.y > edge.p2.y: continue
        # Deal with points colinear to p1
        co0 = (ccw(p1, edge.p1, p2) == 0) and (edge.p1.x > p1.x)
        co1 = (ccw(p1, edge.p2, p2) == 0) and (edge.p2.x > p1.x)
        co_point = edge.p1 if co0 else edge.p2
        if co0 or co1:
            if edge.get_adjacent(co_point).y > p1.y:
                co_dir += 1
            else:
                co_dir -= 1
            if co_flag:
                if co_dir == 0:
                    intersect_count += 1
                co_flag = False
                co_dir = 0
            else:
                co_flag = True
        elif edge_intersect(p1, p2, edge):
            intersect_count += 1
    if intersect_count % 2 == 0:
        return False
    return True
Example #12
0
def edge_in_polygon(p1, p2, graph):
    if p1.polygon_id != p2.polygon_id:
        return False
    if p1.polygon_id == -1 or p2.polygon_id == -1:
        return False
    mid_point = Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2)
    return polygon_crossing(mid_point, graph.polygons[p1.polygon_id])
Example #13
0
 def test_collin11(self):
     graph = Graph([[
         Point(0, 0),
         Point(3, 0),
         Point(3, 2),
         Point(2, 3),
         Point(2, 1),
         Point(1, 1),
         Point(1, 2),
         Point(0, 2)
     ]])
     pip = point_in_polygon(Point(0.5, 1), graph)
     assert pip > -1
Example #14
0
def edge_in_polygon(p1, p2, graph):
    """Return true if the edge from p1 to p2 is interior to any polygon
    in graph."""
    if p1.polygon_id != p2.polygon_id:
        return False
    if p1.polygon_id == -1 or p2.polygon_id == -1:
        return False
    mid_point = Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2)
    return polygon_crossing(mid_point, graph.polygons[p1.polygon_id])
Example #15
0
 def test_collin5(self):
     r = 0.2  # Radius of polygon
     n = 4  # Sides of polygon
     c = Point(1.0, 1.0)  # Center of polygon
     verts = []
     for i in range(n):
         verts.append(
             Point(r * cos(2 * pi * i / n - pi / 4) + c.x,
                   r * sin(2 * pi * i / n - pi / 4) + c.y))
     g = vg.VisGraph()
     g.build([verts])
     s = Point(0, 0)
     t = Point(1.7, 1.7)
     shortest = g.shortest_path(s, t)
     visible = visible_vertices(t, g.graph, s, None)
     assert verts[3] not in visible
     assert verts[1] not in shortest
     assert verts[3] not in shortest
Example #16
0
def test_edge_intersect_function():
    point_a = Point(3.0, 5.0)
    point_b = Point(5.0, 3.0)
    point_c = Point(4.0, 2.0)
    point_d = Point(4.0, 5.0)
    point_e = Point(5.0, 4.0)
    point_f = Point(3.0, 4.0)
    point_g = Point(4.0, 1.0)
    point_h = Point(6.0, 4.0)
    point_i = Point(4.0, 4.0)
    edge = Edge(point_a, point_b)
    assert edge_intersect(point_c, point_d, edge) is True
    assert edge_intersect(point_c, point_e, edge) is True
    assert edge_intersect(point_f, point_e, edge) is True
    assert edge_intersect(point_g, point_b, edge) is True
    assert edge_intersect(point_c, point_h, edge) is True
    assert edge_intersect(point_h, point_i, edge) is True
Example #17
0
 def setup_method(self, method):
     self.point_a = Point(0, 1)
     self.point_b = Point(1, 0)
     self.point_c = Point(2, 3)
     self.point_d = Point(3, 2)
     self.point_e = Point(3.5, 0.5)
     self.point_f = Point(4.5, 3.5)
Example #18
0
 def setup_method(self, method):
     self.point_a = Point(0.0, 1.0)
     self.point_b = Point(1.0, 0.0)
     self.point_c = Point(2.0, 3.0)
     self.point_d = Point(3.0, 2.0)
     self.point_e = Point(3.5, 0.5)
     self.point_f = Point(4.5, 3.5)
Example #19
0
def test_point_edge_distance_function():
    point_a = Point(3.0, 1.0)
    point_b = Point(3.0, 5.0)
    point_c = Point(2.0, 2.0)
    point_d = Point(4.0, 4.0)
    point_e = Point(1.0, 1.0)
    point_f = Point(1.0, 2.0)
    point_g = Point(3.0, 4.0)
    point_h = Point(2.0, 5.0)
    edge = Edge(point_a, point_b)
    edge2 = Edge(point_c, point_d)
    edge3 = Edge(point_e, point_b)
    assert point_edge_distance(point_c, point_d, edge) == 1.4142135623730951
    assert point_edge_distance(point_a, point_b, edge2) == 2.0
    assert point_edge_distance(point_f, point_g, edge3) == 1.4142135623730951
    assert point_edge_distance(point_h, point_g, edge3) == 0.9428090415820635
Example #20
0
def polygon_crossing(p1, poly_edges):
    if not poly_edges: return True
    a = poly_edges.pop()
    polys = [[a.p1.x, a.p1.y], [a.p2.x, a.p2.y]]
    last = a.p2
    while poly_edges:
        curr = None
        for edge in poly_edges:
            if edge.p1 == last:
                curr = edge
        poly_edges.remove(curr)
        polys.append([curr.p2.x, curr.p2.y])
        last = curr.p2
    poly = Polygon(polys)
    return poly.contains(Point(p1.x, p1.y))
Example #21
0
def test_angle_function():
    center = Point(1.0, 1.0)
    point_a = Point(3.0, 1.0)
    point_b = Point(1.0, 0)
    point_c = Point(0.0, 2.0)
    point_d = Point(2.0, 2.0)
    point_e = Point(2.0, 0.0)
    point_f = Point(0.0, 0.0)
    assert angle(center, point_a) == 0
    assert angle(center, point_b) == pi * 3 / 2
    assert degrees(angle(center, point_c)) == 135
    assert degrees(angle(center, point_d)) == 45
    assert degrees(angle(center, point_e)) == 315
    assert degrees(angle(center, point_f)) == 225
Example #22
0
def polygon_crossing(p1, poly_edges):
    """Returns True if Point p1 is internal to the polygon. The polygon is
    defined by the Edges in poly_edges. Uses crossings algorithm and takes into
    account edges that are collinear to p1."""
    p2 = Point(INF, p1.y)
    intersect_count = 0
    for edge in poly_edges:
        if p1.y < edge.p1.y and p1.y < edge.p2.y: continue
        if p1.y > edge.p1.y and p1.y > edge.p2.y: continue
        if p1.x > edge.p1.x and p1.x > edge.p2.x: continue
        # Deal with points collinear to p1
        edge_p1_collinear = (ccw(p1, edge.p1, p2) == COLLINEAR)
        edge_p2_collinear = (ccw(p1, edge.p2, p2) == COLLINEAR)
        if edge_p1_collinear and edge_p2_collinear: continue
        if edge_p1_collinear or edge_p2_collinear:
            collinear_point = edge.p1 if edge_p1_collinear else edge.p2
            if edge.get_adjacent(collinear_point).y > p1.y:
                intersect_count += 1
        elif edge_intersect(p1, p2, edge):
            intersect_count += 1
    if intersect_count % 2 == 0:
        return False
    return True
Example #23
0
def closest_point(p, graph, polygon_id, length=0.001):
    """Assumes p is interior to the polygon with polygon_id. Returns the
    closest point c outside the polygon to p, where the distance from c to
    the intersect point from p to the edge of the polygon is length."""
    polygon_edges = graph.polygons[polygon_id]
    close_point = None
    close_edge = None
    close_dist = None
    # Finds point closest to p, but on a edge of the polygon.
    # Solution from http://stackoverflow.com/a/6177788/4896361
    for i, e in enumerate(polygon_edges):
        num = ((p.x - e.p1.x) * (e.p2.x - e.p1.x) + (p.y - e.p1.y) *
               (e.p2.y - e.p1.y))
        denom = ((e.p2.x - e.p1.x)**2 + (e.p2.y - e.p1.y)**2)
        u = num / denom
        pu = Point(e.p1.x + u * (e.p2.x - e.p1.x),
                   e.p1.y + u * (e.p2.y - e.p1.y))
        pc = pu
        if u < 0:
            pc = e.p1
        elif u > 1:
            pc = e.p2
        d = edge_distance(p, pc)
        if i == 0 or d < close_dist:
            close_dist = d
            close_point = pc
            close_edge = e

    # Extend the newly found point so it is outside the polygon by `length`.
    if close_point in close_edge:
        c = close_edge.p1 if close_point == close_edge.p1 else close_edge.p2
        edges = list(graph[c])
        v1 = unit_vector(c, edges[0].get_adjacent(c))
        v2 = unit_vector(c, edges[1].get_adjacent(c))
        vsum = unit_vector(Point(0, 0), Point(v1.x + v2.x, v1.y + v2.y))
        close1 = Point(c.x + (vsum.x * length), c.y + (vsum.y * length))
        close2 = Point(c.x - (vsum.x * length), c.y - (vsum.y * length))
        if point_in_polygon(close1, graph) == -1:
            return close1
        return close2
    else:
        v = unit_vector(p, close_point)
        return Point(close_point.x + v.x * length,
                     close_point.y + v.y * length)
Example #24
0
 def round_point(self, point):
     return Point(round(point.x, self.precision), round(point.y, self.precision))
Example #25
0
def visible_vertices(point, graph, origin=None, destination=None, scan='full'):
    """Returns list of Points in graph visible by point.

    If origin and/or destination Points are given, these will also be checked
    for visibility. scan 'full' will check for visibility against all points in
    graph, 'half' will check for visibility against half the points. This saves
    running time when building a complete visibility graph, as the points
    that are not checked will eventually be 'point'.
    """
    edges = graph.get_edges()
    points = graph.get_points()
    if origin: points.append(origin)
    if destination: points.append(destination)
    points.sort(key=lambda p: (angle(point, p), edge_distance(point, p)))

    # Initialize open_edges with any intersecting edges on the half line from
    # point along the positive x-axis
    open_edges = []
    point_inf = Point(INF, point.y)
    for e in edges:
        if point in e: continue
        if edge_intersect(point, point_inf, e):
            if on_segment(point, e.p1, point_inf): continue
            if on_segment(point, e.p2, point_inf): continue
            k = EdgeKey(point, point_inf, e)
            insort(open_edges, k)

    visible = []
    prev = None
    prev_visible = None
    for p in points:
        if p == point: continue
        if scan == 'half' and angle(point, p) > pi: break

        # Remove clock wise edges incident on p
        if open_edges:
            for edge in graph[p]:
                if ccw(point, p, edge.get_adjacent(p)) == -1:
                    k = EdgeKey(point, p, edge)
                    index = bisect(open_edges, k) - 1
                    if len(open_edges) > 0 and open_edges[index] == k:
                        del open_edges[index]

        # Check if p is visible from point
        is_visible = False
        # ...Non-collinear points
        if prev is None or ccw(point, prev, p) != 0 or not on_segment(point, prev, p):
            if len(open_edges) == 0:
                is_visible = True
            elif not edge_intersect(point, p, open_edges[0].edge):
                is_visible = True
        # ...For collinear points, if previous point was not visible, p is not
        elif not prev_visible:
            is_visible = False
        # ...For collinear points, if previous point was visible, need to check
        # that the edge from prev to p does not intersect any open edge.
        else:
            is_visible = True
            for e in open_edges:
                if prev not in e.edge and edge_intersect(prev, p, e.edge):
                    is_visible = False
                    break
            if is_visible and edge_in_polygon(prev, p, graph):
                    is_visible = False

        # Check if the visible edge is interior to its polygon
        if is_visible and p not in graph.get_adjacent_points(point):
            is_visible = not edge_in_polygon(point, p, graph)

        if is_visible: visible.append(p)

        # Add counter clock wise edges incident on p to open_edges
        for edge in graph[p]:
            if (point not in edge) and ccw(point, p, edge.get_adjacent(p)) == 1:
                k = EdgeKey(point, p, edge)
                insort(open_edges, k)

        prev = p
        prev_visible = is_visible
    return visible
Example #26
0
def test_angle2_function():
    polys = [[
        Point(353.6790486272709, 400.99387840984855),
        Point(351.1303807396073, 398.8696192603927),
        Point(349.5795890382704, 397.8537806679034),
        Point(957.1067811865476, -207.10678118654744),
        Point(-457.10678118654766, -207.10678118654744),
        Point(-457.10678118654744, 1207.1067811865476),
        Point(957.1067811865476, 1207.1067811865473),
        Point(353.52994294901674, 606.0798841165788),
        Point(354.0988628008279, 604.098862800828),
        Point(354.52550331744527, 601.3462324760635),
        Point(352.6969055662087, 602.6943209889012),
        Point(351.22198101804634, 603.781672670995),
        Point(247.0, 500.0),
        Point(341.8964635104416, 405.50444716676054),
        Point(349.24224903733045, 410.671256247085),
        Point(350.84395848060774, 407.17766877398697)
    ]]
    v = vg.VisGraph()
    v.build(polys)
Example #27
0
def unit_vector(c, p):
    magnitude = edge_distance(c, p)
    return Point((p.x - c.x) / magnitude, (p.y - c.y) / magnitude)
    def build_mod(self, input, workers=1, status=True, ref_point=None):
        """Build visibility graph based on a list of polygons.
        
        Modified version. Takes into account the case where one polygon surrounds the rest
        To test this, a reference-point is given to check the existance of such polygon
        
        The input must be a list of polygons, where each polygon is a list of
        in-order (clockwise or counter clockwise) Points. It only one polygon,
        it must still be a list in a list, i.e. [[Point(0,0), Point(2,0),
        Point(2,1)]].
        Take advantage of processors with multiple cores by setting workers to
        the number of subprocesses you want. Defaults to 1, i.e. no subprocess
        will be started.
        Set status=False to turn off the statusbar when building.
        """

        self.graph = Graph(input)
        self.visgraph = Graph([])

        # Check if surrounding polygon exists
        surPoly = []
        if ref_point:
            sPoly = pointVec_in_polygon(ref_point, self.graph)
            surPoly = sPoly

            if sPoly.__len__() == 2: #choose the outer polygon
                pp0 = list(self.graph.polygons[sPoly[0]])
                pp1 = list(self.graph.polygons[sPoly[1]])
                x0=[]
                for e in pp0:
                    x0.append(e.p1.x)
                    x0.append(e.p2.x)
                x1=[]
                for e in pp1:
                    x1.append(e.p1.x)
                    x1.append(e.p2.x)

                if min(x0)<min(x1):
                    surPoly = sPoly[0]
                else: surPoly = sPoly[1]

        if surPoly:
            surPoly = surPoly[0]
            surPolyEdges = list(self.graph.polygons[surPoly])

        points = self.graph.get_points()
        batch_size = 10

        if workers == 1:
            for batch in tqdm([points[i:i + batch_size]
                               for i in xrange(0, len(points), batch_size)],
                            disable=not status):
                for edge in _vis_graph(self.graph, batch):
                    if surPoly != -1:  # skip an edge outside the surrounding polygon
                        edgePtsInPoly = 0
                        for n in range(surPolyEdges.__len__()):
                            if surPolyEdges[n].__contains__(edge.p1) or surPolyEdges[n].__contains__(edge.p2):
                                edgePtsInPoly += 1
                        if edgePtsInPoly == 4:  # both edge points on surrounding polygon, but not same edge
                            midP = Point((edge.p1.x + edge.p2.x)/2. , (edge.p1.y + edge.p2.y)/2. )
                            if not polygon_crossing(midP, self.graph.polygons[surPoly]):
                                continue
                    self.visgraph.add_edge(edge)
        else:
            pool = Pool(workers)
            batches = [(self.graph, points[i:i + batch_size])
                       for i in xrange(0, len(points), batch_size)]

            results = list(tqdm(pool.imap(_vis_graph_wrapper, batches), total=len(batches),
                disable=not status))
            for result in results:
                for edge in result:
                    self.visgraph.add_edge(edge)
Example #29
0
def edge_intersect(p1, p2, edge):
    edge2 = LineString([Point(p1.x, p1.y), Point(p2.x, p2.y)])
    edge1 = LineString(
        [Point(edge.p1.x, edge.p1.y),
         Point(edge.p2.x, edge.p2.y)])
    return edge1.intersects(edge2)
Example #30
0
def on_segment(p, q, r):
    line = LineString([Point(p.x, p.y), Point(r.x, r.y)])
    return line.contains(Point(q.x, q.y))