#!/usr/bin/python3 """The sweep module defines a base class sweep for various sweep algorithms. It also contains a child-class for each individual algorithm.""" import copy import linesegment import point class Algorithm(): "The Algorithm class is the base class for each individual algorithm" def __init__(self): self._input = None # The input values self._result = {} # The result of the sweep self._ready = False # If the sweep is reade to be executed self._running = False # If the sweep is currently running self._section = "start" # A string that names the current section of the algorithm self._num_steps = {} # The number of steps that were needed to solve the problem def start(self): """Start the performing the algorithm. Return True if it was successful""" if not self._ready: print("Error: Sweep is not yet ready to be performed") return False self._running = True return True def step(self): """Perform a single step of the algorithm.""" if self._section: if self._section in self._num_steps: self._num_steps[self._section] += 1 else: self._num_steps[self._section] = 1 def run(self): """Execute the sweep. Returns the result dict.""" if not self.start(): return False while self._running: self.step() return self._result def get_result(self): """Return the result of the algorithm.""" return self._result def draw(self): """Dummy for draw method""" class NearestNeighborsSweep(Algorithm): """Calculate the pair of points inside a set, that have the minimal distance between each other inside this set""" 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 = {} self._es = [] self._result = {"success": False, \ "distance": None, \ "points": [None, None]} 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 = {"mindist": None, \ "points": []} # Populate event structure self._es = copy.deepcopy(self._input) # Sort the input elements self._num_steps["sort"] = point.sort_set(self._es) return True def step(self): """Perform a single step of the algorithm.""" if not self._running: return self._section = "sweep" event = self._es.pop(0) if self._sss["mindist"] is not None: while len(self._sss["points"]) > 0 and \ self._sss["points"][0].get_x() <= (event.get_x() - self._sss["mindist"]): del self._sss["points"][0] for pnt in self._sss["points"]: if self._sss["mindist"] is None: self._sss["mindist"] = linesegment.LineSegment(pnt, event).get_length() elif (event.get_y() - self._sss["mindist"]) < \ pnt.get_y() < (event.get_y() + self._sss["mindist"]): distance = linesegment.LineSegment(pnt, event).get_length() if self._sss["mindist"] > distance > 0: self._sss["mindist"] = distance self._result["points"][0] = pnt self._result["points"][1] = event super().step() self._sss["points"].append(event) if len(self._es) == 0: self._result["success"] = True self._result["distance"] = self._sss["mindist"] self._running = False def get_result_string(self, print_result=False): """Pack the result into a string.""" result_string = "" if self._running: result_string = "Sweep is still running." elif not self._result["success"]: result_string = "Sweep was not successful." else: result_string = "Sweep successfully completed\n" result_string += " Summary:\n" result_string += " Number of Inputs:" + str(len(self._input)) + "\n" result_string += " Inputs: [" for i, pnt in enumerate(self._input): if i: result_string += "," result_string += pnt.str() result_string += "]\n" result_string += " Nearest Neighbors: " result_string += linesegment.LineSegment(self._result["points"][0], \ self._result["points"][1]).str() result_string += "\n" result_string += " Distance: " + str(self._result["distance"]) + "\n" result_string += " Number of steps:\n" result_string += " Sort:" + str(self._num_steps["sort"]) +"\n" result_string += " Sweep:" + str(self._num_steps["sweep"]) +"\n" if print_result: print(result_string) return result_string def draw(self): """TODO: Draw the algorithm state on a canvas"""