Files
computational-geometry-visu/algorithm.py
Pascal Lais 7210a94995 Convert sweep module and class to algorithm
Since an algorithm can use more than one sweep, the sweep class doesn't
fit very good as it is right now. For this reasen it got converted to a
more general class named algorithm, that shall be used as parent for
every individual algorithm. The exact behaviour of the algorithm is
then defined in the child classes.
2020-03-09 17:41:37 +01:00

137 lines
5.0 KiB
Python

#!/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 Sweep class is the base class for each individual sweep algorithm"
# pylint: disable=too-many-instance-attributes
def __init__(self):
self._input = None # The input values
self._result = None # 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._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 get_result(self):
return self._result
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, \
"MinDistSoFar": None, \
"Startpoint": None, \
"Endpoint": None}
def exec(self):
"""Execute the sweep. Returns True on success and False on failure."""
if not self.start():
return False
while self._running:
self.step()
return self._result
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 = []
# Populate event structure
self._es = copy.deepcopy(self._input)
# Sort the input elements
self._num_steps["sort"] = point.sort_point_set(self._es)
self._num_steps["sweep"] = 0
return True
def step(self):
"""Perform a single step of the algorithm."""
if not self._running:
return
event = self._es.pop(0)
if self._result["MinDistSoFar"] is not None:
while len(self._sss) > 0 and \
self._sss[0].get_x() <= (event.get_x() - self._result["MinDistSoFar"]):
del self._sss[0]
for pnt in self._sss:
if self._result["MinDistSoFar"] is None:
self._result["MinDistSoFar"] = linesegment.LineSegment(pnt, event).get_length()
elif (event.get_y() - self._result["MinDistSoFar"]) < \
pnt.get_y() < (event.get_y() + self._result["MinDistSoFar"]):
distance = linesegment.LineSegment(pnt, event).get_length()
if self._result["MinDistSoFar"] > distance > 0:
self._result["MinDistSoFar"] = distance
self._result["Startpoint"] = pnt
self._result["Endpoint"] = event
self._num_steps["sweep"] += 1
self._sss.append(event)
if len(self._es) == 0:
self._result["Success"] = True
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 pnt in self._input:
result_string += pnt.str() + ", "
result_string += "]\n"
result_string += " Nearest Neighbors: "
result_string += linesegment.LineSegment(self._result["Startpoint"], \
self._result["Endpoint"]).str()
result_string += "\n"
result_string += " Distance: " + str(self._result["MinDistSoFar"]) + "\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