Refactor curved_corner_by_distance

This commit is contained in:
2024-06-04 15:59:39 +02:00
parent bfe6851a6c
commit 6398287116
4 changed files with 103 additions and 75 deletions

14
main.py
View File

@@ -12,7 +12,7 @@ import random
from networks.roads import Road as Road from networks.roads import Road as Road
from networks.roads.intersections import Intersection as Intersection from networks.roads.intersections import Intersection as Intersection
from networks.geometry.point_tools import curved_corner_intersection from networks.geometry.point_tools import curved_corner
editor = Editor(buffering=True) editor = Editor(buffering=True)
@@ -111,12 +111,12 @@ block_list = ["blue_concrete", "red_concrete", "green_concrete",
# print(l.get_surface()) # print(l.get_surface())
circle = curved_corner_intersection( # circle = curved_corner(
((-1365, 520), (-1326, 523)), ((-1344, 496), (-1336, 535)), 10, angle_adaptation=False, output_only_points=False) # ((-1365, 520), (-1326, 523)), ((-1344, 496), (-1336, 535)), 10, angle_adaptation=False, output_only_points=False)
for coordinate in circle[0]: # for coordinate in circle[0]:
editor.placeBlock( # editor.placeBlock(
(round(coordinate[0]), 125, round(coordinate[1])), Block("green_concrete")) # (round(coordinate[0]), 125, round(coordinate[1])), Block("green_concrete"))
# --- # ---
@@ -194,4 +194,4 @@ for k in range(len(i.intersections_curved)):
if coordinate != None: if coordinate != None:
if k >= 0: if k >= 0:
editor.placeBlock( editor.placeBlock(
(coordinate[0], 75, coordinate[1]), Block("cyan_concrete")) (coordinate[0], 75, coordinate[1]), Block("brown_concrete"))

View File

@@ -1,6 +1,6 @@
from math import sqrt, cos, pi, sin from math import sqrt, cos, pi, sin
import numpy as np import numpy as np
from networks.geometry.segment_tools import discrete_segment, middle_point from networks.geometry.segment_tools import discrete_segment, middle_point, parallel
def circle(center, radius): def circle(center, radius):
@@ -35,11 +35,11 @@ def circle(center, radius):
def is_in_triangle(point, xy0, xy1, xy2): def is_in_triangle(point, xy0, xy1, xy2):
# 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. # 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.
dX = point[0] - xy0[0] dX = point[0] - xy0[0]
dY = point[1] - xy0[1] dY = point[-1] - xy0[-1]
dX20 = xy2[0] - xy0[0] dX20 = xy2[0] - xy0[0]
dY20 = xy2[1] - xy0[1] dY20 = xy2[-1] - xy0[-1]
dX10 = xy1[0] - xy0[0] dX10 = xy1[0] - xy0[0]
dY10 = xy1[1] - xy0[1] dY10 = xy1[-1] - xy0[-1]
s_p = (dY20 * dX) - (dX20 * dY) s_p = (dY20 * dX) - (dX20 * dY)
t_p = (dX10 * dY) - (dY10 * dX) t_p = (dX10 * dY) - (dY10 * dX)
@@ -328,77 +328,48 @@ def perpendicular(distance, xy1, xy2):
return ((round(x3), round(y3)), (round(x4), round(y4))) return ((round(x3), round(y3)), (round(x4), round(y4)))
def curved_corner_intersection( def curved_corner(
line0, line1, start_distance, angle_adaptation=False, full_line=True, center=(), output_only_points=True intersection, xyz0, xyz1, distance, curvature, full_line=True, output_only_points=True
): ):
""" # If curvature radius is set, compute the center of the circle as the intersection between the two lines, offseted by the curvature radius.
Create points between the two lines to smooth the intersection. if curvature != None:
center = segments_intersection(parallel(
(xyz0, intersection), curvature), parallel((xyz1, intersection), -curvature))
Args: # If distance is set, compute where the arc should merge on the two intersecting lines.
line0 (tuple): Tuple of tuple. Line coordinates. Order matters. elif distance != None:
line1 (tuple): Tuple of tuple. Line coordinates. Order matters. start_curve_point = circle_segment_intersection(
start_distance (int): distance from the intersection where the intersection, distance, xy0[0], intersection, full_line
curve should starts. )[0]
angleAdaptation (bool, optional): True will adapt the start_curve_point = (
start_distance depending of the angle between the two lines. round(start_curve_point[0]), round(start_curve_point[-1]))
False will force the distance to be start_distance. Defaults to
False.
Returns: end_curve_point = circle_segment_intersection(
[list]: List of tuple of coordinates (2d) that forms the curve. intersection, distance, xy1[0], intersection, full_line
Starts on the line and end on the other line. )[0]
end_curve_point = (
round(end_curve_point[0]), round(end_curve_point[-1]))
>>> curved_corner_intersection(((0, 0), (50, 20)), ((-5, 50), (25, -5)), 10) # Then compute the center as the intersection between perpendicular segment at the points computed before.
""" # Higher value for better precision
print("\nInput:") perpendicular0 = perpendicular(
print(line0, line1) 10e3, start_curve_point, intersection)[0]
intersection = segments_intersection(line0, line1, full_line) perpendicular1 = perpendicular(10e3, end_curve_point, intersection)[-1]
if intersection == None:
return None
# Define automatically the distance from the intersection, where the curve
# starts.
if angle_adaptation:
angle = get_angle(
(line0[0][0], line0[0][-1]),
intersection,
(line1[0][0], line1[0][-1]),
)
# Set here the radius of the circle for a square angle.
start_distance = start_distance * abs(1 / (angle / 90))
start_curve_point = circle_segment_intersection(
intersection, start_distance, line0[0], intersection, full_line
)[0]
start_curve_point = (
round(start_curve_point[0]), round(start_curve_point[-1]))
end_curve_point = circle_segment_intersection(
intersection, start_distance, line1[0], intersection, full_line
)[0]
end_curve_point = (round(end_curve_point[0]), round(end_curve_point[-1]))
# Higher value for better precision
perpendicular0 = perpendicular(10e3, start_curve_point, intersection)[0]
perpendicular1 = perpendicular(10e3, end_curve_point, intersection)[-1]
if center == ():
center = segments_intersection( center = segments_intersection(
(perpendicular0, start_curve_point), (perpendicular1, end_curve_point) (perpendicular0, start_curve_point), (perpendicular1, end_curve_point))
)
center = round(center[0]), round(center[-1]) center = round(center[0]), round(center[-1])
# Distance with startCurvePoint and endCurvePoint from the center are the curvature = round(distance(start_curve_point, center))
# same.
radius = round(distance(start_curve_point, center))
if output_only_points: if output_only_points:
circle_data = circle_points( circle_data = circle_points(
center, radius, 32 center, curvature, 32
) # n=round((2 * pi * radius) / 32) )
else: else:
circle_data = circle(center, radius)[0] circle_data = circle(center, curvature)
# Find the correct point on the circle. # Find the correct points on the circle.
curved_corner_points_temporary = [start_curve_point] curved_corner_points_temporary = [start_curve_point]
for point in circle_data: for point in circle_data:
if is_in_triangle(point, intersection, start_curve_point, end_curve_point): if is_in_triangle(point, intersection, start_curve_point, end_curve_point):
@@ -410,4 +381,58 @@ def curved_corner_intersection(
# Be sure that all the points are in correct order. # Be sure that all the points are in correct order.
curve_corner_points = optimized_path( curve_corner_points = optimized_path(
curved_corner_points_temporary, start_curve_point) curved_corner_points_temporary, start_curve_point)
return curve_corner_points, center, radius return curve_corner_points, center, curvature
def curved_corner_by_distance(
intersection, xyz0, xyz1, distance_from_intersection, resolution, full_line=True
):
# Comute the merging point on the first line
start_curve_point = circle_segment_intersection(
intersection, distance_from_intersection, xyz0, intersection, full_line
)[0]
start_curve_point = (
round(start_curve_point[0]), round(start_curve_point[-1]))
# Comute the merging point on the second line
end_curve_point = circle_segment_intersection(
intersection, distance_from_intersection, xyz1, intersection, full_line
)[0]
end_curve_point = (
round(end_curve_point[0]), round(end_curve_point[-1]))
# Compute the intersection between perpendicular lines at the merging points
# Higher value for better precision
perpendicular0 = perpendicular(
10e3, start_curve_point, intersection)[0]
perpendicular1 = perpendicular(10e3, end_curve_point, intersection)[-1]
center = segments_intersection(
(perpendicular0, start_curve_point), (perpendicular1, end_curve_point))
center = round(center[0]), round(center[-1])
# Compute the curvature for indications
curvature = round(distance(start_curve_point, center))
# Return a full discrete circle or only some points of it
if resolution != 0:
circle_data = circle_points(
center, curvature, resolution
)
else:
circle_data = circle(center, curvature)[0]
# Find the correct points on the circle.
curved_corner_points_temporary = [start_curve_point]
for point in circle_data:
print(point, intersection, start_curve_point, end_curve_point, is_in_triangle(
point, intersection, start_curve_point, end_curve_point))
if is_in_triangle(point, intersection, start_curve_point, end_curve_point):
curved_corner_points_temporary.append(
(round(point[0]), round(point[1])))
curved_corner_points_temporary.append(end_curve_point)
# Be sure that all the points are in correct order.
curve_corner_points = optimized_path(
curved_corner_points_temporary, start_curve_point)
return curve_corner_points, center, curvature

View File

@@ -50,8 +50,6 @@ def orthogonal(origin, point, distance, normal=np.array([0, 1, 0])):
orthogonal = np.cross(normalized_vector, normalized_normal) orthogonal = np.cross(normalized_vector, normalized_normal)
if np.array_equal(orthogonal, np.zeros((3,))): if np.array_equal(orthogonal, np.zeros((3,))):
print(normalized_vector, normalized_normal, orthogonal, normal)
print(origin, point, distance)
raise ValueError("The input vectors are not linearly independent.") raise ValueError("The input vectors are not linearly independent.")
orthogonal = np.add(np.multiply(orthogonal, distance), origin).astype(int) orthogonal = np.add(np.multiply(orthogonal, distance), origin).astype(int)

View File

@@ -1,5 +1,5 @@
from networks.geometry.segment_tools import parallel, orthogonal from networks.geometry.segment_tools import parallel, orthogonal
from networks.geometry.point_tools import sort_by_clockwise, segments_intersection, curved_corner_intersection from networks.geometry.point_tools import sort_by_clockwise, segments_intersection, curved_corner_by_distance
from networks.roads import Road from networks.roads import Road
@@ -33,5 +33,10 @@ class Intersection:
current_parallel = tuple(self.parallel_delimitations[j][1][0]), tuple( current_parallel = tuple(self.parallel_delimitations[j][1][0]), tuple(
self.parallel_delimitations[j][1][1]) self.parallel_delimitations[j][1][1])
self.intersections_curved.append(curved_corner_intersection( intersection2d = segments_intersection(((current_parallel[0][0], current_parallel[0][-1]), (current_parallel[1][0], current_parallel[1][-1])), ((
((current_parallel[0][0], current_parallel[0][-1]), (current_parallel[1][0], current_parallel[1][-1])), ((next_parallel[0][0], next_parallel[0][-1]), (next_parallel[1][0], next_parallel[1][-1])), 10, angle_adaptation=True, output_only_points=False)) next_parallel[0][0], next_parallel[0][-1]), (next_parallel[1][0], next_parallel[1][-1])), full_line=False)
intersection = (
round(intersection2d[0]), 100, round(intersection2d[1]))
self.intersections_curved.append(curved_corner_by_distance(
intersection, current_parallel[0], next_parallel[0], 10, 0, full_line=True))