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] \
|
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")
|
||||||
|
|||||||
Reference in New Issue
Block a user