diff --git a/main.py b/main.py index 6efc190..747834d 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,5 @@ +from networks.geometry.Polyline import Polyline +from networks.geometry.Point2D import Point2D import networks.roads.lines.Line as Line import networks.roads.lanes.Lane as Lane from gdpc import Editor, Block, geometry @@ -244,7 +246,17 @@ block_list = ["blue_concrete", "red_concrete", "green_concrete", # --- -r = Road.Road(((-1829, 141, 553), (-1830, 110, 621), (-1711, 69, 625), (-1662, - 65, 627), (-1667, 65, 761), (-1683, 70, 800), (-1721, 70, 834)), "None") +# r = Road.Road(((-1829, 141, 553), (-1830, 110, 621), (-1711, 69, 625), (-1662, +# 65, 627), (-1667, 65, 761), (-1683, 70, 800), (-1721, 70, 834)), "None") -r.place_roads() +# r.place_roads() + + +polyline = Polyline((Point2D(0, 0), Point2D(0, 10), + Point2D(50, 10), Point2D(20, 20))) + + +# print(polyline.radius_balance(2)) + +# polyline._alpha_assign(1, polyline.length_polyline-1) +print(polyline.alpha_radii) diff --git a/networks/geometry/Point2D.py b/networks/geometry/Point2D.py index c50a6a7..1d02ab7 100644 --- a/networks/geometry/Point2D.py +++ b/networks/geometry/Point2D.py @@ -1,21 +1,20 @@ -from typing import Type +import numpy as np +import math class Point2D: def __init__(self, x: int, y: int): self.x = x self.y = y + self.coordinate = (self.x, self.y) def copy(self): return Point2D(self.x, self.y) - def coordinates(self): - return (self.x, self.y) - def __repr__(self): return f"Point2D(x: {self.x}, y: {self.y})" - def is_in_triangle(self, xy0: Type[Point2D], xy1: Type[Point2D], xy2: Type[Point2D]): + def is_in_triangle(self, xy0: "Point2D", xy1: "Point2D", xy2: "Point2D"): """Returns True is the point is in a triangle defined by 3 others points. From: https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle#:~:text=A%20simple%20way%20is%20to,point%20is%20inside%20the%20triangle. @@ -27,6 +26,9 @@ class Point2D: Returns: bool: False if the point is not inside the triangle. + + >>> Point2D(0, 0).is_in_triangle(Point2D(10, 10), Point2D(-10, 20), Point2D(0, -20))) + True """ dx = self.x - xy0.x dy = self.y - xy0.y @@ -45,5 +47,31 @@ class Point2D: else: return (s_p <= 0) and (t_p <= 0) and (s_p + t_p) >= d - def distance(self, point: Type[Point2D]): + def distance(self, point: "Point2D"): return sqrt((point.x - self.x) ** 2 + (point.y - self.y) ** 2) + + def angle(self, xy1, xy2): + """ + Compute angle (in degrees). Corner in current point. + + From: https://stackoverflow.com/questions/13226038/calculating-angle-between-two-vectors-in-python + + Args: + xy0 (numpy.ndarray): Points in the form of [x,y]. + xy1 (numpy.ndarray): Points in the form of [x,y]. + xy2 (numpy.ndarray): Points in the form of [x,y]. + + Returns: + float: Angle negative for counterclockwise angle, angle positive + for counterclockwise angle. + + >>> Point2D(0, 0).angle(Point2D(10, 10), Point2D(0, -20)) + -135.0 + """ + if xy2 is None: + xy2 = xy1.coordinate + np.array([1, 0]) + v0 = np.array(xy1.coordinate) - np.array(self.coordinate) + v1 = np.array(xy2.coordinate) - np.array(self.coordinate) + + angle = math.atan2(np.linalg.det([v0, v1]), np.dot(v0, v1)) + return np.degrees(angle) diff --git a/networks/geometry/Point3D.py b/networks/geometry/Point3D.py index 393fa24..e94598e 100644 --- a/networks/geometry/Point3D.py +++ b/networks/geometry/Point3D.py @@ -1,6 +1,3 @@ -from typing import Type - - class Point3D: def __init__(self, x: int, y: int, z: int): self.x = x @@ -16,5 +13,5 @@ class Point3D: def __repr__(self): return f"Point2D(x: {self.x}, y: {self.y}, z: {self.z})" - def distance(self, point: Type[Point3D]): + def distance(self, point: "Point3D"): return sqrt((point.x - self.x) ** 2 + (point.y - self.y) ** 2 + (point.z - self.z) ** 2) diff --git a/networks/geometry/Polyline.py b/networks/geometry/Polyline.py index 39bae5c..6f3a37e 100644 --- a/networks/geometry/Polyline.py +++ b/networks/geometry/Polyline.py @@ -1,12 +1,12 @@ -from typing import Type from networks.geometry.Point2D import Point2D +from networks.geometry.point_tools import coordinates_to_vectors from math import sqrt, inf import numpy as np class Polyline: - def __init__(self, points: List[Point2D]): + def __init__(self, points: list["Point2D"]): """A polyline with smooth corners, only composed of segments and circle arc. Mathematics and algorithms behind this can be found here: https://cdr.lib.unc.edu/concern/dissertations/pz50gw814?locale=en, E2 Construction of arc roads from polylines, page 210. @@ -16,6 +16,8 @@ class Polyline: Raises: ValueError: At least 4 points required. + + >>> Polyline((Point2D(0, 0), Point2D(0, 10), Point2D(50, 10), Point2D(20, 20))) """ self.points = coordinates_to_vectors(points) self.length_polyline = len(points) @@ -26,16 +28,16 @@ class Polyline: self.vectors = [None] * self.length_polyline self.lengths = [None] * self.length_polyline self.unit_vectors = [None] * self.length_polyline - self.tangente = [None] * self.length_polyline + self.tangente = [0] * self.length_polyline self.alpha_radii = [None] * self.length_polyline self._compute_requirements() self._compute_alpha_radii() - _alpha_assign(0, self.length_polyline-1) + self._alpha_assign(0, self.length_polyline-1) - def _alpha_assign(self, start_index, end_index): + def _alpha_assign(self, start_index: int, end_index: int): """ The alpha-assign procedure assigning radii based on a polyline. """ @@ -61,7 +63,6 @@ class Polyline: # Assign alphas at ends of selected segment self.alpha_radii[minimum_index] = alpha_low self.alpha_radii[minimum_index+1] = alpha_high - print(alpha_low, alpha_high) # Recur on lower segments self._alpha_assign(start_index, minimum_index) @@ -100,16 +101,3 @@ class Polyline: for i in range(1, self.length_polyline-2): self.alpha_radii[i] = min(self.lengths[i-1] - self.alpha_radii[i-1], (self.lengths[i] * self.tangente[i+1])/(self.tangente[i]+self.tangente[i+1])) - - -# polyline = Polyline((Point2D(0, 9), Point2D(0, 10), Point2D( -# 10, 10), Point2D(10, 20), Point2D(20, 20), Point2D(20, 30), Point2D(60, 60), Point2D(-60, -60))) - -polyline = Polyline((Point2D(0, 10), Point2D(-10, -10), - Point2D(20, 0), Point2D(20, 20))) - - -# print(polyline.radius_balance(2)) - -polyline._alpha_assign(1, polyline.length_polyline-1) -print(polyline.alpha_radii) diff --git a/networks/geometry/point_tools.py b/networks/geometry/point_tools.py index 24ab3db..195ca6d 100644 --- a/networks/geometry/point_tools.py +++ b/networks/geometry/point_tools.py @@ -3,35 +3,6 @@ import numpy as np from networks.geometry.segment_tools import discrete_segment, middle_point, parallel -def distance(xy1, xy2): # TODO : Can be better. - # Works in 2d but supports 3d. - return sqrt((xy2[0] - xy1[0]) ** 2 + (xy2[-1] - xy1[-1]) ** 2) - - -def get_angle(xy0, xy1, xy2): - """ - Compute angle (in degrees) for xy0, xy1, xy2 corner. - - https://stackoverflow.com/questions/13226038/calculating-angle-between-two-vectors-in-python - - Args: - xy0 (numpy.ndarray): Points in the form of [x,y]. - xy1 (numpy.ndarray): Points in the form of [x,y]. - xy2 (numpy.ndarray): Points in the form of [x,y]. - - Returns: - float: Angle negative for counterclockwise angle, angle positive - for counterclockwise angle. - """ - if xy2 is None: - xy2 = xy1 + np.array([1, 0]) - v0 = np.array(xy0) - np.array(xy1) - v1 = np.array(xy2) - np.array(xy1) - - angle = np.math.atan2(np.linalg.det([v0, v1]), np.dot(v0, v1)) - return np.degrees(angle) - - def circle_points(center_point, radius, number=100): # Works in 2d but supports 3d. # https://stackoverflow.com/questions/8487893/generate-all-the-points-on-the-circumference-of-a-circle @@ -467,7 +438,7 @@ def curved_corner_by_curvature( def coordinates_to_vectors(coordinates): vectors = [] for coordinate in coordinates: - vectors.append(np.array(coordinate.get_coordinates())) + vectors.append(np.array(coordinate.coordinate)) if (len(vectors) == 1): return vectors[0]