Skip to content

Commit

Permalink
More documentation setup.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yatoom committed Apr 6, 2021
1 parent c4bcbe4 commit 6c1a5ec
Show file tree
Hide file tree
Showing 21 changed files with 217 additions and 46 deletions.
8 changes: 4 additions & 4 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
=============
API Reference
=============
==============
Public classes
==============

.. toctree::
:maxdepth: 2
:glob:

usage/*
public/*
24 changes: 24 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,38 @@
Welcome to Foronoi's documentation!
===================================

Foronoi is a Python implementation of the Fortune's algorithm based on the description of "Computational Geometry:
Algorithms and Applications" by de Berg et al.

This algorithm is a sweep line algorithm that scans top down over the
cell points and traces out the lines via breakpoints in between parabola's (arcs). Once a new point is inserted, a check
is done to see if it will converge with the lines on the left or right. If that's the case, it will insert a so-called
circle-event which causes a new vertex (i.e. a cross-way between edges) to be created in the middle of the circle.

The algorithm keeps track of the status (everything above the line is handled) in a so-called status-structure. This
status-structure is a balanced binary search tree that keeps track of the positions of the arcs (in its leaf nodes) and
the breakpoints (in its internal nodes). This data structure allows for fast look-up times, so that the entire
algorithm can run in `O(n log n)` time.

This implementation includes some additional features to the standard algorithm. For example, this implementation is
able to clip the diagram to a bounding box in different shapes. And it will clean up zero-length edges that occur in
edge-cases where two events happen at the same time so that it is more practical to use.


.. image:: ../voronoi.gif
:width: 800
:alt: Voronoi diagram under construction

Table of contents
+++++++++++++++++

.. toctree::
:maxdepth: 2
:glob:

installation
api
private


Indices and tables
Expand Down
12 changes: 12 additions & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Installation
===================

Manual
++++++
First, clone the repository and then install the package.

.. code-block:: bash
git clone https://github.com/Yatoom/voronoi.git
cd voronoi
python setup.py install
9 changes: 9 additions & 0 deletions docs/private.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
==============
Private classes
==============

.. toctree::
:maxdepth: 2
:glob:

private/*
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions docs/public/coordinate.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.. _coordinate:

Coordinate
==========
.. autoclass:: voronoi.graph.Coordinate
:members:

File renamed without changes.
File renamed without changes.
6 changes: 6 additions & 0 deletions docs/public/polygon.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _polygon:

Polygon
=======
.. autoclass:: voronoi.graph.Polygon
:members:
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 2 additions & 1 deletion examples/observers.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@

# Callback that saves the figure every step
# If no callback is provided, it will simply display the figure in a matplotlib window
callback=lambda observer, figure: figure.savefig(f"output/voronoi/{observer.n_messages:02d}.png")
callback=lambda observer, figure: figure.savefig(f"output/voronoi/{observer.n_messages:02d}.png"),
visualize_before_clipping=True
)
)

Expand Down
17 changes: 11 additions & 6 deletions voronoi/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,16 @@ def create_diagram(self, points: list):
self.notify_observers(Message.SWEEP_FINISHED)

# Finish with the bounding box
self._edges, polygon_vertices = self.bounding_poly.finish_edges(
self._edges = self.bounding_poly.finish_edges(
edges=self._edges, vertices=self._vertices, points=self.sites, event_queue=self.event_queue
)

self.notify_observers(Message.SWEEP_FINISHED)

self._edges, self._vertices = self.bounding_poly.finish_polygon(self._edges, self._vertices, self.sites)

self.notify_observers(Message.SWEEP_FINISHED)

if self.remove_zero_length_edges:
self.clean_up_zero_length_edges()

Expand Down Expand Up @@ -333,7 +338,7 @@ def handle_site_event(self, event: SiteEvent):
node_a, node_b, node_c = root.left.predecessor, root.left, root.right.left
node_c, node_d, node_e = node_c, root.right.right, root.right.right.successor

self.check_circles((node_a, node_b, node_c), (node_c, node_d, node_e))
self._check_circles((node_a, node_b, node_c), (node_c, node_d, node_e))

# X. Rebalance the tree
self.status_tree = Tree.balance_and_propagate(root)
Expand Down Expand Up @@ -377,7 +382,7 @@ def handle_circle_event(self, event: CircleEvent):
successor = arc_node.successor

# Update breakpoints
self.status_tree, updated, removed, left, right = self.update_breakpoints(
self.status_tree, updated, removed, left, right = self._update_breakpoints(
self.status_tree, self.sweep_line, arc_node, predecessor, successor)

if updated is None:
Expand Down Expand Up @@ -441,9 +446,9 @@ def remove(neighbor_event):
node_a, node_b, node_c = former_left.predecessor, former_left, former_left.successor
node_d, node_e, node_f = former_right.predecessor, former_right, former_right.successor

self.check_circles((node_a, node_b, node_c), (node_d, node_e, node_f))
self._check_circles((node_a, node_b, node_c), (node_d, node_e, node_f))

def check_circles(self, triple_left, triple_right):
def _check_circles(self, triple_left, triple_right):
node_a, node_b, node_c = triple_left
node_d, node_e, node_f = triple_right

Expand Down Expand Up @@ -481,7 +486,7 @@ def check_circles(self, triple_left, triple_right):
return left_event, right_event

@staticmethod
def update_breakpoints(root, sweep_line, arc_node, predecessor, successor):
def _update_breakpoints(root, sweep_line, arc_node, predecessor, successor):

# If the arc node is a left child, then its parent is the node with right_breakpoint
if arc_node.is_left_child():
Expand Down
2 changes: 1 addition & 1 deletion voronoi/contrib/bounding_circle.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def finish_edges(self, edges, vertices=None, points=None, event_queue=None):
.show()

# Re-order polygon vertices
self.polygon_vertices = self.get_ordered_vertices(self.polygon_vertices)
self.polygon_vertices = self._get_ordered_vertices(self.polygon_vertices)

if DEBUG:
Visualizer(self.voronoi, 1) \
Expand Down
81 changes: 71 additions & 10 deletions voronoi/graph/coordinate.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
class Coordinate:
def __init__(self, x=None, y=None):
"""
A point in 2D space.
:param x: (float) The x-coordinate
:param y: (float) The y-coordinate
A point in 2D space
Parameters
----------
x: float
The x-coordinate
y: float
The y-coordinate
"""
self._xd: Decimal = Coordinate.to_dec(x)
self._yd: Decimal = Coordinate.to_dec(y)
self._xd: Decimal = Coordinate._to_dec(x)
self._yd: Decimal = Coordinate._to_dec(y)

def __sub__(self, other):
return Coordinate(x=self.xd - other.xd, y=self.yd - other.yd)
Expand All @@ -18,41 +23,97 @@ def __repr__(self):
return f"Coord({self.xd:.2f}, {self.yd:.2f})"

@staticmethod
def to_dec(value):
def _to_dec(value):
return Decimal(str(value)) if value is not None else None

@property
def x(self):
"""
Get the x-coordinate as float
Returns
-------
x: float
The x-coordinate
"""
return float(self._xd)

@property
def y(self):
"""
Get the y-coordinate as float
Returns
-------
y: float
The y-coordinate
"""
return float(self._yd)

@x.setter
def x(self, value):
self._xd = Coordinate.to_dec(value)
"""
Stores the x-coordinate as Decimal
Parameters
----------
value: float
The x-coordinate as float
"""
self._xd = Coordinate._to_dec(value)

@y.setter
def y(self, value):
self._yd = Coordinate.to_dec(value)
"""
Stores the y-coordinate as Decimal
Parameters
----------
value: float
The y-coordinate as float
"""
self._yd = Coordinate._to_dec(value)

@property
def xy(self):
"""
Get a (x, y) tuple
Parameters
----------
xy: (float, float)
A tuple of the (x, y)-coordinate
"""
return self.x, self.y

@property
def xd(self):
"""
Get the x-coordinate as Decimal
Returns
-------
x: Decimal
The x-coordinate
"""
return self._xd

@xd.setter
def xd(self, value: float):
self._xd = Coordinate.to_dec(value)
self._xd = Coordinate._to_dec(value)

@property
def yd(self):
"""
Get the y-coordinate as Decimal
Returns
-------
y: Decimal
The y-coordinate
"""
return self._yd

@yd.setter
def yd(self, value: float):
self._yd = Coordinate.to_dec(value)
self._yd = Coordinate._to_dec(value)
2 changes: 1 addition & 1 deletion voronoi/graph/point.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class Point(Coordinate):

def __init__(self, x=None, y=None, name=None, first_edge=None):
"""
A cell point a.k.a. a site.
A cell point a.k.a. a site. Extends the :class:`Coordinate` class.
Examples
--------
Expand Down
Loading

0 comments on commit 6c1a5ec

Please sign in to comment.