diff --git a/main.py b/main.py index 28309d7..b1bfa74 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,5 @@ +from networks.roads_2.Roads import Road import json import random @@ -25,7 +26,7 @@ from networks.geometry.point_tools import ( 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 import Road as Road from networks.roads.intersections import Intersection as Intersection matplotlib.use('Agg') @@ -296,9 +297,6 @@ 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)) @@ -396,9 +394,9 @@ for i in range(0, len(p.arcs)): 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 j in range(len(p.segments[i].segment_thick(5, LINE_THICKNESS_MODE.MIDDLE))): + draw.point((p.segments[i].points_thick[j].x+w, + w-p.segments[i].points_thick[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') @@ -409,9 +407,29 @@ for i in range(1, len(p.centers)-1): draw.point((p.acrs_intersections[i][2].x+w, w-p.acrs_intersections[i][2].y), fill='blue') - image.save('output_image.png') + +# road = Road([Point3D(-1201, 75, 705), Point3D(-1162, 69, 687), +# Point3D(-1149, 71, 647), Point3D(-1191, 68, 611)], 5) + +# road = Road([Point3D(-1359, 75, 696), Point3D(-1389, 126, 697), +# Point3D(-1401, 126, 714), Point3D(-1426, 126, 707), Point3D(-1452, 126, 714), Point3D(-1430, 126, 765)], 5) + +# road = Road([Point3D(-1203, 73, 718), Point3D(-1157, 76, 719), +# Point3D(-1119, 76, 763), Point3D(-1101, 76, 827), Point3D(-1088, 76, 879), Point3D(-1095, 76, 944)], 10) + +# road = Road([Point3D(-986, 83, 602), Point3D(-1000, 83, 647), +# Point3D(-993, 83, 680), Point3D(-965, 83, 712)], 10) + +# road = Road([Point3D(-984, 97, 811), Point3D(-984, 97, 847), +# Point3D(-962, 97, 860), Point3D(-970, 97, 900), Point3D(-953, 97, 920)], 10) + +road = Road([Point3D(-1024, 106, 1000), Point3D(-1024, 101, 972), + Point3D(-1001, 100, 966), Point3D(-977, 98, 984), Point3D(-966, 102, 1011), Point3D(-905, 97, 1013), Point3D(-774, 99, 998), Point3D(-694, 99, 1047)], 9) + +road.place() + # s = Segment2D(Point2D(-88, -12), Point2D(9, 75)) # s.segment_thick(3, LINE_THICKNESS_MODE.MIDDLE) # print(s.points) diff --git a/networks/geometry/Point2D.py b/networks/geometry/Point2D.py index ef8a804..9848d5b 100644 --- a/networks/geometry/Point2D.py +++ b/networks/geometry/Point2D.py @@ -197,9 +197,33 @@ class Point2D: self.coordinates = (self.x, self.y) return self - def distance(self, point: "Point2D") -> int: + def distance(self, point: "Point2D") -> float: return sqrt((point.x - self.x) ** 2 + (point.y - self.y) ** 2) + # def slope(self, point: "Point2D") -> int: + # try: + # slope = (point.y - self.y) / (point.x - self.x) + # return slope + # except ZeroDivisionError: + # return float('inf') + + # def is_between_slopes(self, lower_slope: int, upper_slope: int) -> bool: + # slope = self.slope(Point2D(0, 0)) + # print("sole", slope, (slope <= upper_slope), (slope >= lower_slope), + # ((slope <= upper_slope) and (slope >= lower_slope))) + # return ((slope <= upper_slope) and (slope >= lower_slope)) + + # def is_between_lines(self, point_1: "Point2D", point_2: "Point2D", point_a: "Point2D", point_b: "Point2D") -> bool: + # slope_1, slope_a = point_1.slope(point_2), point_a.slope(point_b) + # lower_slope, upper_slope = min(slope_1, slope_a), max(slope_1, slope_a) + # print(self.is_between_slopes(lower_slope, upper_slope), "slope", + # lower_slope, upper_slope, self.slope(Point2D(0, 0))) + # print(self.x <= max(point_1.x, point_2.x, point_a.x, point_b.x), "x max") + # print(self.x >= min(point_1.x, point_2.x, point_a.x, point_b.x), "x min") + # print(self.y <= max(point_1.y, point_2.y, point_a.y, point_b.y), "y max") + # print(self.y >= min(point_1.y, point_2.y, point_a.y, point_b.y), "y min") + # return self.is_between_slopes(lower_slope, upper_slope) and self.x <= max(point_1.x, point_2.x, point_a.x, point_b.x) and self.x >= min(point_1.x, point_2.x, point_a.x, point_b.x) and self.y <= max(point_1.y, point_2.y, point_a.y, point_b.y) and self.y >= min(point_1.y, point_2.y, point_a.y, point_b.y) + @staticmethod def collinear(p0: "Point2D", p1: "Point2D", p2: "Point2D") -> bool: # https://stackoverflow.com/questions/9608148/python-script-to-determine-if-x-y-coordinates-are-colinear-getting-some-e diff --git a/networks/geometry/Point3D.py b/networks/geometry/Point3D.py index 75fb36c..dcbca41 100644 --- a/networks/geometry/Point3D.py +++ b/networks/geometry/Point3D.py @@ -1,5 +1,6 @@ from math import sqrt -from typing import List +from typing import List, Union +from networks.geometry.Point2D import Point2D import numpy as np @@ -72,23 +73,52 @@ class Point3D: return sqrt((point.x - self.x) ** 2 + (point.y - self.y) ** 2 + (point.z - self.z) ** 2) @staticmethod - def to_vectors(points: List["Point3D"]): - 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["Point3D"], "Point3D"]) -> Union[List[np.array], "Point3D"]: + 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: 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: + def from_arrays(vectors: Union[List[np.array], "Point3D"]) -> Union[List["Point3D"], "Point3D"]: + if isinstance(vectors, list): + points = [] + for vector in vectors: + points.append(Point3D(vector[0], vector[1], vector[2])) return points + else: + return Point3D(vectors[0], vectors[1], vectors[2]) + + @staticmethod + def to_2d(points: List["Point3D"], removed_axis: str) -> List[Point2D]: + points_2d = [] + if removed_axis == 'x': + for i in range(len(points)): + points_2d.append(Point2D(points[i].y, points[i].z)) + if removed_axis == 'y': + for i in range(len(points)): + points_2d.append(Point2D(points[i].x, points[i].z)) + if removed_axis == 'z': + for i in range(len(points)): + points_2d.append(Point2D(points[i].x, points[i].y)) + return points_2d + + @staticmethod + def insert_3d(points: List[Point2D], position: str, to_insert: List[int]) -> List["Point3D"]: + points_3d = [] + if position == 'x': + for i in range(len(points)): + points_3d.append( + Point3D(to_insert[i], points[i].x, points[i].y)) + if position == 'y': + for i in range(len(points)): + points_3d.append( + Point3D(points[i].x, to_insert[i], points[i].y)) + if position == 'z': + for i in range(len(points)): + points_3d.append( + Point3D(points[i].x, points[i].y, to_insert[i])) + return points_3d diff --git a/networks/geometry/Polyline.py b/networks/geometry/Polyline.py index 5f320ec..d5892a9 100644 --- a/networks/geometry/Polyline.py +++ b/networks/geometry/Polyline.py @@ -47,7 +47,7 @@ class Polyline: # 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 + self.bisectors = [None] * self.length_polyline # For n points, there is n-1 segments. Last element should stays None. self.segments = [None] * \ @@ -106,16 +106,11 @@ class Polyline: 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") + self.bisectors[i] = Point2D.to_arrays( + self.centers[i]) + (self.unit_vectors[i-1] - self.points_array[i]) + + (self.unit_vectors[i]+self.unit_vectors[i-1]) / \ + np.linalg.norm(self.unit_vectors[i]-self.unit_vectors[i-1]) return self.arcs def get_segments(self) -> List[Segment2D]: @@ -133,14 +128,14 @@ class Polyline: self.points_array[0]), self.acrs_intersections[1][0]) # Get segments between arcs - for i in range(2, self.length_polyline - 2): + for i in range(2, self.length_polyline - 1): 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]) + self.segments[-2] = Segment2D(self.acrs_intersections[-2][2], Point2D.from_arrays( + self.points_array[-1])) return self.segments @@ -205,9 +200,11 @@ class Polyline: self.unit_vectors[j] = self.vectors[j]/self.lengths[j] # Between two segments, there is only one angle - for k in range(1, self.length_polyline-1): - dot = np.dot(self.unit_vectors[k], self.unit_vectors[k-1]) - self.tangente[k] = sqrt((1+dot)/(1-dot)) + for i in range(1, self.length_polyline-1): + dot = np.dot(self.unit_vectors[i], self.unit_vectors[i-1]) + self.tangente[i] = sqrt((1+dot)/(1-dot)) + # self.bisectors[i] = (self.unit_vectors[i]+self.unit_vectors[i-1]) / \ + # np.linalg.norm(self.unit_vectors[i]-self.unit_vectors[i-1]) def _compute_alpha_radii(self): self.alpha_radii[0] = 0 diff --git a/networks/roads_2/Roads.py b/networks/roads_2/Roads.py new file mode 100644 index 0000000..1d7b16a --- /dev/null +++ b/networks/roads_2/Roads.py @@ -0,0 +1,79 @@ +import json +from typing import List +from networks.geometry.Polyline import Polyline +from networks.geometry.Segment2D import Segment2D +from networks.geometry.Segment3D import Segment3D +from networks.geometry.Point3D import Point3D +from networks.geometry.Point2D import Point2D +from networks.geometry.Circle import Circle +from Enums import LINE_THICKNESS_MODE +from gdpc import Block, Editor, geometry + + +class Road: + def __init__(self, coordinates: List[Point3D], width: int): + self.coordinates = coordinates + self.output_block = [] + # with open(road_configuration) as f: + # self.road_configuration = json.load(f) + # self.width = self.road_configuration["width"] + self.width = width + + self.polyline = Polyline(Point3D.to_2d(coordinates, 'y')) + self.surface() + + # for i in range(1, len(self.polyline.segments)-1): + # print(self._y_interpolation(self.polyline.segments[i].segment_thick( + # self.width, LINE_THICKNESS_MODE.MIDDLE))) + # self._y_interpolation(self.polyline.segments[i].segment()) + + def surface(self): + # Segments + for i in range(1, len(self.polyline.segments)-1): + print() + if len(self.polyline.segments[i].segment()) > 1: + for j in range(len(self.polyline.segments[i].segment_thick(self.width, LINE_THICKNESS_MODE.MIDDLE))): + self.output_block.append( + (Point3D.insert_3d([self.polyline.segments[i].points_thick[j]], 'y', [170])[0].coordinates, Block("stone"))) + + for i in range(1, len(self.polyline.centers)-1): + # Circle + + circle = Circle(self.polyline.centers[i]) + circle.circle_thick(int( + (self.polyline.radii[i]-self.width/2)), int((self.polyline.radii[i]+self.width/2)-1)) + + # Better to do here than drawing circle arc inside big triangle! + double_point_a = Point2D.from_arrays(Point2D.to_arrays(self.polyline.acrs_intersections[i][0]) + 5 * (Point2D.to_arrays( + self.polyline.acrs_intersections[i][0]) - Point2D.to_arrays(self.polyline.centers[i]))) + double_point_b = Point2D.from_arrays(Point2D.to_arrays(self.polyline.acrs_intersections[i][2]) + 5 * (Point2D.to_arrays( + self.polyline.acrs_intersections[i][2]) - Point2D.to_arrays(self.polyline.centers[i]))) + + for j in range(len(circle.points_thick)): + if circle.points_thick[j].is_in_triangle(double_point_a, self.polyline.centers[i], double_point_b): + self.output_block.append( + (Point3D.insert_3d([circle.points_thick[j]], 'y', [ + 170+i])[0].coordinates, Block("white_concrete"))) + + # v = Point2D.to_arrays( + # self.polyline.centers[i]) - self.polyline.bisectors[i] + + # print(self.polyline.centers[i], Point2D.from_arrays(v).round()) + # # s = Segment2D( + # # self.polyline.centers[i], Point2D.from_arrays(v).round()) + # # s.segment() + # arc = Point2D.to_arrays(self.polyline.acrs_intersections[i][0]) + # s = Segment2D( + # self.polyline.centers[i], Point2D.from_arrays(arc)) + # s.segment() + + # for j in range(len(s.points)): + # self.output_block.append( + # (Point3D.insert_3d([s.points[j]], 'y', [ + # 162])[0].coordinates, Block("purple_concrete"))) + + def place(self): + editor = Editor(buffering=True) + for i in range(len(self.output_block)): + editor.placeBlock(self.output_block[i][0], + self.output_block[i][1]) diff --git a/output_image.png b/output_image.png index b091c41..ed7d9f2 100644 Binary files a/output_image.png and b/output_image.png differ