Clean Polyline and Points
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user