Files
computational-geometry-visu/linesegment.py
Pascal Lais cf004ec5de
All checks were successful
continuous-integration/drone/push Build is passing
Add __getitem__ and __setitem__ for linesegment
2020-03-22 18:40:54 +01:00

124 lines
5.5 KiB
Python

#!/usr/bin/python3
"""The linesegment module defines the class LineSegment."""
import random
import point
class LineSegment:
"""The class LineSegment defines a two-dimensional line segment in the coordinate system
starting at a startpoint and ending at a endpoint."""
def __init__(self, startpoint=point.Point(), endpoint=point.Point()):
"""Initialize the line segment."""
self.set_startpoint(startpoint)
self.set_endpoint(endpoint)
def set_startpoint(self, new_startpoint):
"""Set or change the startpoint of the line segment. If not a Point object is given
the startpoint gets set to a default value of Point(0,0)."""
self.__startpoint = new_startpoint
def get_startpoint(self):
"""Returns the current startpoint"""
return self.__startpoint
def set_endpoint(self, new_endpoint):
"""Set or change the endpoint of the line segment. If not a Point object is given
the endpoint gets set to a default value of Point(0,0)."""
self.__endpoint = new_endpoint
def get_endpoint(self):
"""Returns the current endpoint"""
return self.__endpoint
def get_length(self):
"""Returns the length of the line segment."""
diff_x = abs(self.__startpoint.get_x() - self.__endpoint.get_x())
diff_y = abs(self.__startpoint.get_y() - self.__endpoint.get_y())
return ((diff_x ** 2) + (diff_y ** 2)) ** (1/2.0)
def get_slope(self):
"""Calculate and return the slope of the line segment"""
if self.__startpoint.get_x() == self.__endpoint.get_x():
return None
diff_x = self.__endpoint.get_x() - self.__startpoint.get_x()
diff_y = self.__endpoint.get_y() - self.__startpoint.get_y()
return diff_y / diff_x
def get_y_at(self, x_val):
"""Returns the y value of the line at a specific x coordinate"""
slope = self.get_slope()
start_x = self.__startpoint.get_x()
start_y = self.__startpoint.get_y()
y_intercept = start_y - (slope * start_x)
return (slope * x_val) + y_intercept
def get_min_x(self):
"""Get the lowest x coordinate of the line segment"""
return min(self.__startpoint.get_x(), self.__endpoint.get_x())
def get_max_x(self):
"""Get the highest x coordinate of the line segment"""
return max(self.__startpoint.get_x(), self.__endpoint.get_x())
def get_min_y(self):
"""Get the lowest y coordinate of the line segment"""
return min(self.__startpoint.get_y(), self.__endpoint.get_y())
def get_max_y(self):
"""Get the highest y coordinate of the line segment"""
return max(self.__startpoint.get_y(), self.__endpoint.get_y())
def __getitem__(self, index):
"""Get an Endpoint by index"""
if index == 0:
return self.__startpoint
elif index == 1:
return self.__endpoint
else:
return None
def __setitem__(self, index, value):
"""Set an Endpoint by index"""
if index == 0:
self.set_startpoint(value)
elif index == 1:
self.set_endpoint(value)
def __str__(self):
"""Return the line segment values as string."""
return str(self.__startpoint) + "-->" + str(self.__endpoint)
def draw(self, canvas, width, height, max_x, max_y, color="#000000"):
"""Draw the line segment in a canvas."""
from_x, from_y = self.__startpoint.draw(canvas, width, height, max_x, max_y, color)
to_x, to_y = self.__endpoint.draw(canvas, width, height, max_x, max_y, color)
canvas.create_line(from_x, from_y, to_x, to_y, fill=color)
def get_random(min_x=0, max_x=100, min_y=0, max_y=100):
"""Set the point to a random place inside the boundaries"""
seg = LineSegment(point.Point(random.randint(min_x, max_x), random.randint(min_y, max_y)), \
point.Point(random.randint(min_x, max_x), random.randint(min_y, max_y)))
while seg.get_startpoint().get_x() == seg.get_endpoint().get_x():
seg = LineSegment(point.Point(random.randint(min_x, max_x), random.randint(min_y, max_y)), \
point.Point(random.randint(min_x, max_x), random.randint(min_y, max_y)))
return seg
def intersection(ls_a, ls_b):
"""Calculate the intersection between two line segments. Returns None if there isn't a
intersection, the Point of the intersection if there is one or the overlapping linesegment"""
res = None
# Check if intervalls are overlapping
if ls_a.get_max_x() < ls_b.get_min_x() or \
ls_a.get_min_x() > ls_b.get_max_x() or \
ls_a.get_max_y() < ls_b.get_min_y() or \
ls_a.get_min_y() > ls_b.get_max_y():
res = None
elif ls_a.get_slope() == ls_b.get_slope():
if ls_a.get_y_at(0) == ls_b.get_y_at(0):
startpoint = None
endpoint = None
if ls_a.get_startpoint().get_x() > ls_b.get_startpoint().get_x():
startpoint = ls_a.get_startpoint()
else:
startpoint = ls_b.get_startpoint()
if ls_a.get_endpoint().get_x() < ls_b.get_endpoint().get_x():
endpoint = ls_a.get_endpoint()
else:
endpoint = ls_b.get_endpoint()
res = LineSegment(startpoint, endpoint)
else:
x_val = (ls_a.get_y_at(0) - ls_b.get_y_at(0)) / \
(ls_b.get_slope() - ls_a.get_slope())
if ls_a.get_min_x() <= x_val <= ls_a.get_max_x():
y_val = (ls_a.get_slope() * x_val) + ls_a.get_y_at(0)
res = point.Point(x_val, y_val)
return res