Add missing parts of ConvexHullIncremental
All checks were successful
continuous-integration/drone/push Build is passing

The algorithm parts to clean up the four parts of the convex hull were
not implemented yet. Also added draw function for completed algorithm.
This commit is contained in:
2020-03-20 12:06:10 +01:00
parent 89d8ff4b3f
commit fd3d055115

View File

@@ -191,7 +191,7 @@ class NearestNeighborsSweep(Algorithm):
self._result["points"][0], self._result["points"][1] \ self._result["points"][0], self._result["points"][1] \
).draw(canvas, width, height, max_x, max_y, "#FF0000") ).draw(canvas, width, height, max_x, max_y, "#FF0000")
class ConvexHull(Algorithm): class ConvexHullIncremental(Algorithm):
"""This algorithm calculates the convex hull for a set of points""" """This algorithm calculates the convex hull for a set of points"""
@@ -220,7 +220,11 @@ class ConvexHull(Algorithm):
self._result["success"] = False self._result["success"] = False
self._sss = {"max": None, \ self._sss = {"max": None, \
"min": None} "min": None, \
"lt": [], \
"lb": [], \
"rt": [], \
"rb": []}
# Populate event structure # Populate event structure
self._es = copy.deepcopy(self._input) self._es = copy.deepcopy(self._input)
# Sort the input elements # Sort the input elements
@@ -236,66 +240,150 @@ class ConvexHull(Algorithm):
event = self._es.pop(0) event = self._es.pop(0)
if self._sss["min"] is None or self._sss["max"] is None: if self._sss["min"] is None or self._sss["max"] is None:
self._sss["min"] = event self._sss["min"] = event
self._result["lb"].append(event)
self._sss["max"] = event self._sss["max"] = event
self._result["lt"].append(event)
elif event.get_y() < self._sss["min"].get_y(): elif event.get_y() < self._sss["min"].get_y():
self._result["rb"].append(linesegment.LineSegment(self._sss["min"], event)) self._result["lb"].append(event)
self._sss["min"] = event self._sss["min"] = event
elif event.get_y() > self._sss["max"].get_y(): elif event.get_y() > self._sss["max"].get_y():
self._result["rt"].append(linesegment.LineSegment(self._sss["max"], event)) self._result["lt"].append(event)
self._sss["max"] = event self._sss["max"] = event
super().step() super().step()
if len(self._es) == 0: if len(self._es) == 0:
self._sss["min"] = None self._sss["min"] = None
self._sss["max"] = None self._sss["max"] = None
self._es = copy.deepcopy(self._input).reverse() self._es = copy.deepcopy(self._input)
self._num_steps["sort"] = point.sort_set(self._es)
self._section = "sweep-right-to-left" self._section = "sweep-right-to-left"
elif self._section == "sweep-right-to-left": elif self._section == "sweep-right-to-left":
event = self._es.pop(0) event = self._es.pop(-1)
if self._sss["min"] is None or self._sss["max"] is None: if self._sss["min"] is None or self._sss["max"] is None:
self._sss["min"] = event self._sss["min"] = event
self._result["rb"].append(event)
self._sss["max"] = event self._sss["max"] = event
self._result["rt"].append(event)
elif event.get_y() < self._sss["min"].get_y(): elif event.get_y() < self._sss["min"].get_y():
self._result["rb"].append(linesegment.LineSegment(self._sss["min"], event)) self._result["rb"].append(event)
self._sss["min"] = event self._sss["min"] = event
elif event.get_y() > self._sss["max"].get_y(): elif event.get_y() > self._sss["max"].get_y():
self._result["rt"].append(linesegment.LineSegment(self._sss["max"], event)) self._result["rt"].append(event)
self._sss["max"] = event self._sss["max"] = event
super().step() super().step()
if len(self._es) == 0: if len(self._es) == 0:
self._es = copy.deepcopy(self._result["lt"])
self._section = "sweep-left-to-top" self._section = "sweep-left-to-top"
elif self._section == "sweep-left-to-top": elif self._section == "sweep-left-to-top":
event = self._es.pop(0) event = self._es.pop(0)
self._sss["lt"].append(event)
start_idx = len(self._sss["lt"]) - 1
for i in range(start_idx, 0, -1):
if len(self._es) > 0:
slope_a = linesegment.LineSegment( \
self._sss["lt"][i-1], self._sss["lt"][i]).get_slope()
slope_b = linesegment.LineSegment(self._sss["lt"][i], self._es[0]).get_slope()
super().step()
if slope_a < slope_b:
del self._sss["lt"][i]
else:
break
else:
break
if len(self._es) == 0: if len(self._es) == 0:
self._result["lt"] = copy.deepcopy(self._sss["lt"])
self._es = copy.deepcopy(self._result["lb"])
self._section = "sweep-left-to-bottom" self._section = "sweep-left-to-bottom"
elif self._section == "sweep-left-to-bottom": elif self._section == "sweep-left-to-bottom":
event = self._es.pop(0) event = self._es.pop(0)
self._sss["lb"].append(event)
start_idx = len(self._sss["lb"]) - 1
for i in range(start_idx, 0, -1):
if len(self._es) > 0:
slope_a = linesegment.LineSegment( \
self._sss["lb"][i-1], self._sss["lb"][i]).get_slope()
slope_b = linesegment.LineSegment(self._sss["lb"][i], self._es[0]).get_slope()
super().step()
if slope_a > slope_b:
del self._sss["lb"][i]
else:
break
else:
break
if len(self._es) == 0: if len(self._es) == 0:
self._result["lb"] = copy.deepcopy(self._sss["lb"])
self._es = copy.deepcopy(self._result["rt"])
self._section = "sweep-right-to-top" self._section = "sweep-right-to-top"
elif self._section == "sweep-right-to-top": elif self._section == "sweep-right-to-top":
event = self._es.pop(0) event = self._es.pop(0)
self._sss["rt"].append(event)
start_idx = len(self._sss["rt"]) - 1
for i in range(start_idx, 0, -1):
if len(self._es) > 0:
slope_a = linesegment.LineSegment( \
self._sss["rt"][i-1], self._sss["rt"][i]).get_slope()
slope_b = linesegment.LineSegment(self._sss["rt"][i], self._es[0]).get_slope()
super().step()
if slope_a > slope_b:
del self._sss["rt"][i]
else:
break
else:
break
if len(self._es) == 0: if len(self._es) == 0:
self._result["rt"] = copy.deepcopy(self._sss["rt"])
self._es = copy.deepcopy(self._result["rb"])
self._section = "sweep-right-to-bottom" self._section = "sweep-right-to-bottom"
elif self._section == "sweep-right-to-bottom": elif self._section == "sweep-right-to-bottom":
event = self._es.pop(0) event = self._es.pop(0)
self._sss["rb"].append(event)
start_idx = len(self._sss["rb"]) - 1
for i in range(start_idx, 0, -1):
if len(self._es) > 0:
slope_a = linesegment.LineSegment( \
self._sss["rb"][i-1], self._sss["rb"][i]).get_slope()
slope_b = linesegment.LineSegment(self._sss["rb"][i], self._es[0]).get_slope()
super().step()
if slope_a < slope_b:
del self._sss["rb"][i]
else:
break
else:
break
if len(self._es) == 0: if len(self._es) == 0:
self._result["rb"] = copy.deepcopy(self._sss["rb"])
self._section = "report-hull" self._section = "report-hull"
elif self._section == "report-hull": elif self._section == "report-hull":
for line in self._result["lb"]: for i in range(len(self._result["lb"]) - 1):
self._result["hull"].append(line) self._result["hull"].append(self._result["lb"][i])
for line in self._result["rb"].reverse(): for i in range(len(self._result["rb"]) - 1, 0, -1):
self._result["hull"].append(line) self._result["hull"].append(self._result["rb"][i])
for line in self._result["rt"]: for i in range(len(self._result["rt"]) - 1):
self._result["hull"].append(line) self._result["hull"].append(self._result["rt"][i])
for line in self._result["lt"].reverse(): for i in range(len(self._result["lt"]) - 1, 0, -1):
self._result["hull"].append(line) self._result["hull"].append(self._result["lt"][i])
self._result["success"] = True self._result["success"] = True
self._running = False self._running = False
def draw(self, canvas, width, height, max_x, max_y):
if self._running:
pass
else:
for i in range(len(self._result["hull"]) - 1):
linesegment.LineSegment( \
self._result["hull"][i], self._result["hull"][i+1]) \
.draw(canvas, width, height, max_x, max_y, "#FF0000")
linesegment.LineSegment( \
self._result["hull"][-1], self._result["hull"][0]) \
.draw(canvas, width, height, max_x, max_y, "#FF0000")
for pnt in self._input:
if pnt in self._result["hull"]:
pnt.draw(canvas, width, height, max_x, max_y, "#000000")
else:
pnt.draw(canvas, width, height, max_x, max_y, "#777777")