From b9138acbc82aa06a2a3e9ea3147f1a5f5dd2909e Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Thu, 24 Dec 2020 00:54:57 -0800 Subject: [PATCH] Use shapely projection instead of brute force. Converts the landmap to use MultiPolygon instead of a collection of polygons, since Shapely has explicit support for this. Because we've done that, we can use a single projection from a line instead of brute forcing the extent of the front line. This makes turn processing ~66% faster (3 seconds to 1.8). There are probably other places this should be used. --- game/theater/conflicttheater.py | 13 ++++++------- game/theater/landmap.py | 14 ++++++++++---- gen/conflictgen.py | 25 +++++++++++++++++-------- qt_ui/widgets/map/QLiberationMap.py | 6 +++--- resources/caulandmap.p | Bin 62427 -> 61880 bytes resources/channellandmap.p | Bin 15746 -> 15654 bytes resources/gulflandmap.p | Bin 92758 -> 91085 bytes resources/nevlandmap.p | Bin 15961 -> 15718 bytes resources/normandylandmap.p | Bin 64592 -> 63000 bytes resources/syrialandmap.p | Bin 41895 -> 41195 bytes resources/tools/generate_landmap.py | 7 ++++++- 11 files changed, 42 insertions(+), 23 deletions(-) diff --git a/game/theater/conflicttheater.py b/game/theater/conflicttheater.py index e0aa1154..6281b7d7 100644 --- a/game/theater/conflicttheater.py +++ b/game/theater/conflicttheater.py @@ -447,11 +447,11 @@ class ConflictTheater: if self.is_on_land(point): return False - for exclusion_zone in self.landmap[1]: + for exclusion_zone in self.landmap.exclusion_zones: if poly_contains(point.x, point.y, exclusion_zone): return False - for sea in self.landmap[2]: + for sea in self.landmap.sea_zones: if poly_contains(point.x, point.y, sea): return True @@ -462,14 +462,13 @@ class ConflictTheater: return True is_point_included = False - for inclusion_zone in self.landmap[0]: - if poly_contains(point.x, point.y, inclusion_zone): - is_point_included = True + if poly_contains(point.x, point.y, self.landmap.inclusion_zones): + is_point_included = True if not is_point_included: return False - for exclusion_zone in self.landmap[1]: + for exclusion_zone in self.landmap.exclusion_zones: if poly_contains(point.x, point.y, exclusion_zone): return False @@ -484,7 +483,7 @@ class ConflictTheater: nearest_points = [] if not self.landmap: raise RuntimeError("Landmap not initialized") - for inclusion_zone in self.landmap[0]: + for inclusion_zone in self.landmap.inclusion_zones: nearest_pair = ops.nearest_points(point, inclusion_zone) nearest_points.append(nearest_pair[1]) min_distance = point.distance(nearest_points[0]) # type: geometry.Point diff --git a/game/theater/landmap.py b/game/theater/landmap.py index 6e510087..89dcdcf7 100644 --- a/game/theater/landmap.py +++ b/game/theater/landmap.py @@ -1,11 +1,17 @@ +from dataclasses import dataclass import pickle -from typing import Collection, Optional, Tuple +from typing import Optional, Tuple, Union import logging from shapely import geometry +from shapely.geometry import MultiPolygon, Polygon -Zone = Collection[Tuple[float, float]] -Landmap = Tuple[Collection[geometry.Polygon], Collection[geometry.Polygon], Collection[geometry.Polygon]] + +@dataclass(frozen=True) +class Landmap: + inclusion_zones: MultiPolygon + exclusion_zones: MultiPolygon + sea_zones: MultiPolygon def load_landmap(filename: str) -> Optional[Landmap]: @@ -17,7 +23,7 @@ def load_landmap(filename: str) -> Optional[Landmap]: return None -def poly_contains(x, y, poly:geometry.Polygon): +def poly_contains(x, y, poly: Union[MultiPolygon, Polygon]): return poly.contains(geometry.Point(x, y)) diff --git a/gen/conflictgen.py b/gen/conflictgen.py index 68946ab2..796e6507 100644 --- a/gen/conflictgen.py +++ b/gen/conflictgen.py @@ -1,9 +1,9 @@ import logging -import random from typing import Tuple, Optional from dcs.country import Country from dcs.mapping import Point +from shapely.geometry import LineString, Point as ShapelyPoint from game.theater.conflicttheater import ConflictTheater, FrontLine from game.theater.controlpoint import ControlPoint @@ -56,7 +56,7 @@ class Conflict: """ center_position, heading = cls.frontline_position(from_cp, to_cp, theater) left_heading = heading_sum(heading, -90) - right_heading = heading_sum(heading, 90) + right_heading = heading_sum(heading, 90) left_position = cls.extend_ground_position(center_position, int(FRONTLINE_LENGTH / 2), left_heading, theater) right_position = cls.extend_ground_position(center_position, int(FRONTLINE_LENGTH / 2), right_heading, theater) distance = int(left_position.distance_to_point(right_position)) @@ -83,12 +83,21 @@ class Conflict: @classmethod def extend_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater) -> Point: """Finds the first intersection with an exclusion zone in one heading from an initial point up to max_distance""" - pos = initial - for distance in range(0, int(max_distance), 100): - pos = initial.point_from_heading(heading, distance) - if not theater.is_on_land(pos): - return initial.point_from_heading(heading, distance - 100) - return pos + extended = initial.point_from_heading(heading, max_distance) + p0 = ShapelyPoint(initial.x, initial.y) + p1 = ShapelyPoint(extended.x, extended.y) + line = LineString([p0, p1]) + + intersection = line.intersection( + theater.landmap.inclusion_zones.boundary) + if intersection.is_empty: + # Max extent does not intersect with the boundary of the inclusion + # zone, so the full front line is usable. This does assume that the + # front line was centered on a valid location. + return extended + + # Otherwise extend the front line only up to the intersection. + return initial.point_from_heading(heading, p0.distance(intersection)) @classmethod def find_ground_position(cls, initial: Point, max_distance: int, heading: int, theater: ConflictTheater, coerce=True) -> Optional[Point]: diff --git a/qt_ui/widgets/map/QLiberationMap.py b/qt_ui/widgets/map/QLiberationMap.py index a06b8f44..025230de 100644 --- a/qt_ui/widgets/map/QLiberationMap.py +++ b/qt_ui/widgets/map/QLiberationMap.py @@ -945,7 +945,7 @@ class QLiberationMap(QGraphicsView): # Polygon display mode if self.game.theater.landmap is not None: - for sea_zone in self.game.theater.landmap[2]: + for sea_zone in self.game.theater.landmap.sea_zones: print(sea_zone) poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in sea_zone.exterior.coords]) if self.reference_point_setup_mode: @@ -954,14 +954,14 @@ class QLiberationMap(QGraphicsView): color = "sea_blue" scene.addPolygon(poly, CONST.COLORS[color], CONST.COLORS[color]) - for inclusion_zone in self.game.theater.landmap[0]: + for inclusion_zone in self.game.theater.landmap.inclusion_zones: poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in inclusion_zone.exterior.coords]) if self.reference_point_setup_mode: scene.addPolygon(poly, CONST.COLORS["grey_transparent"], CONST.COLORS["dark_grey_transparent"]) else: scene.addPolygon(poly, CONST.COLORS["grey"], CONST.COLORS["dark_grey"]) - for exclusion_zone in self.game.theater.landmap[1]: + for exclusion_zone in self.game.theater.landmap.exclusion_zones: poly = QPolygonF([QPointF(*self._transform_point(Point(point[0], point[1]))) for point in exclusion_zone.exterior.coords]) if self.reference_point_setup_mode: scene.addPolygon(poly, CONST.COLORS["grey_transparent"], CONST.COLORS["dark_dark_grey_transparent"]) diff --git a/resources/caulandmap.p b/resources/caulandmap.p index c9f77f43939a38768b6c4d8a3418454b22b56bc9..7ceefc71a52aa19b121360e8773806d0e025dc6b 100644 GIT binary patch delta 507 zcmY*WTWAwe5Z${s?Y3Yj(jfSVf{N(JuHa{Jq4=SQmWuxp)_TbX_Ys&LC_&u# zn$;j>RYVko1?zwmA%bA+L)ThGgqEOCXc6p3Py~@cZ!|y7*PP+ZIm4O76*{>@N6*D> zhIQd@d5N@UGR4uE=CDD<(5zFYmi0a9XsZK%&w1bVcY9qKYrx3oGPadEYg;Vmd&!)x zWtmY>(#$rQGgwf}yy0ZBwoypimhY|WYrGIQEHCnmkoNDbe2!sZ9;kH=iIlzokN;yfwhyZ9y-7OUVh`?x-T3KI0Oo57lsC z*zLrDv80IJ1({&=BA*{A2Kck65>ziW2p+twQt+-s$gai-j$Eq{JamIgKLO78?enF5 zw*rETWe#`Vc0~-wRf@mvm=x{%s|582aS=uyHn8|8PVwGjGmaZ4OCmmfUZXhv!feCD zt0aM*YKT9oeFP3q)nM;*gdH<3!Rxa!fvGnkxNlvcQ3YnA2=2bC0GlhppSe}2zYm~1 zUjq3<4L5w0W7z+h8&5B&ZMgnxNO5*a7LhLVEBCK_i6yydN5k!Ub=tKyNd6c4f*(tIP%8D#@%%T0~dR=J#7Eay} zYmJ>q@YBrco=f@ccy6qe9?cc>Tydh59xsfQMhh3s>G;{*FEEduGY6gI-0j6=cUCix zf;z0VpT zL`nI`-eDz0h#K>e{-PQq#6Z>JWrI~c_;bbMe!}msUNsVg$f$Aprpy`&YUC#s_8O?x zrb4O~>?^ZZ6&WwfDl^)MY~N`!q6$8;c~2E+Ul$HnUGgCzW2Y)H!|{<<_ZupIORq--BQ8J@Vaj9}(dxd)ym~|`EYr*l=7F8A;TC=FCz?(Hb=|QH!&sq_EzsJ5PBJCU8 z*3j3`ZK;^q(l?bevoY7`cbjunF#8uj70y1`ySW~EPae+Nv++ah%4z2R|Gpisi(7MX JFxs03FE3ReSoS`hsw0WXxEaT+w zYJVsHRsXx0O;eX~v%MCOsL%$=E!4fsw7JUw$l7e=&nVl&S)7^(^%2CJ{YYRHoTeF+jUG8Q&@tGUimZansTn11>K2wYz!I}1T1lN{YuIfE>mpMd zkr<+}*JZqIZUpZT%?24^mNusyX?uGkAp2U;tQJtQqU7^2?nCU9iG-e_*p5?mWXH9&8;wT&&!Ee z;_kRB6mDwmXb(lgTb_@EgYAj9yS*jQ7HsYGGzTM6FuJ4DBXzV!Lv4}P&gMus5zqBy zwwva*98{mE8f~!IvcbWB&b7T?u{4ji=BfGQDz@&RMHP}r-RmVg-S(){K}8#UBE48= z3e>UDEmBXtCD5TKd@#_^1x0aJaOeNsw9L!kU8c=8OYgDK{>CmlmHT74bSh*54Q|tc zx+SMT{SghQX}edXqfx^_$rpSAO~q7!lwDlXwwp^{dnE-_zlX23y{e1!Se$!NyZG7G zZWYLdZlH$}GSJsaezEdRL!bq3aoywrH(>rj3m3g(Qr^2JV0N!T*Ls~mIfo39ru+Rs zPafsJlpW*6`JN=uo&m3jUw&ZVz=tX}vKWpr9gh!6xbhw-azL?3m06{aQIS+_Fm?x1`Un2 zkNE^lkL&dI4=P~wRSj=mRjKz!FVNIaKA@VPy@2vBDz5$2pe4U)K%>8F0=_<_QrRCV zAnTeRuxVPRo70@Q{JM%m*JHH#PYbZ&hKarzldAvn3e@#CKS^2^_1tm;rT=k4aso7V z06+uQD1rpah#gFp&H^W}aR(T{hUbA#P?pYzn9@5REagZp#8{aV+`#;|gBMtz3sS%$ zdEf&!ln*+vgA2hF*uFc#6d5iC8Q3a!rk*X}8f9@I7|gy5R8abtgQ{#Q0!?uggP}|o zgRJac0g^Ja0{qI;B_OjKB~WT-tMBCwm5EhgDwj)nIq%`}!TUg0-dN28)U3(S%=vfIR?bP!J;;NwuO5a{U^x{TpI6ppa_?WCd0hDjSgf`(69}t7 z7nM*o=&Y&+{DN|L17~<@Iru^?Y=n|zWx;HZ+u}Lx!N6SC{?{iZ{ARXKz{b|p!LkCe H;~CGt(;mrq delta 2892 zcmZ8jYitx%6z*-8LSZ+iYivr*mJ(E2wY4fKN*QZdl&D>x#0MeS2u(JWz|cw?ZI$sE zti+Bbo^7tLX=$`kkTIHK7pWr^sZFdS21-HA;DbO!GtdT%K^^0qf!uTJ{@U~1bI$jj zbHCXgdt}=9*tF_rLtUd;EDJx$bZJLnbHlo()TXwI^{GZR)v~3nqN#CH+xo`M>5l0u zuY7}a*{bxCSpG*Z&dCp_>l<<~G@@Bq{eAgHR3Kh~k1V;)D-ej9<0CcIY7QYGAK7!4 z8WKn(*GFc@Be?=eVAT!xC8)~H_L1gVH(TVyFlX(G80C1Fqpk8NC*e=o|KvjnCaQEq zMjq~D;gmo7|Z@6v0KP~`~{2H1BK~rQjU#! zdfRQ%6KsC-%hKk9K7+4FeGKf}y2GH(F+{F;HAaYz$Zen#5_CS0mO48)SNJtYnhW)u zeM8a{bROuAvAip;i+gai#}knY-|lp$-jmhqQnmxT-*&`#1XZ=a6CqU&GN$_++CUO> z9@~|qoM7AE?3T72AaCxG5EW->_&}vug1bKUp^_uCIuPCKh{%BRdkqn3(DAV*A{+7s zY!Rt2KA?)og?Pplkp`9fsLlj)pDE59Sn~<->9BCWF3xl~G$pDVq%#{%4%#BqgZDr6 zL}bBxmL(z;QlF_(bVQ15s5wAgbO;X-g9)z>nWD~tdp{?g8q7PWNoP9`(wPI=7Zka$ z=8!8gEm$^eiO7S{m!60WU?YZbfr)qCJz~<$*zmxpEzVUuFZ^01Pw0qjJFF8DxFmX1 za*2h$X&kd;@7+93YCXt1PKr#(JwY3=p#Ov=_yf;3eJ6R|1pRwcoF~w0i+)ICi}`G5 zcSyg1N*+9EkP;Ine@8&4ah!i2!028PSaCn zV*S=LCe@p$xa?Px6dN%98)>kxqWO1=Dw2p)x=CWxK|iO99mMdw=)ANe0~St@A`QkS zG?DFLcHN{$-CS6HfxP2F^+i`?E2y^g4~3rPpg#4dRPRCkB~MfYY99S7M*1Vjxb^P{ zi>B+lp4brl*=7ZQH*piT|3jA^E<)XZ|u3|1N+4Uc?%=RdA=_%8(@bLnsQ(*w*6v|M*xMQ}@C}wlGQ^Xu` zKL+;Me=Rd8!{Cp^82QEI7h{Yb5r_8{Ge@-3`O|ZlE<%;hDq*S!lf1QrB}J(7VxW`H5tOsE!Z(y?>G8T-rg&p{rQ{r)k5)<(23A{rt8X>YvK(9X-OkGC z;%tPDERanQ?4hU1--9R&#Mj;-i}(21I~hG|3idg(NOqx(&Y8EE+0rjMpQvHBXq!a4 wS$DG}{Q_ycC@#%pa2}U-l0cRPOW6uG%YRY4{GJ#q&g{B}%`FbCYfo4F2Z~|P#Q*>R diff --git a/resources/nevlandmap.p b/resources/nevlandmap.p index 1b92631ae893597b91ffbc1cc59f944fd6d4389b..42e34c3733984b1f1cbc79c7d45c6d5e05fd242b 100644 GIT binary patch delta 378 zcmcav^Q@}Afn{p6Edvaxrs|bsq$ZZ67U|_A=B4B&7EI}3_kpq|Ptk0gQaeSX zhd(nfIj6KZGe0lBDnBo^cuJ3KaYkZ6YEGqIdTM@dYDrP0UT$elNoGNQPGx$2-jp65 zUl2C{$^{w}G{q^6nSp_wkqu}!Bg00kL}t|<{?rOob2B(V3LPwgN50=#o4Z{xkYc|Kn+<7Nv1pn^cbSjNfQh4xOa6+XK; zOyn%fW_?Lrrp+1BzKoj>%B*GFTqQS`X|jUi+R4`x*KY1ts%73Rp{C2cIZ!i~W%6;| z+|3SpKvN?1?=nudH(WdUtKr(s>x_VQmYV?e8kqSqPHr>5yE)&YmvJ(y)!WVgtZJDi gx7eOn?BOgjO^ebW?-0-RGOp*0OQhz%m4rY delta 653 zcmaD>b+g8*fn}-&PXgs&8gH&PtDIwEh(zhE6C5OOwZ4o(!(AAWlf%< z88pQymU&}aA~Sbl>=ca*W}txc-N`&GcX_5Hfq726j0_B$U$XEr!bSFiM82`^MTqz^ z0Yx^m`!d1R*fKLPY~r$I=7bvKJa@7!?_4xEXsVuM^q}=bfFLEqoSk{aF^EY73FGEN~HBkP}%YbrDYV1(|3h?TfH=El8wZ zW-UTwE=ZS-+*~HOJ!>bQR9K6|D^pwxx1$#5>CMVYwajo4U69BERb7NgF34qPHF8z`(#?hI0Q-EoE|Smhf?Tyl?=HgUYbQ@MKz4(jA;Jyd$a!su6ggmDtuRLN71-yY xroIRh?@nH1h87?7=Di5{x087+-@@Hk3ksE=mbHjbIXk(`<~&&8>3v<;rkn9? zQ!^u>FB$oEVRLzb4TKHy9PGe0iBE%?;13>x`(rGzQKO{F_F{x+{HMVS?jLXRN$$zH z_nh-R_uMQ0czR|$?H%53-`}pgD>XkVb0ydmQ{*OPUoau7uW-2`otm>{c8B!Rx6@jB zNva^OzMN=oj3?E|n@Lq^OsD*fF}XoWv<9O}k}FO7T7$ef(G+h;CR(FOHJ!RIe8;Sr zHASEu>57)1%Qc7PiQM_FGi84i(aHxxUTS|R;HB}04L9~IHZlLv9QhwJ877uE_7{CI8~su{J)6UJ$IsB8Fjht20iMc;*to%fyZsgr4H(zFsX1wh+*fG8Cv_4 z&yCtu4yvCv!B(3XTkXJn#=+4t2fb@7L_!*_hd6eZ>-e*rBf8dsw2ot9osFSqB@|R> z)KlSSbm2K4!{mAip$$4F1o29a9|g5lI;N{6Y~LthY@-2blZE2VCZ;xPh*azNtJ*-{ z76~jYAu6y1E4CV#60~o#u%X7lwBX?O91iU;spk2BoA%fG8HRV-=&Uoae3yZ%yEv*| zFh^btxUupj9hU_4QVy{_8ElO>Sie`o$-NwlWDUn)i;FlF!;I!^$p=`2{YPc((O`vvj%69wM$RY6xl|4Fs=&>-+t5ewroYC1n z&alj|=$0Wg79GxE;Sn9@1l9dIe(tyF{D8!;=$H_4Orw$y9frjxIQj(h1`Ui2as-Af z+!`{_dy=EzltJUCEQU7Iz#|`JaPP2L|!bL&AvMKLVp{?YCXw3Vci_Z0bAqL=^FNM^ui#h83D(s<~ z-)0!D*$!R3EDqfG&T-Q(-v_)Xn$&1uQY0I{mZAQsP(HH1nsns4P?VR|>2OwD>-^ou k?i)5rr*HdHa~lb%7 delta 2730 zcmZ8jZA?{l7zgeR$M7x;ms(=WmI`?(9Vsb?07LQRBK9I1b!4~*KXAhGWf7gt@d4K2 zOyzgUT>g!P_?AZ_+O*g)@k2`P6sFkbcEp0U+B$1}aaP{Z{U6-({E1Keo|oVA`hV{E z=#S9w-O$QC;jZ#~DZ!r}U(_*s$F{od^^MK>4fRb%{m!?W^S3uOHa9fA8Sj`@b^kxa zb6<>?`E&Z({+u&CzI9tjLM@z<(!c8wEliTAlzcHS$`X;5l#I?7X&LvuR@r#(Nt;jt zxeF5HZ>J`$7c8_>N$=y@BA<|n3%MpC2U?y(zKKxM_n*9p(DeFbRg)R&sr_@Gu4OhC zEzh{*@1tS~bK7`!sZDH}%;cA)8vA;9tiU6EMAmh$Ai{O|$XKqj-C1r^BpW@2jC@o* z$Cf^{6)MVG$;iR1B8ON^TrcA44Q$d3(pfmKS%eI%FJ_&ObH&VQp!a#!xp=6=B|jab zB|0G!MWrTHoFhB(RcTHtNg`5mqb$Nb(lNG*{VkNdU=f=IS3w49$~g-ImlR~7U^V;c z7+lSqI_9lmB+#-(Py`3FD;z>LMk;JVCR*2;ge**~zGAH?s}apb+k=EV^dJc z2DTIs8<<64MU0VypJEPi3dAc}C$MBAqXfR+m>^3VSE_g?qjKlo*%VEq2?R6geJO`0 z;Ns%TF8K@WeTBIN7H?)`U}&>JmNu4E|1Z*5b(FW;LRJlT%z{u*0(q};&K?%N<`J)t zuGEljNGcYl*#Z+{KwFcGc%e&HB>+@ZS$=&OGJ;s$g7_H}P5bWlmHzK^P zy5u;~pfiV%9O;dMZM5{Hq{qL(Q%j`x|mX$95Y$AzQ|n*{obN z3xn@+CzCyB;W~q>GSCuX|KP@6HnlM2VB&#R?o)EFTltMf<8Wo%eGTFIh*nx)ntSd1AqP`TL;qUJ`itm1j__$S;26LsA@C0|h{^%z?Dx8%ECZl4bthdyCT4wR zDk!cX3o}kxq_c4N6i+K6tA5Iks4)vqb4&*#rycV3(0PV4aM1KQ>yme@k86p@?H%fi z@b<>!_TKn1#@nmoiL*L!>)4|p7v5Q(WbhVFo>SgJOy+%QKzZdsB{Lmmi-Wy-{Jiqp z=*S$3zfoRL0{;#sXaX^r_1%jx&f1f4%D?rvKR)JP_Q@lN`rwcf)t52me&_SG2)@5E z+^BjjmR;q|3po0(Dl_nK;YW{RXqibyaZSslUfH;L%O?Hgo{uVfZejd3&p4>zt)G<| mTvU$n?znh#oKXV5jZb7Izt$!{)*@N`;a_KDh3nem`TqeXFUd3j diff --git a/resources/syrialandmap.p b/resources/syrialandmap.p index 1b5cc168247a535baffa54b4608f58b4052dedee..0d11a3c2fd6354c6511f9a482b2cbb826af2ef48 100644 GIT binary patch delta 573 zcmY+BOK1~e5XX1Ew59<|AqG+Fs!*{H&4L$8)F`$VQ5v;@>Oo`K#%&VJW84 zr6Ie}I_s+t5d{S?U>ztuG)PaL7PKG;60IJU;7LS9^o!==zz6gA&3~Br9=%|nm)Y2O z!;RH@!e28y5m{BFOjMCGN=k~$iSw$QvcmC?(k`Md*jJ_PHFnV*W>Y!K01B|)`I2R698J!&r06sfarc0;G zjdVEV1spwBrrx2DgPsigfxd=KhJ_KGJP{l4Q?y7J6B#XCXm-wqAy>hk9n1EUf}GkVPdhBjTq4{c4XqSBf=0TGIp4wj@S6@yV)k;;Gxh7{?TqM`(Rr7@CV z+iBH1t%3#w7wTdbC4#FUu5>e25bJ6dy6Hl)(}jzoxzF(KYgY5lJLlYU?hN_)-t+Q< zXK=P<`PmB>|7qqz=Z(qKbY?0a&1Q0X=H~T$bUHVc&*rX~3)_;-Com74H)B?CwX_;+ zPibb~q!)pNyE?J`th?Pz|351pm#g}EhvE^4?rtFKyL93NkQ46=5Jy8!vRiZen?7+J ztlhde+0Y%bg(E}uMu?FkN3QH)q_^OEk0lfpoVd8RLKAta{{2!a6Nx$! zXq~1fkh7LZ5Qk?DC8a!dSrO4l zp<%KOO`~Kg&KOClv;_lm6w-!Ad~XaoGEB^{Q8AyfX+{MuX6bE&QU5y|rXGP{0|{OY z1cgT!J$mkh$)g5CtR^Np@P|2q&EL!VjPzc3&!e+aPYW&==nLomfxD8w1(Bj9{26>J zQX>n~jNP*+4Fh+H3AO< Z!qb(%Z5hpM{;m0|Zyz7=x1`Eu^dIbguu%X2 diff --git a/resources/tools/generate_landmap.py b/resources/tools/generate_landmap.py index 1812ac4b..7e1a9f4b 100644 --- a/resources/tools/generate_landmap.py +++ b/resources/tools/generate_landmap.py @@ -2,6 +2,9 @@ import pickle from dcs.mission import Mission from shapely import geometry +from shapely.geometry import MultiPolygon + +from game.theater.landmap import Landmap for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]: print("Terrain " + terrain) @@ -29,4 +32,6 @@ for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]: with open("../{}landmap.p".format(terrain), "wb") as f: print(len(inclusion_zones), len(exclusion_zones), len(seas_zones)) - pickle.dump((inclusion_zones, exclusion_zones, seas_zones), f) + pickle.dump(Landmap(MultiPolygon(inclusion_zones), + MultiPolygon(exclusion_zones), + MultiPolygon(seas_zones)), f)