Add algorithm class ConvexHullIncremental
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2020-03-16 19:48:02 +01:00
parent 94ad6def57
commit 8a3910497e

View File

@@ -191,3 +191,111 @@ class NearestNeighborsSweep(Algorithm):
self._result["points"][0], self._result["points"][1] \
).draw(canvas, width, height, max_x, max_y, "#FF0000")
class ConvexHull(Algorithm):
"""This algorithm calculates the convex hull for a set of points"""
def __init__(self, point_set=None):
super().__init__()
if isinstance(point_set, list):
for pnt in point_set:
if not isinstance(pnt, point.Point):
raise Exception(self, "Inputs have to be of type point.Point!")
self._input = copy.deepcopy(point_set)
self._ready = True
elif point_set is not None:
raise Exception(self, "Wrong input type for point_set")
self._sss = {} # The sweep state structure
self._es = [] # The event queue
self._result = {"success": False, \
"lt": [], \
"lb": [], \
"rt": [], \
"rb": [], \
"hull": []}
def start(self):
"""Start the performing the algorithm. Return True if it was successful"""
if not super().start():
return False
self._result["success"] = False
self._sss = {"max": None, \
"min": None}
# Populate event structure
self._es = copy.deepcopy(self._input)
# Sort the input elements
self._num_steps["sort"] = point.sort_set(self._es)
self._section = "sweep-left-to-right"
return True
def step(self):
"""Perform a single step of the algorithm."""
if not self._running:
return
if self._section == "sweep-left-to-right":
event = self._es.pop(0)
if self._sss["min"] is None or self._sss["max"] is None:
self._sss["min"] = event
self._sss["max"] = event
elif event.get_y() < self._sss["min"].get_y():
self._result["rb"].append(linesegment.LineSegment(self._sss["min"], event))
self._sss["min"] = event
elif event.get_y() > self._sss["max"].get_y():
self._result["rt"].append(linesegment.LineSegment(self._sss["max"], event))
self._sss["max"] = event
super().step()
if len(self._es) == 0:
self._sss["min"] = None
self._sss["max"] = None
self._es = copy.deepcopy(self._input).reverse()
self._section = "sweep-right-to-left"
elif self._section == "sweep-right-to-left":
event = self._es.pop(0)
if self._sss["min"] is None or self._sss["max"] is None:
self._sss["min"] = event
self._sss["max"] = event
elif event.get_y() < self._sss["min"].get_y():
self._result["rb"].append(linesegment.LineSegment(self._sss["min"], event))
self._sss["min"] = event
elif event.get_y() > self._sss["max"].get_y():
self._result["rt"].append(linesegment.LineSegment(self._sss["max"], event))
self._sss["max"] = event
super().step()
if len(self._es) == 0:
self._section = "sweep-left-to-top"
elif self._section == "sweep-left-to-top":
event = self._es.pop(0)
if len(self._es) == 0:
self._section = "sweep-left-to-bottom"
elif self._section == "sweep-left-to-bottom":
event = self._es.pop(0)
if len(self._es) == 0:
self._section = "sweep-right-to-top"
elif self._section == "sweep-right-to-top":
event = self._es.pop(0)
if len(self._es) == 0:
self._section = "sweep-right-to-bottom"
elif self._section == "sweep-right-to-bottom":
event = self._es.pop(0)
if len(self._es) == 0:
self._section = "report-hull"
elif self._section == "report-hull":
for line in self._result["lb"]:
self._result["hull"].append(line)
for line in self._result["rb"].reverse():
self._result["hull"].append(line)
for line in self._result["rt"]:
self._result["hull"].append(line)
for line in self._result["lt"].reverse():
self._result["hull"].append(line)
self._result["success"] = True
self._running = False