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] \
).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"""
@@ -220,7 +220,11 @@ class ConvexHull(Algorithm):
self._result["success"] = False
self._sss = {"max": None, \
"min": None}
"min": None, \
"lt": [], \
"lb": [], \
"rt": [], \
"rb": []}
# Populate event structure
self._es = copy.deepcopy(self._input)
# Sort the input elements
@@ -236,66 +240,150 @@ class ConvexHull(Algorithm):
event = self._es.pop(0)
if self._sss["min"] is None or self._sss["max"] is None:
self._sss["min"] = event
self._result["lb"].append(event)
self._sss["max"] = event
self._result["lt"].append(event)
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
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
super().step()
if len(self._es) == 0:
self._sss["min"] = 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"
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:
self._sss["min"] = event
self._result["rb"].append(event)
self._sss["max"] = event
self._result["rt"].append(event)
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
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
super().step()
if len(self._es) == 0:
self._es = copy.deepcopy(self._result["lt"])
self._section = "sweep-left-to-top"
elif self._section == "sweep-left-to-top":
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:
self._result["lt"] = copy.deepcopy(self._sss["lt"])
self._es = copy.deepcopy(self._result["lb"])
self._section = "sweep-left-to-bottom"
elif self._section == "sweep-left-to-bottom":
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:
self._result["lb"] = copy.deepcopy(self._sss["lb"])
self._es = copy.deepcopy(self._result["rt"])
self._section = "sweep-right-to-top"
elif self._section == "sweep-right-to-top":
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:
self._result["rt"] = copy.deepcopy(self._sss["rt"])
self._es = copy.deepcopy(self._result["rb"])
self._section = "sweep-right-to-bottom"
elif self._section == "sweep-right-to-bottom":
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:
self._result["rb"] = copy.deepcopy(self._sss["rb"])
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)
for i in range(len(self._result["lb"]) - 1):
self._result["hull"].append(self._result["lb"][i])
for i in range(len(self._result["rb"]) - 1, 0, -1):
self._result["hull"].append(self._result["rb"][i])
for i in range(len(self._result["rt"]) - 1):
self._result["hull"].append(self._result["rt"][i])
for i in range(len(self._result["lt"]) - 1, 0, -1):
self._result["hull"].append(self._result["lt"][i])
self._result["success"] = True
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")