Constrain front lines better.

Holes in the inclusion zone are defined by exclusion zones, not by holes
in the inclusion zone. Add a cached property for the inclusion zone that
is not also sea or exclusion zone and use that boundary instead.
This commit is contained in:
Dan Albert 2020-12-24 13:50:29 -08:00
parent aafd09569c
commit 10debbc286
9 changed files with 52 additions and 10 deletions

View File

@ -1,5 +1,6 @@
from dataclasses import dataclass
import pickle
from functools import cached_property
from typing import Optional, Tuple, Union
import logging
@ -13,6 +14,18 @@ class Landmap:
exclusion_zones: MultiPolygon
sea_zones: MultiPolygon
def __post_init__(self):
if not self.inclusion_zones.is_valid:
raise RuntimeError("Inclusion zones not valid")
if not self.exclusion_zones.is_valid:
raise RuntimeError("Exclusion zones not valid")
if not self.sea_zones.is_valid:
raise RuntimeError("Sea zones not valid")
@cached_property
def inclusion_zone_only(self) -> MultiPolygon:
return self.inclusion_zones - self.exclusion_zones - self.sea_zones
def load_landmap(filename: str) -> Optional[Landmap]:
try:

View File

@ -93,7 +93,7 @@ class Conflict:
line = LineString([p0, p1])
intersection = line.intersection(
theater.landmap.inclusion_zones.boundary)
theater.landmap.inclusion_zone_only.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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,37 @@
import pickle
from functools import singledispatch
from dcs.mission import Mission
from shapely import geometry
from shapely.geometry import MultiPolygon
from shapely.geometry import GeometryCollection, MultiPolygon, Polygon
from shapely.ops import unary_union
from game.theater.landmap import Landmap
@singledispatch
def to_multipoly(obj) -> MultiPolygon:
raise NotImplementedError(
f"to_multipoly not implemented for {obj.__class__.__name__}")
@to_multipoly.register
def _poly_to_multipoly(obj: Polygon) -> MultiPolygon:
return MultiPolygon([obj])
@to_multipoly.register
def _multipoly_to_multipoly(obj: MultiPolygon) -> MultiPolygon:
return obj
@to_multipoly.register
def _geometry_collection_to_multipoly(obj: GeometryCollection) -> MultiPolygon:
if obj.is_empty:
return MultiPolygon()
raise RuntimeError(
f"Not sure how to convert collection to multipoly: {obj.wkt}")
for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]:
print("Terrain " + terrain)
m = Mission()
@ -19,19 +45,22 @@ for terrain in ["cau", "nev", "syria", "channel", "normandy", "gulf"]:
if terrain == "cau" and inclusion_zones:
# legacy
exclusion_zones.append(geometry.Polygon(zone))
exclusion_zones.append(Polygon(zone))
else:
poly = Polygon(zone)
if not poly.is_valid:
raise RuntimeError(f"{plane_group} is invalid")
if plane_group.units[0].type == "F-15C":
exclusion_zones.append(geometry.Polygon(zone))
exclusion_zones.append(poly)
else:
inclusion_zones.append(geometry.Polygon(zone))
inclusion_zones.append(poly)
for ship_group in m.country("USA").ship_group:
zone = [(x.position.x, x.position.y) for x in ship_group.points]
seas_zones.append(geometry.Polygon(zone))
seas_zones.append(Polygon(zone))
with open("../{}landmap.p".format(terrain), "wb") as f:
print(len(inclusion_zones), len(exclusion_zones), len(seas_zones))
pickle.dump(Landmap(MultiPolygon(inclusion_zones),
MultiPolygon(exclusion_zones),
MultiPolygon(seas_zones)), f)
pickle.dump(Landmap(to_multipoly(unary_union(inclusion_zones)),
to_multipoly(unary_union(exclusion_zones)),
to_multipoly(unary_union(seas_zones))), f)