Arrangements and Visibility

[1]:
from skgeom import *

In this chapter we create a 2D arrangement, and explore how to use it in order to compute the visibility from different positions inside this arrangement.

A 2D arrangement consists of vertices, segments, and faces.

We can use the insert, and insert_point function on the arrangement to insert new points into it.

Then, the arrangement can be queried or iterated upon by using either the find function or the iterators.

[2]:
M = 10
outer = [
    Segment2(Point2(-M, -M), Point2(-M, M)), Segment2(Point2(-M, M), Point2(M, M)),
    Segment2(Point2(M, M), Point2(M, -M)), Segment2(Point2(M, -M), Point2(-M, -M))
]

segments = [
    Segment2(Point2(0, 0), Point2(0, 4)), Segment2(Point2(2, 4), Point2(8, 4)),
    Segment2(Point2(3, 4), Point2(-8, 0)), Segment2(Point2(1, 0), Point2(0, 5)),
]
arr = arrangement.Arrangement()

for s in outer:
    arr.insert(s)

for s in segments:
    arr.insert(s)

Now the arrangement can be iterated upon with the halfedges iterator property. Note that the segments that have been inserted are split at their intersections.

[3]:
for he in arr.halfedges:
    draw.draw(he.curve())
_images/arrangements_visibility_5_0.svg

Finding things in the arrangement

We can find the face associated with a certain point in the arrangement, and use the outer_ccb circulator to iterate over the halfedges associated with the face.

[4]:
q = Point2(-2.5, 5)
face = arr.find(q)
[5]:
i = face.outer_ccb
first = next(i)
halfedge = next(i)
[6]:
while first != halfedge:
    print(halfedge.source().point(), halfedge.target().point())
    halfedge = next(i)
print(halfedge.source().point(), halfedge.target().point())
PointC2(10, 10) PointC2(-10, 10)
PointC2(-10, 10) PointC2(-10, -10)
PointC2(-10, -10) PointC2(10, -10)
PointC2(10, -10) PointC2(10, 10)

Similarly, if we query a point that is lying on a halfedge, or a vertex itself we get either a halfedge or a vertex in return.

[7]:
vertex = arr.find(Point2(0, 0))
[8]:
vertex
[8]:
<skgeom._skgeom.arrangement.Vertex at 0x7f41aa4a3d88>

Computing Visibility

We can use the RotationalSweepVisibility class to compute the visibility from a specific point inside the arrangement.

[9]:
vs = RotationalSweepVisibility(arr)
[10]:
q = Point2(-2.5, 5)
face = arr.find(q)
vx = vs.compute_visibility(q, face)
[11]:
for he in arr.halfedges:
    draw.draw(he.curve(), visible_point=False)
for v in vx.halfedges:
    draw.draw(v.curve(), color='red', visible_point=False)

draw.draw(q, color='magenta')
_images/arrangements_visibility_16_0.svg

An additional, faster method to compute the visibility is also available, the TriangularExpansionVisibility. However, the TriangularExpansionVisibility requires a one-time initialization cost to be paid. You can read more about both algorithms here: https://doc.cgal.org/latest/Visibility_2/index.html

[12]:
ts = RotationalSweepVisibility(arr)
tx = ts.compute_visibility(q, face)
[13]:
for he in arr.halfedges:
    draw.draw(he.curve(), visible_point=False)
for v in tx.halfedges:
    draw.draw(v.curve(), color='red', visible_point=False)

draw.draw(q, color='magenta')
_images/arrangements_visibility_19_0.svg
[ ]: