From a04c3056c98d689db7d236c6d1c3275114071287 Mon Sep 17 00:00:00 2001 From: Xeon0X Date: Sat, 15 Jun 2024 19:58:58 +0200 Subject: [PATCH] Working debug roads --- main.py | 34 +++++++++++---- networks/geometry/Point2D.py | 26 ++++++++++- networks/geometry/Point3D.py | 64 +++++++++++++++++++-------- networks/geometry/Polyline.py | 31 ++++++------- networks/roads_2/Roads.py | 79 ++++++++++++++++++++++++++++++++++ output_image.png | Bin 1754 -> 1912 bytes 6 files changed, 191 insertions(+), 43 deletions(-) create mode 100644 networks/roads_2/Roads.py 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 b091c4164b965d6678afc3f5decdfdb2757ebf5d..ed7d9f205ffda42f732f0c472ede6285fbc11734 100644 GIT binary patch delta 1898 zcmV-w2bK8R4fqa_BYy`!NklTpdg#IUNx7=Ksq0sw|ZQ!p%=f??4V z42z~K#CGw#CS@ z7}oz37Q@1_xPKHD3#)ek3d8zOX8hd!Pfn~S3@ao3Q$mLIgkjMX4C@chp0OBKJGPj> zuu}LktY!>Lq-pkWT%|EAnu1}`6b$QeQA<3);yRecuxJYJVR80M;ytVeY_SBxy2mS6 zom_{-*)xypuoC!uuoJ_gDg1_&m_1J)kj!ya&Tm)=e1F(3-S;AfMK_MBdfIXt7GKVg za6QuIqjnk=J^3xEtu2pX`I$Yno^F|jTg+ov4Lr1%KE}`IQ?)gQMIyPXj_WT~ZMh38 zaSOWrCG{m$9m?Bs7gjVowtR)f%U4%zRf$N9F?+N43X4uX zRh4XkVSjnlUsZNHj>6(PcoV5Y?-RSCngZBVfzZB@dsOj=%*m=DY0 zI+)%6r+NlfCFaBOrttK~7{7i2H^` zs`C-d^}bUL7#2K*<4SPDvbPRe8driF79G^yTOh+yduui`Hm(FTtOlSh0)Jh& z`r;)l%{2GX3@l z4`)L8JDY1^gw;UpX;8akW0?&L!hgQ+=N~MMD}e~h(&ekK9g8s@ZJBw@egX)~wisgw zd-~s~y`Lm7toJe_9Kf1y~ zyvvTd7K(W63A(~+p!s~bt$#`kgtb=swN`Gc5>;WrUA`Jpl~szu!ZNBVljBMlRvT88 zwXNQPKOok@>~~~UC%#K3udo1Cb)_OKwYPG4Qeyg@5e-y?)nICiRU2=30;u+mG!SZ7 zGc=rUR`q0kSQ>8Vwxr~``~^wBIimR+fm$C{gHflac{?|Qs&PwZL4StTuO}&KeVp!R zT*>n5STA3`>iOEvr+%)g5+@U@^Q4w16+*cEUf!w_^I?^r(c5~C$5K_7J&*6`u%s_5 zm%@4LVC{vd>t8#sbDrP&_Yba^npizO9kxwIWf1-~W^-tkO{}(C{OPM|m%KDS>Fb9y zv3}27|A-obN&P|!>wjwOh&olxD)yAHCamUDGH*oj6)$70d5ksn+;Bu`fVvd^Vo$0p zm{`Nl6PG-NfF~A5lxC1&aYX6&_EOmY`hr3nQEOpLtn#GTlM=5^tlAUFB@dUziNz() z09|2mM49p4QkXcq?8zP#6KmV#^U41+CIv*rgZF*kW!pCS++*g&o)D>+STV-^i0U%C z_^2G3t_!5KZ?R%eYC--Gnmy?U_IfNPg<|!aDFQ!B!zS%-v1d}C7Js-c!?J4qrzWS< kVOXHnhb1H4hDzG}16!N8*=lDAO8@`>07*qoM6N<$g6%D-ga7~l delta 1739 zcmV;+1~mEj4%!WnBYy^=Nkl-#?>ghE?5^=td5v_zVOb+yqD0-<-}@5IVHAJtCh z_l9;Gy{WC-{@}_>j1GN;^LJB{e(Q8r$II|Qmpf;V(z*L`MO{N7gwJjz5dRbmOD0=! z9e2-5C>xecyb$2*?Zh%$$GV|;efOuq{Ttk|S$ThS^ZK(L@s;~`T`8=qO%&bk`~8mn zBg?Xs*po;8I)D5BGfm~TY&Un>P(mfg*Ll6<^GSTQWDYv38rHTIlWl!RP~ogs-rTnl zJIlQvtG?|7xBA$U!(gMcqy6$;w>$mVQ^Rj#=@KXROQ_*)qgdbF>m?yLFMsU(E7T@!DM!?*x34&pz2EOT zW6X0{?+})=SB^?bsvo1$o2$@P{Yi0o(?`uuhi;RqwhyJ->L@Hp-5dSSM4b;RC9AzE z+E)ETXMAh&@#uu`KD|&KZctsZT0dKsrP}pY1rPT>MjfWBwjL~$9HwSma6}jD{nDkVm06y^shh1=-eUBV2XdD9ChTcvYs>Kp)~eKU!zseL8d~O6 zwH=U>_N)|!R;JxqH>|3k!<+aJ9@@%eUR7^LwavvlLI@(C5SGlUdh2PE{@5^vR=(up z(0~5{ta|aj>HoNNYn1im^pC>Fcj)Yv$hL-v>08-}rCf`jmgXRgGNN{}F5U-y&qEmf zz#2UBm#g?pF26i&bMd}$a~$(I8~-*>DQ9S5r}4xR!g9(ctj9Q(WeFkrQL`AAb z$4Z5zjDrh#uL@4AoWaA;8eRK~cZQZrWy8w(KxAkQt^LGWUA0ACgR;E4;fg*EZhvs2 zmx;By|0a>P22x{UN#wkF{M(2W*1t+&iFI4CFNn(e`Y7CJ)*$$B>{-2uC7Kx%et-O) z0sY_5r?B317S=&OzjhT-s)i-0=bq6uoZ4YY`L>cb0Yk%tC0>3b>m(Y4C3(N8A@-SD zEwzSNL=X$D>iDfD0V#`xiLRjX~ z+HzKv5LOAXZTYK8xW+0+nTyM+go#y-rWmhP31KzlxGLeJu(Z>9d?&SHVwH7lXojkU zuqya2X_Bf?4@m(407RfypVm770000000000000000000000000000000000000000 h000000001(`vX2A^D(GLZkhl9002ovPDHLkV1i3Fb~XS2