Skip to content

Commit

Permalink
More documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yatoom committed Apr 6, 2021
1 parent 073fe01 commit 29520fb
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 21 deletions.
4 changes: 2 additions & 2 deletions docs/usage/visualization.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.. _visualization:

Visualization
=============
Visualizer
==========
.. automodule:: voronoi.visualization.visualizer
:members:
84 changes: 83 additions & 1 deletion voronoi/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,33 @@
class Algorithm(Subject):
def __init__(self, bounding_poly: Polygon = None, remove_zero_length_edges=True):
"""
A Python implementation of Fortune's algorithm based on the description of "Computational Geometry:
Algorithms and Applications" by de Berg et al.
Parameters
----------
bounding_poly: Polygon
The bounding box or bounding polygon around the voronoi diagram
remove_zero_length_edges: bool
Removes zero length edges and combines vertices with the same location into one
Attributes
----------
bounding_poly: Polygon
The bounding box (or polygon) around the edge
event_queue: PriorityQueue
Event queue for upcoming site and circle events
beach_line: SmartNode
Root node of the beach line
sweep_line: Decimal
The y-coordinate
arcs: list(:class:`voronoi.nodes.Arc`)
List of arcs
sites: list(:class:`voronoi.graph.Point`)
List of points
vertices: list(:class:`voronoi.graph.Vertex`)
List of vertices
"""
super().__init__()

Expand Down Expand Up @@ -79,7 +99,29 @@ def create_diagram(self, points: list):
"""
Create the Voronoi diagram.
:param points: (list) The list of cell points to make the diagram for
The overall structure of the algorithm is as follows.
1. Initialize the event queue `event_queue` with all site events, initialize an empty status structure
`beach_line` and an empty doubly-connected edge list `D`.
2. **while** `event_queue` is not empty.
3.  **do** Remove the event with largest `y`-coordinate from `event_queue`.
4.   **if** the event is a site event, occurring at site `point`
5.    **then** :func:`~handle_site_event`
6.    **else** :func:`handle_circle_event`
7. The internal nodes still present in `beach_line` correspond to the half-infinite edges of the Voronoi
diagram. Compute a bounding box (or polygon) that contains all vertices of bounding box by updating the
doubly-connected edge list appropriately.
8. **If** `remove_zero_length_edges` is true.
9.  Call :func:`~clean_up_zero_length_edges` which removes zero length edges and combines vertices with the same location into one.
Parameters
----------
points: list(Point)
A set of point sites in the plane.
Returns
-------
Output. The Voronoi diagram `Vor(P)` given inside a bounding box in a doublyconnected edge list `D`.
"""

points = [Point(x, y) for x, y in points]
Expand Down Expand Up @@ -155,6 +197,35 @@ def create_diagram(self, points: list):
self.notify_observers(Message.VORONOI_FINISHED)

def handle_site_event(self, event: SiteEvent):
"""
Handle a site event.
1. If T is empty, insert pi into it (so that T consists of a single leaf storing pi)
and return. Otherwise, continue with steps 2– 5.
2. Search in T for the arc α vertically above pi. If the leaf representing α has
a pointer to a circle event in Q, then this circle event is a false alarm and it
must be deleted from Q.
3. Replace the leaf of T that represents α with a subtree having three leaves.
The middle leaf stores the new site pi and the other two leaves store the site
pj that was originally stored with α. Store the tuples pj, pi and pi, pj
representing the new breakpoints at the two new internal nodes. Perform
rebalancing operations on T if necessary.
4. Create new half-edge records in the Voronoi diagram structure for the
edge separating V(pi) and V(pj), which will be traced out by the two new
breakpoints.
5. Check the triple of consecutive arcs where the new arc for pi is the left arc
to see if the breakpoints converge. If so, insert the circle event into Q and
add pointers between the node in T and the node in Q. Do the same for the
triple where the new arc is the right arc.
Parameters
----------
event
Returns
-------
"""

# Create a new arc
new_point = event.point
Expand Down Expand Up @@ -243,6 +314,17 @@ def handle_site_event(self, event: SiteEvent):
self.beach_line = SmartTree.balance_and_propagate(root)

def handle_circle_event(self, event: CircleEvent):
"""
Handle a circle event
Parameters
----------
event
Returns
-------
"""

# 1. Delete the leaf γ that represents the disappearing arc α from T.
arc = event.arc_pointer.data
Expand Down
9 changes: 9 additions & 0 deletions voronoi/graph/half_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ def __init__(self, incident_point, twin=None, origin=None):
origin: Breakpoint or Vertex
The origin of the half edge. Can be a Breakpoint or a Vertex during construction, and only Vertex when
the diagram is finished.
Attributes
----------
origin: :class:`Breakpoint` or :class:`Vertex`
Pointer to the origin. Can be breakpoint or vertex.
next: :class:`HalfEdge`
Pointer to the next edge
prev: :class:`HalfEdge`
Pointer to the previous edge
"""

# Pointer to the origin. Can be breakpoint or vertex.
Expand Down
13 changes: 8 additions & 5 deletions voronoi/graph/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class Point(Coordinate):

def __init__(self, x=None, y=None, metadata=None, name=None, first_edge=None):
def __init__(self, x=None, y=None, name=None, first_edge=None):
"""
A cell point a.k.a. a site.
Expand All @@ -33,13 +33,16 @@ def __init__(self, x=None, y=None, metadata=None, name=None, first_edge=None):
A name to easily identify this point
first_edge: HalfEdge
Pointer to the first edge
Attributes
----------
name: str
A name to easily identify this point
first_edge: HalfEdge
Pointer to the first edge
"""
super().__init__(x, y)

if metadata is None:
metadata = {}

self.metadata = metadata
self.name = name
self.first_edge = first_edge

Expand Down
5 changes: 5 additions & 0 deletions voronoi/graph/vertex.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ def __init__(self, x, y, connected_edges=None):
y-coordinate
connected_edges: list(:class:`HalfEdge`)
List of edges connected to this vertex.
Attributes
----------
connected_edges: list(:class:`HalfEdge`)
List of edges connected to this vertex.
"""

super().__init__(x, y)
Expand Down
43 changes: 30 additions & 13 deletions voronoi/nodes/arc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@


class Arc:
"""
Each leaf of beach line, representing an arc α, stores one pointer to a node in the event queue, namely, the node
that represents the circle event in which α will disappear. This pointer is None if no circle event exists where α
will disappear, or this circle event has not been detected yet.
"""

def __init__(self, origin: Coordinate, circle_event=None):
"""
:param origin: The point that caused the arc
:param circle_event: The pointer to the circle event in which the arc will disappear
Each leaf of beach line, representing an arc `α`, stores one pointer to a node in the event queue, namely, the
node that represents the circle event in which `α` will disappear. This pointer is None if no circle event
exists where `α` will disappear, or this circle event has not been detected yet.
Parameters
----------
origin: Point
The point that caused the arc
circle_event: CircleEvent
The pointer to the circle event in which the arc will disappear
Attributes
----------
origin: Point
The point that caused the arc
circle_event: CircleEvent
The pointer to the circle event in which the arc will disappear
"""

self.origin = origin
self.circle_event = circle_event

Expand All @@ -23,11 +33,18 @@ def __repr__(self):

def get_plot(self, x, sweep_line):
"""
Method for plotting the arc.
Will return the y-coordinates for all the x coordinates that are given as input.
:param x: The input x-coordinates
:param sweep_line: The y-coordinate of the sweep line
:return: A list of y-values
Computes all `y`-coordinates for given `x`-coordinates and the sweep line's `y`-coordinate.
Parameters
----------
x: np.array
The input x-coordinates
sweep_line: Decimal, float
The y-coordinate of the sweep line
Returns
-------
y: number, array-like
A list of y-values
"""
sweep_line = float(sweep_line)
i = self.origin
Expand Down

0 comments on commit 29520fb

Please sign in to comment.