Add missing parts of ConvexHullIncremental
All checks were successful
continuous-integration/drone/push Build is passing
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:
124
algorithm.py
124
algorithm.py
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user