Redo curved_corner_by_distance

This commit is contained in:
2024-06-04 18:47:22 +02:00
parent 6398287116
commit 0eb39fc4a4
3 changed files with 156 additions and 111 deletions

109
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 from networks.geometry.point_tools import curved_corner_by_curvature, curved_corner_by_distance
editor = Editor(buffering=True) editor = Editor(buffering=True)
@@ -150,48 +150,85 @@ block_list = ["blue_concrete", "red_concrete", "green_concrete",
# --- # ---
y = 100 # y = 100
# x = -200
r1 = Road.Road((-1380, 75, 406), "None") # r1 = Road.Road((-1380+x, 75, 406), "None")
r2 = Road.Road((-1365, 75, 468), "None") # r2 = Road.Road((-1365+x, 75, 468), "None")
r3 = Road.Road((-1411, 75, 501), "None") # r3 = Road.Road((-1411+x, 75, 501), "None")
r4 = Road.Road((-1451, 75, 449), "None") # r4 = Road.Road((-1451+x, 75, 449), "None")
r5 = Road.Road((-1432, 75, 423), "None") # r5 = Road.Road((-1432+x, 75, 423), "None")
i = Intersection.Intersection( # i = Intersection.Intersection(
(-1411, 75, 461), [(-1392, 75, 427), (-1385, 75, 465), (-1411, 75, 487), (-1435, 75, 454), (-1426, 75, 435)], [r1, r2, r3, r4, r5]) # (-1411+x, 75, 461), [(-1392+x, 75, 427), (-1385+x, 75, 465), (-1411+x, 75, 487), (-1435+x, 75, 454), (-1426+x, 75, 435)], [r1, r2, r3, r4, r5])
i.compute_curved_corner() # i.compute_curved_corner()
for j in range(len(i.orthogonal_delimitations)): # for j in range(len(i.orthogonal_delimitations)):
coordinates = segment_tools.discrete_segment( # coordinates = segment_tools.discrete_segment(
i.orthogonal_delimitations[j][0][0], i.orthogonal_delimitations[j][0][1]) # i.orthogonal_delimitations[j][0][0], i.orthogonal_delimitations[j][0][1])
for coordinate in coordinates: # for coordinate in coordinates:
editor.placeBlock(coordinate, Block("purple_concrete")) # editor.placeBlock(coordinate, Block("purple_concrete"))
coordinates = segment_tools.discrete_segment( # coordinates = segment_tools.discrete_segment(
i.orthogonal_delimitations[j][1][0], i.orthogonal_delimitations[j][1][1]) # i.orthogonal_delimitations[j][1][0], i.orthogonal_delimitations[j][1][1])
for coordinate in coordinates: # for coordinate in coordinates:
editor.placeBlock(coordinate, Block("pink_concrete")) # editor.placeBlock(coordinate, Block("pink_concrete"))
coordinates = segment_tools.discrete_segment( # coordinates = segment_tools.discrete_segment(
i.parallel_delimitations[j][0][0], i.parallel_delimitations[j][0][1]) # i.parallel_delimitations[j][0][0], i.parallel_delimitations[j][0][1])
for coordinate in coordinates: # for coordinate in coordinates:
editor.placeBlock(coordinate, Block("orange_concrete")) # editor.placeBlock(coordinate, Block("orange_concrete"))
coordinates = segment_tools.discrete_segment( # coordinates = segment_tools.discrete_segment(
i.parallel_delimitations[j][1][0], i.parallel_delimitations[j][1][1]) # i.parallel_delimitations[j][1][0], i.parallel_delimitations[j][1][1])
for coordinate in coordinates: # for coordinate in coordinates:
editor.placeBlock(coordinate, Block("yellow_concrete")) # editor.placeBlock(coordinate, Block("yellow_concrete"))
for coordinate in i.intersections: # for coordinate in i.intersections:
if coordinate != None: # if coordinate != None:
editor.placeBlock(coordinate, Block("black_concrete")) # editor.placeBlock(coordinate, Block("black_concrete"))
for k in range(len(i.intersections_curved)): # for k in range(len(i.intersections_curved)):
for coordinate in i.intersections_curved[k][0]: # for coordinate in i.intersections_curved[k][0]:
if coordinate != None: # if coordinate != None:
if k >= 0: # if k >= 0:
editor.placeBlock( # editor.placeBlock(
(coordinate[0], 75, coordinate[1]), Block("brown_concrete")) # (coordinate[0], 75, coordinate[1]), Block("gray_concrete"))
# editor.placeBlock(
# (i.intersections_curved[k][1][0], 76, i.intersections_curved[k][1][1]), Block("black_concrete"))
# coordinates = segment_tools.discrete_segment(
# i.intersections_curved[k][-1][0], i.intersections_curved[k][-1][1])
# for coordinate in coordinates:
# editor.placeBlock(coordinate, Block("lime_concrete"))
# coordinates = segment_tools.discrete_segment(
# i.intersections_curved[k][-2][0], i.intersections_curved[k][-2][1])
# for coordinate in coordinates:
# editor.placeBlock(coordinate, Block("green_concrete"))
# ---
intersection = (-1510, 94, 455)
xyz0 = (-1545, 90, 537)
xyz1 = (-1443, 160, 452)
circle = curved_corner_by_distance(
intersection, xyz0, xyz1, 50, 0)
line0 = segment_tools.discrete_segment(intersection, xyz0)
line1 = segment_tools.discrete_segment(intersection, xyz1)
for coordinate in circle[0]:
editor.placeBlock(
coordinate, Block("cyan_concrete"))
for coordinate in line0:
editor.placeBlock(
coordinate, Block("blue_concrete"))
for coordinate in line1:
editor.placeBlock(
coordinate, Block("red_concrete"))

View File

@@ -5,7 +5,7 @@ from networks.geometry.segment_tools import discrete_segment, middle_point, para
def circle(center, radius): def circle(center, radius):
""" """
Can be used for circle or disc. Can be used for circle or disc. Works in 2d but supports 3d.
Args: Args:
xyC (tuple): Coordinates of the center. xyC (tuple): Coordinates of the center.
@@ -17,9 +17,9 @@ def circle(center, radius):
for a disc, positive values for a hole. for a disc, positive values for a hole.
""" """
area = ( area = (
(round(center[0]) - round(radius), round(center[1]) - round(radius)), (round(center[0]) - round(radius), round(center[-1]) - round(radius)),
(round(center[0]) + round(radius) + 1, (round(center[0]) + round(radius) + 1,
round(center[1]) + round(radius) + 1), round(center[-1]) + round(radius) + 1),
) )
circle = {} circle = {}
@@ -33,6 +33,7 @@ def circle(center, radius):
def is_in_triangle(point, xy0, xy1, xy2): def is_in_triangle(point, xy0, xy1, xy2):
# Works in 2d but supports 3d.
# 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]
@@ -52,6 +53,7 @@ def is_in_triangle(point, xy0, xy1, xy2):
def distance(xy1, xy2): # TODO : Can be better. 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) return sqrt((xy2[0] - xy1[0]) ** 2 + (xy2[-1] - xy1[-1]) ** 2)
@@ -80,6 +82,7 @@ def get_angle(xy0, xy1, xy2):
def circle_points(center_point, radius, number=100): 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 # https://stackoverflow.com/questions/8487893/generate-all-the-points-on-the-circumference-of-a-circle
points = [ points = [
(cos(2 * pi / number * x) * radius, sin(2 * pi / number * x) * radius) (cos(2 * pi / number * x) * radius, sin(2 * pi / number * x) * radius)
@@ -89,7 +92,7 @@ def circle_points(center_point, radius, number=100):
for i in range(len(points)): for i in range(len(points)):
points[i] = ( points[i] = (
points[i][0] + center_point[0], points[i][0] + center_point[0],
points[i][1] + center_point[1], points[i][-1] + center_point[-1],
) )
return points return points
@@ -325,91 +328,36 @@ def perpendicular(distance, xy1, xy2):
y3 = y1 - (distance / 2) * dx y3 = y1 - (distance / 2) * dx
x4 = x1 - (distance / 2) * dy x4 = x1 - (distance / 2) * dy
y4 = y1 + (distance / 2) * dx y4 = y1 + (distance / 2) * dx
return ((round(x3), round(y3)), (round(x4), round(y4))) return (x3, y3), (x4, y4)
def curved_corner(
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.
if curvature != None:
center = segments_intersection(parallel(
(xyz0, intersection), curvature), parallel((xyz1, intersection), -curvature))
# If distance is set, compute where the arc should merge on the two intersecting lines.
elif distance != None:
start_curve_point = circle_segment_intersection(
intersection, distance, xy0[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, distance, xy1[0], intersection, full_line
)[0]
end_curve_point = (
round(end_curve_point[0]), round(end_curve_point[-1]))
# Then compute the center as the intersection between perpendicular segment at the points computed before.
# 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])
curvature = round(distance(start_curve_point, center))
if output_only_points:
circle_data = circle_points(
center, curvature, 32
)
else:
circle_data = circle(center, curvature)
# Find the correct points on the circle.
curved_corner_points_temporary = [start_curve_point]
for point in circle_data:
if is_in_triangle(point, intersection, start_curve_point, end_curve_point):
curved_corner_points_temporary.append(
(round(point[0]), round(point[1])))
if output_only_points:
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
def curved_corner_by_distance( def curved_corner_by_distance(
intersection, xyz0, xyz1, distance_from_intersection, resolution, full_line=True intersection, xyz0, xyz1, distance_from_intersection, resolution, full_line=True
): ):
# Comute the merging point on the first line # Compute the merging point on the first line
start_curve_point = circle_segment_intersection( start_curve_point = circle_segment_intersection(
intersection, distance_from_intersection, xyz0, intersection, full_line intersection, distance_from_intersection, xyz0, intersection, full_line
)[0] )[0]
start_curve_point = ( start_curve_point = (
round(start_curve_point[0]), round(start_curve_point[-1])) round(start_curve_point[0]), nearest(discrete_segment(intersection, xyz0), (start_curve_point[0], 100, start_curve_point[-1]))[1], round(start_curve_point[-1]))
# Comute the merging point on the second line # Compute the merging point on the second line
end_curve_point = circle_segment_intersection( end_curve_point = circle_segment_intersection(
intersection, distance_from_intersection, xyz1, intersection, full_line intersection, distance_from_intersection, xyz1, intersection, full_line
)[0] )[0]
end_curve_point = ( end_curve_point = (
round(end_curve_point[0]), round(end_curve_point[-1])) round(end_curve_point[0]), nearest(discrete_segment(intersection, xyz1), (end_curve_point[0], 100, end_curve_point[-1]))[1], round(end_curve_point[-1]))
# Compute the intersection between perpendicular lines at the merging points # Compute the intersection between perpendicular lines at the merging points
# Higher value for better precision # Higher value for better precision
perpendicular0 = perpendicular( perpendicular0 = perpendicular(10e3, start_curve_point, intersection)[0]
10e3, start_curve_point, intersection)[0] perpendicular0 = (round(perpendicular0[0]), round(perpendicular0[-1]))
perpendicular1 = perpendicular(10e3, end_curve_point, intersection)[-1] perpendicular1 = perpendicular(10e3, end_curve_point, intersection)[1]
perpendicular1 = (round(perpendicular1[0]), round(perpendicular1[-1]))
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]), middle_point(xyz0, xyz1)[1], round(center[-1])
# Compute the curvature for indications # Compute the curvature for indications
curvature = round(distance(start_curve_point, center)) curvature = round(distance(start_curve_point, center))
@@ -420,19 +368,76 @@ def curved_corner_by_distance(
center, curvature, resolution center, curvature, resolution
) )
else: else:
print(center, curvature, circle(center, curvature))
circle_data = circle(center, curvature)[0] circle_data = circle(center, curvature)[0]
# Find the correct points 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:
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): if is_in_triangle(point, intersection, start_curve_point, end_curve_point):
curved_corner_points_temporary.append( curved_corner_points_temporary.append(point)
(round(point[0]), round(point[1])))
curved_corner_points_temporary.append(end_curve_point) curved_corner_points_temporary.append(end_curve_point)
# 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)
for i in range(len(curve_corner_points)):
y = min(start_curve_point[1], end_curve_point[1]) + \
(i * abs(start_curve_point[1] -
end_curve_point[1])/len(curve_corner_points))
curve_corner_points[i] = (round(curve_corner_points[i][0]), round(
y), round(curve_corner_points[i][-1]))
return curve_corner_points, center, curvature return curve_corner_points, center, curvature
def curved_corner_by_curvature(
intersection, xyz0, xyz1, curvature_radius, resolution, full_line=True
):
print(xyz0, intersection, xyz1)
# Get the center.
center = segments_intersection(parallel(
(xyz0, intersection), -curvature_radius), parallel((xyz1, intersection), curvature_radius))
center = round(center[0]), round(center[-1])
# Return a full discrete circle or only some points of it.
if resolution != 0:
circle_data = circle_points(
center, curvature_radius, resolution
)
else:
circle_data = circle(center, curvature_radius)[0]
# Compute the merging point on the first line.
print(center, curvature_radius, xyz0, intersection)
start_curve_point = circle_segment_intersection(
center, curvature_radius, xyz0, intersection, full_line
)[0]
start_curve_point = (
round(start_curve_point[0]), round(start_curve_point[-1]))
# Compute the merging point on the second line.
end_curve_point = circle_segment_intersection(
center, curvature_radius, xyz1, intersection, full_line
)[0]
end_curve_point = (
round(end_curve_point[0]), round(end_curve_point[-1]))
# 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)
# Distance from intersection just for information
distance_from_intersection = round(distance(start_curve_point, center))
return curve_corner_points, center, distance_from_intersection, parallel(
(xyz0, intersection), -curvature_radius), parallel((xyz1, intersection), curvature_radius)

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_by_distance from networks.geometry.point_tools import sort_by_clockwise, segments_intersection, curved_corner_by_distance, curved_corner_by_curvature
from networks.roads import Road from networks.roads import Road
@@ -37,6 +37,9 @@ class Intersection:
next_parallel[0][0], next_parallel[0][-1]), (next_parallel[1][0], next_parallel[1][-1])), full_line=False) next_parallel[0][0], next_parallel[0][-1]), (next_parallel[1][0], next_parallel[1][-1])), full_line=False)
intersection = ( intersection = (
round(intersection2d[0]), 100, round(intersection2d[1])) round(intersection2d[0]), 75, round(intersection2d[1]))
self.intersections_curved.append(curved_corner_by_distance( self.intersections_curved.append(curved_corner_by_distance(
intersection, current_parallel[0], next_parallel[0], 10, 0, full_line=True)) intersection, current_parallel[0], next_parallel[0], 10, 0, full_line=True))
# print("\n\n\nBY DISTANCE\n\n\n")
# self.intersections_curved.append(curved_corner_by_distance(
# intersection, current_parallel[0], next_parallel[0], 10, 0, full_line=True))