Fix naming convention

This commit is contained in:
2024-05-27 20:43:49 +02:00
parent 9bece74ffd
commit db3a8b24c1
7 changed files with 83 additions and 147 deletions

18
main.py
View File

@@ -1,5 +1,5 @@
import networks.lines.Line as Line import networks.roads.lines.Line as Line
import networks.lanes.Lane as Lane import networks.roads.lanes.Lane as Lane
from gdpc import Editor, Block, geometry from gdpc import Editor, Block, geometry
import networks.geometry.curve as curve import networks.geometry.curve as curve
import networks.geometry.CurveSurface as CurveSurface import networks.geometry.CurveSurface as CurveSurface
@@ -9,7 +9,7 @@ import json
from buildings.Building import Building from buildings.Building import Building
import random import random
from networks.geometry.point import curveCornerIntersectionLine, curveCornerIntersectionPoints from networks.geometry.point import curved_corner_intersection
editor = Editor(buffering=True) editor = Editor(buffering=True)
@@ -107,11 +107,11 @@ block_list = ["blue_concrete", "red_concrete", "green_concrete",
# print(l.get_surface()) # print(l.get_surface())
circle = curveCornerIntersectionLine( circle = curved_corner_intersection(
((-1313, 392), (-1378, 415)), ((-1371, 348), (-1341, 439)), 30, angleAdaptation=True) ((-1313, 392), (-1378, 415)), ((-1371, 348), (-1341, 439)), 30, angle_adaptation=True, output_only_points=False)
print(circle[0]) print(circle)
for coordinate in circle[0]: # for coordinate in circle[0]:
editor.placeBlock( # editor.placeBlock(
(round(coordinate[0]), 100, round(coordinate[1])), Block("green_concrete")) # (round(coordinate[0]), 100, round(coordinate[1])), Block("green_concrete"))

View File

@@ -2,7 +2,7 @@ from math import sqrt, cos, pi, sin
import numpy as np import numpy as np
def circle(xyC, r): def circle(center, radius):
""" """
Can be used for circle or disc. Can be used for circle or disc.
@@ -16,21 +16,22 @@ def circle(xyC, r):
for a disc, positive values for a hole. for a disc, positive values for a hole.
""" """
area = ( area = (
(round(xyC[0]) - round(r), round(xyC[1]) - round(r)), (round(center[0]) - round(radius), round(center[1]) - round(radius)),
(round(xyC[0]) + round(r) + 1, round(xyC[1]) + round(r) + 1), (round(center[0]) + round(radius) + 1,
round(center[1]) + round(radius) + 1),
) )
circle = {} circle = {}
for x in range(area[0][0], area[1][0]): for x in range(area[0][0], area[1][0]):
for y in range(area[0][1], area[1][1]): for y in range(area[0][1], area[1][1]):
d = round(distance2D((x, y), (xyC))) - r d = round(distance((x, y), (center))) - radius
if circle.get(d) == None: if circle.get(d) == None:
circle[d] = [] circle[d] = []
circle[d].append((x, y)) circle[d].append((x, y))
return circle return circle
def InTriangle(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]
@@ -49,11 +50,11 @@ def InTriangle(point, xy0, xy1, xy2):
return (s_p <= 0) and (t_p <= 0) and (s_p + t_p) >= D return (s_p <= 0) and (t_p <= 0) and (s_p + t_p) >= D
def distance2D(A, B): # TODO : Can be better. def distance(xy1, xy2): # TODO : Can be better.
return sqrt((B[0] - A[0]) ** 2 + (B[1] - A[1]) ** 2) return sqrt((xy2[0] - xy1[0]) ** 2 + (xy2[1] - xy1[1]) ** 2)
def getAngle(xy0, xy1, xy2): def get_angle(xy0, xy1, xy2):
""" """
Compute angle (in degrees) for xy0, xy1, xy2 corner. Compute angle (in degrees) for xy0, xy1, xy2 corner.
@@ -77,7 +78,7 @@ def getAngle(xy0, xy1, xy2):
return np.degrees(angle) return np.degrees(angle)
def circlePoints(center_point, radius, number=100): def circle_points(center_point, radius, number=100):
# 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)
@@ -93,7 +94,7 @@ def circlePoints(center_point, radius, number=100):
return points return points
def optimizedPath(points, start=None): def optimized_path(points, start=None):
# https://stackoverflow.com/questions/45829155/sort-points-in-order-to-have-a-continuous-curve-using-python # https://stackoverflow.com/questions/45829155/sort-points-in-order-to-have-a-continuous-curve-using-python
if start is None: if start is None:
start = points[0] start = points[0]
@@ -101,17 +102,17 @@ def optimizedPath(points, start=None):
path = [start] path = [start]
pass_by.remove(start) pass_by.remove(start)
while pass_by: while pass_by:
nearest = min(pass_by, key=lambda x: distance2D(path[-1], x)) nearest = min(pass_by, key=lambda x: distance(path[-1], x))
path.append(nearest) path.append(nearest)
pass_by.remove(nearest) pass_by.remove(nearest)
return path return path
def nearest(points, start): def nearest(points, start):
return min(points, key=lambda x: distance2D(start, x)) return min(points, key=lambda x: distance(start, x))
def sortRotation(points): def sort_by_clockwise(points):
""" """
Sort point in a rotation order. Works in 2d but supports 3d. Sort point in a rotation order. Works in 2d but supports 3d.
@@ -124,7 +125,7 @@ def sortRotation(points):
Returns: Returns:
list: List of tuples of coordinates sorted (2d or 3d). list: List of tuples of coordinates sorted (2d or 3d).
>>> sortRotation([(0, 45, 100), (4, -5, 5),(-5, 36, -2)]) >>> sort_by_clockwise([(0, 45, 100), (4, -5, 5),(-5, 36, -2)])
[(0, 45, 100), (-5, 36, -2), (4, -5, 5)] [(0, 45, 100), (-5, 36, -2), (4, -5, 5)]
""" """
x, y = [], [] x, y = [], []
@@ -150,21 +151,21 @@ def sortRotation(points):
y_sorted = list(y[mask]) y_sorted = list(y[mask])
# Rearrange tuples to get the right coordinates. # Rearrange tuples to get the right coordinates.
sortedPoints = [] sorted_points = []
for i in range(len(points)): for i in range(len(points)):
j = 0 j = 0
while (x_sorted[i] != points[j][0]) and (y_sorted[i] != points[j][-1]): while (x_sorted[i] != points[j][0]) and (y_sorted[i] != points[j][-1]):
j += 1 j += 1
else: else:
if len(points[0]) == 3: if len(points[0]) == 3:
sortedPoints.append((x_sorted[i], points[j][1], y_sorted[i])) sorted_points.append((x_sorted[i], points[j][1], y_sorted[i]))
else: else:
sortedPoints.append((x_sorted[i], y_sorted[i])) sorted_points.append((x_sorted[i], y_sorted[i]))
return sortedPoints return sorted_points
def lineIntersection(line0, line1, fullLine=True): def segments_intersection(line0, line1, full_line=True):
""" """
Find (or not) intersection between two lines. Works in 2d but Find (or not) intersection between two lines. Works in 2d but
supports 3d. supports 3d.
@@ -174,13 +175,13 @@ def lineIntersection(line0, line1, fullLine=True):
Args: Args:
line0 (tuple): Tuple of tuple of coordinates. line0 (tuple): Tuple of tuple of coordinates.
line1 (tuple): Tuple of tuple of coordinates. line1 (tuple): Tuple of tuple of coordinates.
fullLine (bool, optional): True to find intersections along full_line (bool, optional): True to find intersections along
full line - not just in the segment. full line - not just in the segment.
Returns: Returns:
tuple: Coordinates (2d). tuple: Coordinates (2d).
>>> lineIntersection(((0, 0), (0, 5)), ((2.5, 2.5), (-2.5, 2.5))) >>> segments_intersection(((0, 0), (0, 5)), ((2.5, 2.5), (-2.5, 2.5)))
""" """
xdiff = (line0[0][0] - line0[1][0], line1[0][0] - line1[1][0]) xdiff = (line0[0][0] - line0[1][0], line1[0][0] - line1[1][0])
ydiff = (line0[0][-1] - line0[1][-1], line1[0][-1] - line1[1][-1]) ydiff = (line0[0][-1] - line0[1][-1], line1[0][-1] - line1[1][-1])
@@ -196,7 +197,7 @@ def lineIntersection(line0, line1, fullLine=True):
x = det(d, xdiff) / div x = det(d, xdiff) / div
y = det(d, ydiff) / div y = det(d, ydiff) / div
if not fullLine: if not full_line:
if ( if (
min(line0[0][0], line0[1][0]) <= x <= max(line0[0][0], line0[1][0]) min(line0[0][0], line0[1][0]) <= x <= max(line0[0][0], line0[1][0])
and min(line1[0][0], line1[1][0]) and min(line1[0][0], line1[1][0])
@@ -216,8 +217,8 @@ def lineIntersection(line0, line1, fullLine=True):
return x, y return x, y
def circleLineSegmentIntersection( def circle_segment_intersection(
circleCenter, circleRadius, xy0, xy1, fullLine=True, tangentTol=1e-9 circle_center, circle_radius, xy0, xy1, full_line=True, tangent_tolerance=1e-9
): ):
""" """
Find the points at which a circle intersects a line-segment. This Find the points at which a circle intersects a line-segment. This
@@ -227,16 +228,16 @@ def circleLineSegmentIntersection(
Note: We follow: http://mathworld.wolfram.com/Circle-LineIntersection.html Note: We follow: http://mathworld.wolfram.com/Circle-LineIntersection.html
Args: Args:
circleCenter (tuple): The (x, y) location of the circle center. circle_center (tuple): The (x, y) location of the circle center.
circleRadius (int): The radius of the circle. circle_radius (int): The radius of the circle.
xy0 (tuple): The (x, y) location of the first point of the xy0 (tuple): The (x, y) location of the first point of the
segment. segment.
xy1 ([tuple]): The (x, y) location of the second point of the xy1 ([tuple]): The (x, y) location of the second point of the
segment. segment.
fullLine (bool, optional): True to find intersections along full_line (bool, optional): True to find intersections along
full line - not just in the segment. False will just return full line - not just in the segment. False will just return
intersections within the segment. Defaults to True. intersections within the segment. Defaults to True.
tangentTol (float, optional): Numerical tolerance at which we tangent_tolerance (float, optional): Numerical tolerance at which we
decide the intersections are close enough to consider it a decide the intersections are close enough to consider it a
tangent. Defaults to 1e-9. tangent. Defaults to 1e-9.
@@ -248,13 +249,13 @@ def circleLineSegmentIntersection(
(p1x, p1y), (p2x, p2y), (cx, cy) = ( (p1x, p1y), (p2x, p2y), (cx, cy) = (
(xy0[0], xy0[-1]), (xy0[0], xy0[-1]),
(xy1[0], xy1[-1]), (xy1[0], xy1[-1]),
(circleCenter[0], circleCenter[1]), (circle_center[0], circle_center[1]),
) )
(x1, y1), (x2, y2) = (p1x - cx, p1y - cy), (p2x - cx, p2y - cy) (x1, y1), (x2, y2) = (p1x - cx, p1y - cy), (p2x - cx, p2y - cy)
dx, dy = (x2 - x1), (y2 - y1) dx, dy = (x2 - x1), (y2 - y1)
dr = (dx ** 2 + dy ** 2) ** 0.5 dr = (dx ** 2 + dy ** 2) ** 0.5
big_d = x1 * y2 - x2 * y1 big_d = x1 * y2 - x2 * y1
discriminant = circleRadius ** 2 * dr ** 2 - big_d ** 2 discriminant = circle_radius ** 2 * dr ** 2 - big_d ** 2
if discriminant < 0: # No intersection between circle and line if discriminant < 0: # No intersection between circle and line
return [] return []
@@ -274,7 +275,7 @@ def circleLineSegmentIntersection(
for sign in ((1, -1) if dy < 0 else (-1, 1)) for sign in ((1, -1) if dy < 0 else (-1, 1))
] # This makes sure the order along the segment is correct ] # This makes sure the order along the segment is correct
if ( if (
not fullLine not full_line
): # If only considering the segment, filter out intersections that do not fall within the segment ): # If only considering the segment, filter out intersections that do not fall within the segment
fraction_along_segment = [ fraction_along_segment = [
(xi - p1x) / dx if abs(dx) > abs(dy) else (yi - p1y) / dy (xi - p1x) / dx if abs(dx) > abs(dy) else (yi - p1y) / dy
@@ -286,7 +287,7 @@ def circleLineSegmentIntersection(
if 0 <= frac <= 1 if 0 <= frac <= 1
] ]
if ( if (
len(intersections) == 2 and abs(discriminant) <= tangentTol len(intersections) == 2 and abs(discriminant) <= tangent_tolerance
): # If line is tangent to circle, return just one point (as both intersections have same location) ): # If line is tangent to circle, return just one point (as both intersections have same location)
return [intersections[0]] return [intersections[0]]
else: else:
@@ -320,8 +321,8 @@ def perpendicular(distance, xy1, xy2):
return ((round(x3), round(y3)), (round(x4), round(y4))) return ((round(x3), round(y3)), (round(x4), round(y4)))
def curveCornerIntersectionPoints( def curved_corner_intersection(
line0, line1, startDistance, angleAdaptation=False line0, line1, start_distance, angle_adaptation=False, full_line=False, center=(), output_only_points=True
): ):
""" """
Create points between the two lines to smooth the intersection. Create points between the two lines to smooth the intersection.
@@ -329,140 +330,75 @@ def curveCornerIntersectionPoints(
Args: Args:
line0 (tuple): Tuple of tuple. Line coordinates. Order matters. line0 (tuple): Tuple of tuple. Line coordinates. Order matters.
line1 (tuple): Tuple of tuple. Line coordinates. Order matters. line1 (tuple): Tuple of tuple. Line coordinates. Order matters.
startDistance (int): distance from the intersection where the start_distance (int): distance from the intersection where the
curve should starts. curve should starts.
angleAdaptation (bool, optional): True will adapt the angleAdaptation (bool, optional): True will adapt the
startDistance depending of the angle between the two lines. start_distance depending of the angle between the two lines.
False will force the distance to be startDistance. Defaults to False will force the distance to be start_distance. Defaults to
False. False.
Returns: Returns:
[list]: List of tuple of coordinates (2d) that forms the curve. [list]: List of tuple of coordinates (2d) that forms the curve.
Starts on the line and end on the other line. Starts on the line and end on the other line.
>>> curveCornerIntersectionPoints(((0, 0), (50, 20)), ((-5, 50), (25, -5)), 10) >>> curved_corner_intersection(((0, 0), (50, 20)), ((-5, 50), (25, -5)), 10)
""" """
intersection = lineIntersection(line0, line1, fullLine=True) intersection = segments_intersection(line0, line1, full_line)
if intersection == None: if intersection == None:
return None return None
# Define automatically the distance from the intersection, where the curve # Define automatically the distance from the intersection, where the curve
# starts. # starts.
if angleAdaptation: if angle_adaptation:
angle = getAngle( angle = get_angle(
(line0[0][0], line0[0][-1]), (line0[0][0], line0[0][-1]),
intersection, intersection,
(line1[0][0], line1[0][-1]), (line1[0][0], line1[0][-1]),
) )
# Set here the radius of the circle for a square angle. # Set here the radius of the circle for a square angle.
startDistance = startDistance * abs(1 / (angle / 90)) start_distance = start_distance * abs(1 / (angle / 90))
startCurvePoint = circleLineSegmentIntersection( start_curve_point = circle_segment_intersection(
intersection, startDistance, line0[0], intersection, fullLine=True intersection, start_distance, line0[0], intersection, full_line
)[0] )[0]
endCurvePoint = circleLineSegmentIntersection( start_curve_point = (
intersection, startDistance, line1[0], intersection, fullLine=True 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] )[0]
end_curve_point = (round(end_curve_point[0]), round(end_curve_point[1]))
# Higher value for better precision # Higher value for better precision
perpendicular0 = perpendicular(10e3, startCurvePoint, intersection)[0] perpendicular0 = perpendicular(10e3, start_curve_point, intersection)[0]
perpendicular1 = perpendicular(10e3, endCurvePoint, intersection)[1] perpendicular1 = perpendicular(10e3, end_curve_point, intersection)[1]
center = lineIntersection( if center == ():
(perpendicular0, startCurvePoint), (perpendicular1, endCurvePoint) center = segments_intersection(
) (perpendicular0, start_curve_point), (perpendicular1, end_curve_point)
)
center = round(center[0]), round(center[1])
# Distance with startCurvePoint and endCurvePoint from the center are the # Distance with startCurvePoint and endCurvePoint from the center are the
# same. # same.
radius = distance2D(startCurvePoint, center) radius = round(distance(start_curve_point, center))
circle = circlePoints( if output_only_points:
center, round(radius), 32 circle_data = circle_points(
) # n=round((2 * pi * radius) / 32) center, radius, 32
) # n=round((2 * pi * radius) / 32)
else:
circle_data = circle(center, radius)[0]
# Find the correct point on the circle. # Find the correct point on the circle.
curveCornerPointsTemp = [startCurvePoint] curved_corner_points_temporary = [start_curve_point]
for point in circle: for point in circle_data:
if InTriangle(point, intersection, startCurvePoint, endCurvePoint): if is_in_triangle(point, intersection, start_curve_point, end_curve_point):
curveCornerPointsTemp.append(point) curved_corner_points_temporary.append(
curveCornerPointsTemp.append(endCurvePoint) (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. # Be sure that all the points are in correct order.
curveCornerPoints = optimizedPath(curveCornerPointsTemp, startCurvePoint) curve_corner_points = optimized_path(
return curveCornerPoints curved_corner_points_temporary, start_curve_point)
return curve_corner_points, center, radius
def curveCornerIntersectionLine(
line0, line1, startDistance, angleAdaptation=False, center=()
):
"""
Create a continuous circular line between the two lines to smooth
the intersection.
Args:
line0 (tuple): Tuple of tuple. Line coordinates. Order matters.
line1 (tuple): Tuple of tuple. Line coordinates. Order matters.
startDistance (int): distance from the intersection where the
curve should starts.
angleAdaptation (bool, optional): True will adapt the
startDistance depending of the angle between the two lines.
False will force the distance to be startDistance. Defaults to
False.
Returns:
[list]: List of tuple of coordinates (2d) that forms the curve.
Starts on the line and end on the other line.
TODO:
angleAdaptation : Set circle radius and not startDistance.
Polar coordinates / Unit circle instead of InTriangle.
>>> curveCornerIntersectionLine(((0, 0), (50, 20)), ((-5, 50), (25, -5)), 10)
"""
intersection = lineIntersection(line0, line1, fullLine=True)
if intersection == None:
return None
# Define automatically the distance from the intersection, where the curve
# starts.
if angleAdaptation:
angle = getAngle(
(line0[0][0], line0[0][-1]),
intersection,
(line1[0][0], line1[0][-1]),
)
# Set here the radius of the circle for a square angle.
startDistance = startDistance * abs(1 / (angle / 90))
startCurvePoint = circleLineSegmentIntersection(
intersection, startDistance, line0[0], intersection, fullLine=True
)[0]
endCurvePoint = circleLineSegmentIntersection(
intersection, startDistance, line1[0], intersection, fullLine=True
)[0]
# Higher value for better precision
perpendicular0 = perpendicular(10e3, startCurvePoint, intersection)[0]
perpendicular1 = perpendicular(10e3, endCurvePoint, intersection)[1]
if center == ():
center = lineIntersection(
(perpendicular0, startCurvePoint), (perpendicular1, endCurvePoint)
)
# Distance with startCurvePoint and endCurvePoint from the center
# are almost the same.
radius = distance2D(startCurvePoint, center)
circleArc = circle(center, round(radius))[0]
# Find the correct point on the circle.
curveCornerPointsTemp = [startCurvePoint]
for point in circleArc:
if InTriangle(point, intersection, startCurvePoint, endCurvePoint):
curveCornerPointsTemp.append(point)
# curveCornerPointsTemp.append(endCurvePoint)
# Be sure that all the points are in correct order.
curveCornerPoints = optimizedPath(curveCornerPointsTemp, startCurvePoint)
return curveCornerPoints, center