Finalize Polyline parsing but still arcs precision issue
This commit is contained in:
148
main.py
148
main.py
@@ -1,31 +1,33 @@
|
||||
|
||||
from Enums import LINE_OVERLAP, LINE_THICKNESS_MODE, ROTATION
|
||||
from PIL import Image, ImageDraw
|
||||
import matplotlib.pyplot as plt
|
||||
from networks.geometry.Point3D import Point3D
|
||||
from networks.geometry.Segment3D import Segment3D
|
||||
from networks.geometry.Segment2D import Segment2D
|
||||
from networks.geometry.Circle import Circle
|
||||
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
|
||||
import networks.geometry.curve_tools as curve_tools
|
||||
import networks.geometry.Strip as Strip
|
||||
import networks.geometry.segment_tools as segment_tools
|
||||
import numpy as np
|
||||
import json
|
||||
from buildings.Building import Building
|
||||
import random
|
||||
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from gdpc import Block, Editor, geometry
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
import networks.geometry.curve_tools as curve_tools
|
||||
import networks.geometry.segment_tools as segment_tools
|
||||
import networks.geometry.Strip as Strip
|
||||
import networks.roads.lanes.Lane as Lane
|
||||
import networks.roads.lines.Line as Line
|
||||
from buildings.Building import Building
|
||||
from Enums import LINE_OVERLAP, LINE_THICKNESS_MODE, ROTATION
|
||||
from networks.geometry.Circle import Circle
|
||||
from networks.geometry.Point2D import Point2D
|
||||
from networks.geometry.Point3D import Point3D
|
||||
from networks.geometry.point_tools import (
|
||||
curved_corner_by_curvature,
|
||||
curved_corner_by_distance,
|
||||
)
|
||||
from networks.geometry.Polyline import Polyline
|
||||
from networks.geometry.Segment2D import Segment2D
|
||||
from networks.geometry.Segment3D import Segment3D
|
||||
from networks.roads import Road as Road
|
||||
from networks.roads.intersections import Intersection as Intersection
|
||||
|
||||
from networks.geometry.point_tools import curved_corner_by_curvature, curved_corner_by_distance
|
||||
|
||||
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
|
||||
|
||||
@@ -286,18 +288,26 @@ block_list = ["blue_concrete", "red_concrete", "green_concrete",
|
||||
# p = Polyline((Point2D(-1225, 468), Point2D(-1138, 481),
|
||||
# Point2D(-1188, 451), Point2D(-1176, 409), Point2D(-1179, 399)))
|
||||
|
||||
w = 200
|
||||
w = 100
|
||||
|
||||
n_points = 20
|
||||
n_points = 8
|
||||
min_val, max_val = -w, w
|
||||
|
||||
random_points = [Point2D(random.randint(min_val, max_val), random.randint(
|
||||
min_val, max_val)) for _ in range(n_points)]
|
||||
|
||||
print(random_points)
|
||||
print("\n\n")
|
||||
|
||||
|
||||
# random_points = (Point2D(-75, -75), Point2D(0, -75), Point2D(75, 75),
|
||||
# Point2D(75, -50), Point2D(-50, 50), Point2D(0, 0))
|
||||
|
||||
# random_points = random_points[0].optimized_path(random_points)
|
||||
|
||||
# random_points = [Point2D(-40, -56), Point2D(-94, 92), Point2D(19, -47), Point2D(
|
||||
# 100, 59), Point2D(-85, -73), Point2D(-33, -9), Point2D(57, -25), Point2D(51, -34)]
|
||||
|
||||
random_points = random_points[0].optimized_path(random_points)
|
||||
|
||||
p = Polyline(random_points)
|
||||
@@ -316,10 +326,8 @@ image = Image.new('RGB', (width, height), 'black')
|
||||
|
||||
draw = ImageDraw.Draw(image)
|
||||
|
||||
print(p.output_points)
|
||||
|
||||
for i in range(len(p.output_points)-1):
|
||||
if p.output_points[i] != None:
|
||||
if p.output_points[i] != 0:
|
||||
s = Segment2D(Point2D(p.output_points[i].x, p.output_points[i].y), Point2D(
|
||||
p.output_points[i+1].x, p.output_points[i+1].y))
|
||||
s.segment_thick(ww, LINE_THICKNESS_MODE.MIDDLE)
|
||||
@@ -331,40 +339,40 @@ for i in range(len(p.output_points)-1):
|
||||
w-s.points_thick[j].y), fill='grey')
|
||||
|
||||
|
||||
for i in range(2, len(p.get_arcs_intersections())-2):
|
||||
# for i in range(2, len(p.get_arcs_intersections())-2):
|
||||
|
||||
s = Segment2D(Point2D(p.acrs_intersections[i][0].x, p.acrs_intersections[i][0].y), Point2D(
|
||||
p.acrs_intersections[i-1][-1].x, p.acrs_intersections[i-1][-1].y))
|
||||
s.segment_thick(ww, LINE_THICKNESS_MODE.MIDDLE)
|
||||
# s = Segment2D(Point2D(p.acrs_intersections[i][0].x, p.acrs_intersections[i][0].y), Point2D(
|
||||
# p.acrs_intersections[i-1][-1].x, p.acrs_intersections[i-1][-1].y))
|
||||
# s.segment_thick(ww, LINE_THICKNESS_MODE.MIDDLE)
|
||||
|
||||
for j in range(len(s.points_thick)-1):
|
||||
# editor.placeBlock(
|
||||
# s.coordinates[j].coordinate, Block("cyan_concrete"))
|
||||
draw.point((s.points_thick[j].x+w,
|
||||
w-s.points_thick[j].y), fill='white')
|
||||
draw.point((p.acrs_intersections[i][0].x+w,
|
||||
w-p.acrs_intersections[i][0].y), fill='blue')
|
||||
draw.point((p.acrs_intersections[i][-1].x+w,
|
||||
w-p.acrs_intersections[i][-1].y), fill='red')
|
||||
# for j in range(len(s.points_thick)-1):
|
||||
# # editor.placeBlock(
|
||||
# # s.coordinates[j].coordinate, Block("cyan_concrete"))
|
||||
# draw.point((s.points_thick[j].x+w,
|
||||
# w-s.points_thick[j].y), fill='green')
|
||||
# draw.point((p.acrs_intersections[i][0].x+w,
|
||||
# w-p.acrs_intersections[i][0].y), fill='green')
|
||||
# draw.point((p.acrs_intersections[i][-1].x+w,
|
||||
# w-p.acrs_intersections[i][-1].y), fill='green')
|
||||
|
||||
|
||||
for i in range(len(center)):
|
||||
if center[i]:
|
||||
circle = Circle(center[i])
|
||||
circle.circle_thick(round(radius[i]-ww/2), round(radius[i]+ww/2))
|
||||
for j in range(len(circle.points_thick)-1):
|
||||
if circle.points_thick[j].is_in_triangle(p.acrs_intersections[i][0], p.acrs_intersections[i][1], p.acrs_intersections[i][2]):
|
||||
# editor.placeBlock(
|
||||
# (circle.coordinates[j].x, y, circle.coordinates[j].y), Block("white_concrete"))
|
||||
draw.point((circle.points_thick[j].x+w,
|
||||
w-circle.points_thick[j].y), fill='white')
|
||||
circle.circle(radius[i])
|
||||
for j in range(len(circle.points)-1):
|
||||
if circle.points[j].is_in_triangle(p.acrs_intersections[i][0], p.acrs_intersections[i][1], p.acrs_intersections[i][2]):
|
||||
# editor.placeBlock(
|
||||
# (circle.coordinates[j].x, y, circle.coordinates[j].y), Block("white_concrete"))
|
||||
draw.point((circle.points[j].x+w,
|
||||
w-circle.points[j].y), fill='purple')
|
||||
# for i in range(len(center)):
|
||||
# if center[i]:
|
||||
# circle = Circle(center[i])
|
||||
# circle.circle_thick(round(radius[i]-ww/2), round(radius[i]+ww/2))
|
||||
# for j in range(len(circle.points_thick)-1):
|
||||
# if circle.points_thick[j].is_in_triangle(p.acrs_intersections[i][0], p.acrs_intersections[i][1], p.acrs_intersections[i][2]):
|
||||
# # editor.placeBlock(
|
||||
# # (circle.coordinates[j].x, y, circle.coordinates[j].y), Block("white_concrete"))
|
||||
# draw.point((circle.points_thick[j].x+w,
|
||||
# w-circle.points_thick[j].y), fill='green')
|
||||
# circle.circle(radius[i])
|
||||
# for j in range(len(circle.points)-1):
|
||||
# if circle.points[j].is_in_triangle(p.acrs_intersections[i][0], p.acrs_intersections[i][1], p.acrs_intersections[i][2]):
|
||||
# # editor.placeBlock(
|
||||
# # (circle.coordinates[j].x, y, circle.coordinates[j].y), Block("white_concrete"))
|
||||
# draw.point(
|
||||
# (circle.points[j].x+w, w-circle.points[j].y), fill='green')
|
||||
|
||||
s1 = Segment2D(Point2D(p.acrs_intersections[1][0].x, p.acrs_intersections[1][0].y), Point2D(
|
||||
p.output_points[0].x, p.output_points[0].y))
|
||||
@@ -372,7 +380,7 @@ s1.segment_thick(ww, LINE_THICKNESS_MODE.MIDDLE)
|
||||
|
||||
for j in range(len(s1.points_thick)-1):
|
||||
draw.point((s1.points_thick[j].x+w,
|
||||
w-s1.points_thick[j].y), fill='white')
|
||||
w-s1.points_thick[j].y), fill='grey')
|
||||
|
||||
s1 = Segment2D(Point2D(p.acrs_intersections[-2][2].x, p.acrs_intersections[-2][2].y), Point2D(
|
||||
p.output_points[-1].x, p.output_points[-1].y))
|
||||
@@ -380,10 +388,34 @@ s1.segment_thick(ww, LINE_THICKNESS_MODE.MIDDLE)
|
||||
|
||||
for j in range(len(s1.points_thick)-1):
|
||||
draw.point((s1.points_thick[j].x+w,
|
||||
w-s1.points_thick[j].y), fill='white')
|
||||
w-s1.points_thick[j].y), fill='grey')
|
||||
|
||||
for i in range(0, len(p.arcs)):
|
||||
for j in range(len(p.arcs[i])):
|
||||
draw.point((p.arcs[i][j].x+w, w-p.arcs[i][j].y), fill='white')
|
||||
|
||||
|
||||
for i in range(1, len(p.segments)-1):
|
||||
for j in range(len(p.segments[i].segment())):
|
||||
draw.point((p.segments[i].points[j].x+w,
|
||||
w-p.segments[i].points[j].y), fill='white')
|
||||
|
||||
for i in range(1, len(p.centers)-1):
|
||||
draw.point((p.centers[i].x+w, w-p.centers[i].y), fill='red')
|
||||
draw.point((p.acrs_intersections[i][0].x+w,
|
||||
w-p.acrs_intersections[i][0].y), fill='blue')
|
||||
draw.point((p.acrs_intersections[i][1].x+w,
|
||||
w-p.acrs_intersections[i][1].y), fill='purple')
|
||||
draw.point((p.acrs_intersections[i][2].x+w,
|
||||
w-p.acrs_intersections[i][2].y), fill='blue')
|
||||
|
||||
|
||||
image.save('output_image.png')
|
||||
|
||||
# s = Segment2D(Point2D(-88, -12), Point2D(9, 75))
|
||||
# s.segment_thick(3, LINE_THICKNESS_MODE.MIDDLE)
|
||||
# print(s.points)
|
||||
|
||||
# s = Segment2D(Point2D(0, 0), Point2D(10, 10)).perpendicular(10)
|
||||
# print(s)
|
||||
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
from networks.geometry.Point2D import Point2D
|
||||
from math import cos, sin, pi
|
||||
from math import cos, pi, sin
|
||||
from typing import List
|
||||
|
||||
import numpy as np
|
||||
|
||||
from networks.geometry.Point2D import Point2D
|
||||
|
||||
|
||||
class Circle:
|
||||
def __init__(self, center: Point2D):
|
||||
self.center = center
|
||||
|
||||
self.radius = None
|
||||
self.points = []
|
||||
self.points: List[Point2D] = []
|
||||
|
||||
self.inner = None
|
||||
self.outer = None
|
||||
self.points_thick = []
|
||||
self.points_thick: List[Point2D] = []
|
||||
|
||||
self.spaced_radius = None
|
||||
self.spaced_points = []
|
||||
self.spaced_points: List[Point2D] = []
|
||||
|
||||
def __repr__(self):
|
||||
return f"Circle(center: {self.center}, radius: {self.radius}, spaced_radius: {self.spaced_radius}, inner: {self.inner}, outer: {self.outer})"
|
||||
@@ -43,6 +46,7 @@ class Circle:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return self.points
|
||||
|
||||
def circle_thick(self, inner: int, outer: int) -> List[Point2D]:
|
||||
"""Compute discrete value of a 2d-circle with thickness.
|
||||
@@ -114,16 +118,17 @@ class Circle:
|
||||
center = self.center
|
||||
|
||||
self.spaced_points = [
|
||||
Point2D(cos(2 * pi / number * i) * radius,
|
||||
sin(2 * pi / number * i) * radius)
|
||||
Point2D(round(cos(2 * pi / number * i) * radius),
|
||||
round(sin(2 * pi / number * i) * radius))
|
||||
for i in range(0, number + 1)
|
||||
]
|
||||
|
||||
for i in range(len(self.spaced_points)):
|
||||
self.spaced_points[i] = Point2D(
|
||||
current_point = Point2D(
|
||||
self.spaced_points[i].x + center.x,
|
||||
self.spaced_points[i].y + center.y
|
||||
).round()
|
||||
self.spaced_points[i] = current_point
|
||||
return self.spaced_points
|
||||
|
||||
def _x_line(self, x1, x2, y):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import numpy as np
|
||||
from typing import List
|
||||
from math import atan2, sqrt
|
||||
from typing import List, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
from Enums import ROTATION
|
||||
|
||||
|
||||
@@ -21,10 +23,26 @@ class Point2D:
|
||||
return self.x == other.x and self.y == other.y
|
||||
return False
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, np.ndarray) and other.shape == (2,):
|
||||
return Point2D(self.x + other[0], self.y + other[1])
|
||||
elif isinstance(other, Point2D):
|
||||
return Point2D(self.x + other.x, self.y + other.y)
|
||||
else:
|
||||
raise TypeError(f"Unsupported type for addition: {type(other)}")
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, np.ndarray) and other.shape == (2,):
|
||||
return Point2D(self.x - other[0], self.y - other[1])
|
||||
elif isinstance(other, Point2D):
|
||||
return Point2D(self.x - other.x, self.y - other.y)
|
||||
else:
|
||||
raise TypeError(f"Unsupported type for subtraction: {type(other)}")
|
||||
|
||||
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.
|
||||
From: https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
|
||||
|
||||
Args:
|
||||
xy0 (Type[Point2D]): Point of the triangle.
|
||||
@@ -190,12 +208,21 @@ class Point2D:
|
||||
return abs(x1 * y2 - x2 * y1) < 1e-12
|
||||
|
||||
@staticmethod
|
||||
def to_vectors(points: List["Point3D"]) -> List[np.array]:
|
||||
vectors = []
|
||||
for point in points:
|
||||
vectors.append(np.array(point.coordinates))
|
||||
|
||||
if (len(vectors) == 1):
|
||||
return vectors[0]
|
||||
else:
|
||||
def to_arrays(points: Union[List["Point2D"], "Point2D"]) -> Union[List[np.array], "Point2D"]:
|
||||
if isinstance(points, list):
|
||||
vectors = []
|
||||
for point in points:
|
||||
vectors.append(np.array(point.coordinates))
|
||||
return vectors
|
||||
else:
|
||||
return np.array(points.coordinates)
|
||||
|
||||
@staticmethod
|
||||
def from_arrays(vectors: Union[List[np.array], "Point2D"]) -> Union[List["Point2D"], "Point2D"]:
|
||||
if isinstance(vectors, list):
|
||||
points = []
|
||||
for vector in vectors:
|
||||
points.append(Point2D(vector[0], vector[1]))
|
||||
return points
|
||||
else:
|
||||
return Point2D(vectors[0], vectors[1])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from math import sqrt
|
||||
from typing import List
|
||||
from math import atan2, sqrt
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
@@ -80,3 +81,14 @@ class Point3D:
|
||||
return vectors[0]
|
||||
else:
|
||||
return vectors
|
||||
|
||||
@staticmethod
|
||||
def from_arrays(vectors: List[np.array]) -> List["Point3D"]:
|
||||
points = []
|
||||
for vector in vectors:
|
||||
points.append(Point3D(vector[0], vector[1], vector[2]))
|
||||
|
||||
if (len(points) == 1):
|
||||
return points[0]
|
||||
else:
|
||||
return points
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
from networks.geometry.Point2D import Point2D
|
||||
from math import inf, sqrt
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
from math import sqrt, inf
|
||||
import numpy as np
|
||||
|
||||
from networks.geometry.Circle import Circle
|
||||
from networks.geometry.Point2D import Point2D
|
||||
from networks.geometry.Segment2D import Segment2D
|
||||
|
||||
# from Enums import LINE_THICKNESS_MODE, LINE_OVERLAP
|
||||
|
||||
|
||||
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.
|
||||
@@ -18,7 +24,8 @@ class Polyline:
|
||||
|
||||
>>> Polyline((Point2D(0, 0), Point2D(0, 10), Point2D(50, 10), Point2D(20, 20)))
|
||||
"""
|
||||
self.points_array = Point2D.to_vectors(
|
||||
self.output_points = points
|
||||
self.points_array = Point2D.to_arrays(
|
||||
self._remove_collinear_points(points))
|
||||
self.length_polyline = len(self.points_array)
|
||||
|
||||
@@ -26,36 +33,46 @@ class Polyline:
|
||||
raise ValueError("The list must contain at least 4 elements.")
|
||||
|
||||
self.vectors = [None] * self.length_polyline # v
|
||||
self.lengths = [None] * (self.length_polyline - 1) # l
|
||||
self.lengths = [0] * (self.length_polyline - 1) # l
|
||||
self.unit_vectors = [None] * self.length_polyline # n
|
||||
self.tangente = [0] * self.length_polyline # f
|
||||
|
||||
# alpha, maximum radius factor
|
||||
self.alpha_radii = [None] * self.length_polyline
|
||||
self.alpha_radii = [0] * self.length_polyline
|
||||
|
||||
self.radii = [None] * self.length_polyline # r
|
||||
self.centers = [None] * self.length_polyline # c
|
||||
# Useful outputs. In order to not break indexation, each list has the same length, even if for n points, there is n-2 radius.
|
||||
# Lists will start and end with None.
|
||||
self.radii = [0] * self.length_polyline # r, list of points
|
||||
self.centers = [None] * self.length_polyline # c, list of points
|
||||
# list of tuple of points (first intersection, corresponding corner, last intersection)
|
||||
self.acrs_intersections = [None] * self.length_polyline
|
||||
self.arcs = [[]] * self.length_polyline # list of points
|
||||
# self.not_arcs = [[]] * self.length_polyline
|
||||
|
||||
# For n points, there is n-1 segments. Last element should stays None.
|
||||
self.segments = [None] * \
|
||||
self.length_polyline # list of segments
|
||||
|
||||
# Run procedure
|
||||
self._compute_requirements()
|
||||
self._compute_alpha_radii()
|
||||
|
||||
self._alpha_assign(0, self.length_polyline-1)
|
||||
|
||||
self.output_points = points
|
||||
self.get_radii()
|
||||
self.get_centers()
|
||||
self.get_arcs_intersections()
|
||||
self.get_arcs()
|
||||
self.get_segments()
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.alpha_radii)
|
||||
|
||||
def get_radii(self):
|
||||
def get_radii(self) -> List[Union[int]]:
|
||||
for i in range(1, self.length_polyline-1):
|
||||
self.radii[i] = round(self.alpha_radii[i] * self.tangente[i])
|
||||
return self.radii
|
||||
|
||||
def get_centers(self):
|
||||
if self.radii == [None] * self.length_polyline:
|
||||
raise ValueError("No radii found. Run get_radii before.")
|
||||
|
||||
def get_centers(self) -> List[Union[Point2D, None]]:
|
||||
for i in range(1, self.length_polyline-1):
|
||||
bisector = (self.unit_vectors[i] - self.unit_vectors[i-1]) / (
|
||||
np.linalg.norm(self.unit_vectors[i] - self.unit_vectors[i-1]))
|
||||
@@ -65,16 +82,68 @@ class Polyline:
|
||||
self.centers[i] = Point2D(array[0], array[1]).round()
|
||||
return self.centers
|
||||
|
||||
def get_arcs_intersections(self):
|
||||
def get_arcs_intersections(self) -> List[Tuple[Point2D]]:
|
||||
"""Get arcs intersections points.
|
||||
|
||||
First and last elements elements of the list should be None. For n points, there are n-1 segments, and n-2 angle.
|
||||
|
||||
Returns:
|
||||
list[tuple(Point2D)]: List of tuples composed - in order - of the first arc points, the corner points, the last arc points. The corresponding arc circle is inside this triangle.
|
||||
"""
|
||||
for i in range(1, self.length_polyline-1):
|
||||
point_1 = self.points_array[i] - \
|
||||
self.alpha_radii[i] * self.unit_vectors[i-1]
|
||||
point_2 = self.points_array[i] + \
|
||||
self.alpha_radii[i] * self.unit_vectors[i]
|
||||
self.acrs_intersections[i] = Point2D(
|
||||
point_1[0], point_1[1]).round(), Point2D(self.points_array[i][0], self.points_array[i][1]), Point2D(point_2[0], point_2[1]).round()
|
||||
point_1 = Point2D.from_arrays(self.points_array[i] -
|
||||
self.alpha_radii[i] * self.unit_vectors[i-1])
|
||||
point_2 = Point2D.from_arrays(self.points_array[i] +
|
||||
self.alpha_radii[i] * self.unit_vectors[i])
|
||||
self.acrs_intersections[i] = point_1.round(), Point2D.from_arrays(
|
||||
self.points_array[i]), point_2.round()
|
||||
return self.acrs_intersections
|
||||
|
||||
def get_arcs(self) -> List[Point2D]:
|
||||
for i in range(1, self.length_polyline-1):
|
||||
circle = Circle(self.centers[i])
|
||||
circle.circle(self.radii[i])
|
||||
for j in range(len(circle.points)):
|
||||
if circle.points[j].is_in_triangle(self.acrs_intersections[i][0], self.acrs_intersections[i][1], self.acrs_intersections[i][2]):
|
||||
self.arcs[i].append(circle.points[j])
|
||||
# for j in range(len(circle.points)):
|
||||
# if (circle.points[j] in Segment2D(self.acrs_intersections[i][0], self.acrs_intersections[i][1]).segment(LINE_OVERLAP.MINOR)):
|
||||
# self.not_arcs[i].append(circle.points[j])
|
||||
# print("hzeh")
|
||||
# if (circle.points[j] in Segment2D(self.acrs_intersections[i][1], self.acrs_intersections[i][2]).segment(LINE_OVERLAP.MINOR)):
|
||||
# self.not_arcs[i].append(circle.points[j])
|
||||
# print("hzeh")
|
||||
# if (circle.points[j] in Segment2D(self.acrs_intersections[i][2], self.acrs_intersections[i][0]).segment(LINE_OVERLAP.MINOR)):
|
||||
# self.not_arcs[i].append(circle.points[j])
|
||||
# print("hzeh")
|
||||
return self.arcs
|
||||
|
||||
def get_segments(self) -> List[Segment2D]:
|
||||
"""Get the segments between the circle arcs and at the start and end.
|
||||
|
||||
Last list element should be None, and last usable index is -2 or self.length_polyline - 2. For n points, there are n-1 segments.
|
||||
|
||||
Returns:
|
||||
list[Segment2D]: List of segments in order.
|
||||
"""
|
||||
# Get first segment.
|
||||
# segments index is 0, corresponding to the first points_array to the first point ([0]) of the first arc (acrs_intersections[1]).
|
||||
# First arc index is 1 because index 0 is None due to fix list lenght. Is it a good choice?
|
||||
self.segments[1] = Segment2D(Point2D.from_arrays(
|
||||
self.points_array[0]), self.acrs_intersections[1][0])
|
||||
|
||||
# Get segments between arcs
|
||||
for i in range(2, self.length_polyline - 2):
|
||||
self.segments[i] = Segment2D(Point2D(self.acrs_intersections[i][0].x, self.acrs_intersections[i][0].y), Point2D(
|
||||
self.acrs_intersections[i-1][-1].x, self.acrs_intersections[i-1][-1].y))
|
||||
|
||||
# Get last segment. Index is -2 because last index -1 should be None due to the same list lenght.
|
||||
# For n points, there are n-1 segments.
|
||||
self.segments[-2] = Segment2D(Point2D.from_arrays(
|
||||
self.points_array[-1]), self.acrs_intersections[-2][2])
|
||||
|
||||
return self.segments
|
||||
|
||||
def _alpha_assign(self, start_index: int, end_index: int):
|
||||
"""
|
||||
The alpha-assign procedure assigning radii based on a polyline.
|
||||
@@ -101,8 +170,8 @@ class Polyline:
|
||||
minimum_radius, minimum_index = current_radius, i
|
||||
alpha_low, alpha_high = alpha_a, alpha_b
|
||||
|
||||
alpha_a = min(self.lengths[end_index-2],
|
||||
self.lengths[end_index-1]-self.alpha_radii[end_index])
|
||||
alpha_a = min(
|
||||
self.lengths[end_index-2], self.lengths[end_index-1]-self.alpha_radii[end_index])
|
||||
|
||||
current_radius = max(self.tangente[end_index-1]*alpha_a, self.tangente[end_index]
|
||||
* self.alpha_radii[end_index]) # Radius at final segment
|
||||
@@ -123,9 +192,8 @@ class Polyline:
|
||||
"""
|
||||
Returns the radius that balances the radii on either end segement i.
|
||||
"""
|
||||
|
||||
alpha_a = min(self.lengths[i-1], (self.lengths[i]*self.tangente[i+1]) /
|
||||
(self.tangente[i] + self.tangente[i+1]))
|
||||
alpha_a = min(self.lengths[i-1], (self.lengths[i] *
|
||||
self.tangente[i+1])/(self.tangente[i] + self.tangente[i+1]))
|
||||
alpha_b = min(self.lengths[i+1], self.lengths[i]-alpha_a)
|
||||
return alpha_a, alpha_b, min(self.tangente[i]*alpha_a, self.tangente[i+1]*alpha_b)
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
from typing import List
|
||||
from typing import List, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
from Enums import LINE_OVERLAP, LINE_THICKNESS_MODE
|
||||
from networks.geometry.Point2D import Point2D
|
||||
from math import sqrt
|
||||
|
||||
|
||||
class Segment2D:
|
||||
def __init__(self, start: Point2D, end: Point2D):
|
||||
self.start = start
|
||||
self.end = end
|
||||
self.points = []
|
||||
self.points_thick = []
|
||||
self.points: List[Point2D] = []
|
||||
self.points_thick: List[Point2D] = []
|
||||
self.thickness = None
|
||||
|
||||
def __repr__(self):
|
||||
return str(self.points)
|
||||
return str(f"Segment2D(start: {self.start}, end: {self.end}, points: {self.points})")
|
||||
|
||||
def segment(self, start: Point2D = None, end: Point2D = None, overlap: LINE_OVERLAP = LINE_OVERLAP.NONE, _is_computing_thickness: bool = False) -> List[Point2D]:
|
||||
def segment(self, start: Point2D = None, end: Point2D = None, overlap: LINE_OVERLAP = LINE_OVERLAP.NONE, _is_computing_thickness: bool = False) -> Union[List[Point2D], None]:
|
||||
"""Modified Bresenham draw (line) with optional overlap.
|
||||
|
||||
From: https://github.com/ArminJo/Arduino-BlueDisplay/blob/master/src/LocalGUI/ThickLine.hpp
|
||||
@@ -29,7 +31,7 @@ class Segment2D:
|
||||
>>> Segment2D(Point2D(0, 0), Point2D(10, 15))
|
||||
"""
|
||||
|
||||
if start == None or end == None:
|
||||
if start is None or end is None:
|
||||
start = self.start.copy()
|
||||
end = self.end.copy()
|
||||
else:
|
||||
@@ -90,6 +92,7 @@ class Segment2D:
|
||||
|
||||
if not _is_computing_thickness:
|
||||
return self.points
|
||||
return None
|
||||
|
||||
def segment_thick(self, thickness: int, thickness_mode: LINE_THICKNESS_MODE) -> List[Point2D]:
|
||||
"""Bresenham with thickness.
|
||||
@@ -208,7 +211,7 @@ class Segment2D:
|
||||
self.segment(
|
||||
start, end, overlap=overlap, _is_computing_thickness=True)
|
||||
|
||||
return self.points
|
||||
return self.points_thick
|
||||
|
||||
def perpendicular(self, distance: int) -> List[Point2D]:
|
||||
"""Compute perpendicular points from both side of the segment placed at start level.
|
||||
|
||||
BIN
output_image.png
BIN
output_image.png
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 1.7 KiB |
Reference in New Issue
Block a user