mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Add fallback locations for join zones.
It's rare with the current 5NM buffer around the origin, but if we use the hold distance as the buffer like we maybe should it's possible for the preferred join locations to fall entirely within the home zone. In that case, fall back to a location within the max-turn-zone that's outside the home zone and is nearest the IP.
This commit is contained in:
parent
2580fe6b79
commit
e22e8669e1
@ -11,7 +11,6 @@ from shapely.geometry import (
|
||||
MultiLineString,
|
||||
)
|
||||
|
||||
from game.theater import ConflictTheater
|
||||
from game.utils import nautical_miles
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -26,12 +25,7 @@ class JoinZoneGeometry:
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
target: Point,
|
||||
home: Point,
|
||||
ip: Point,
|
||||
coalition: Coalition,
|
||||
theater: ConflictTheater,
|
||||
self, target: Point, home: Point, ip: Point, coalition: Coalition
|
||||
) -> None:
|
||||
# Normal join placement is based on the path from home to the IP. If no path is
|
||||
# found it means that the target is on a direct path. In that case we instead
|
||||
@ -82,14 +76,28 @@ class JoinZoneGeometry:
|
||||
]
|
||||
)
|
||||
|
||||
permissible_lines = ip_direction_limit_wedge.intersection(
|
||||
permissible_zones = ip_direction_limit_wedge.difference(
|
||||
self.excluded_zones
|
||||
).difference(self.home_bubble)
|
||||
if permissible_zones.is_empty:
|
||||
permissible_zones = MultiPolygon([])
|
||||
if not isinstance(permissible_zones, MultiPolygon):
|
||||
permissible_zones = MultiPolygon([permissible_zones])
|
||||
self.permissible_zones = permissible_zones
|
||||
|
||||
preferred_lines = ip_direction_limit_wedge.intersection(
|
||||
self.excluded_zones.boundary
|
||||
).difference(self.home_bubble)
|
||||
|
||||
if not isinstance(permissible_lines, MultiLineString):
|
||||
permissible_lines = MultiLineString([permissible_lines])
|
||||
self.permissible_lines = permissible_lines
|
||||
if preferred_lines.is_empty:
|
||||
preferred_lines = MultiLineString([])
|
||||
if not isinstance(preferred_lines, MultiLineString):
|
||||
preferred_lines = MultiLineString([preferred_lines])
|
||||
self.preferred_lines = preferred_lines
|
||||
|
||||
def find_best_join_point(self) -> Point:
|
||||
join, _ = shapely.ops.nearest_points(self.permissible_lines, self.home)
|
||||
if self.preferred_lines.is_empty:
|
||||
join, _ = shapely.ops.nearest_points(self.permissible_zones, self.ip)
|
||||
else:
|
||||
join, _ = shapely.ops.nearest_points(self.preferred_lines, self.home)
|
||||
return Point(join.x, join.y)
|
||||
|
||||
@ -975,7 +975,6 @@ class FlightPlanBuilder:
|
||||
package_airfield.position,
|
||||
ingress_point,
|
||||
self.coalition,
|
||||
self.theater,
|
||||
).find_best_join_point()
|
||||
|
||||
# And the split point based on the best route from the IP. Since that's no
|
||||
|
||||
@ -869,7 +869,8 @@ class JoinZonesJs(QObject):
|
||||
targetBubbleChanged = Signal()
|
||||
ipBubbleChanged = Signal()
|
||||
excludedZonesChanged = Signal()
|
||||
permissibleLinesChanged = Signal()
|
||||
permissibleZonesChanged = Signal()
|
||||
preferredLinesChanged = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -877,14 +878,16 @@ class JoinZonesJs(QObject):
|
||||
target_bubble: LeafletPoly,
|
||||
ip_bubble: LeafletPoly,
|
||||
excluded_zones: list[LeafletPoly],
|
||||
permissible_lines: list[list[LeafletLatLon]],
|
||||
permissible_zones: list[LeafletPoly],
|
||||
preferred_lines: list[list[LeafletLatLon]],
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self._home_bubble = home_bubble
|
||||
self._target_bubble = target_bubble
|
||||
self._ip_bubble = ip_bubble
|
||||
self._excluded_zones = excluded_zones
|
||||
self._permissible_lines = permissible_lines
|
||||
self._permissible_zones = permissible_zones
|
||||
self._preferred_lines = preferred_lines
|
||||
|
||||
@Property(list, notify=homeBubbleChanged)
|
||||
def homeBubble(self) -> LeafletPoly:
|
||||
@ -902,13 +905,17 @@ class JoinZonesJs(QObject):
|
||||
def excludedZones(self) -> list[LeafletPoly]:
|
||||
return self._excluded_zones
|
||||
|
||||
@Property(list, notify=permissibleLinesChanged)
|
||||
def permissibleLines(self) -> list[list[LeafletLatLon]]:
|
||||
return self._permissible_lines
|
||||
@Property(list, notify=permissibleZonesChanged)
|
||||
def permissibleZones(self) -> list[LeafletPoly]:
|
||||
return self._permissible_zones
|
||||
|
||||
@Property(list, notify=preferredLinesChanged)
|
||||
def preferredLines(self) -> list[list[LeafletLatLon]]:
|
||||
return self._preferred_lines
|
||||
|
||||
@classmethod
|
||||
def empty(cls) -> JoinZonesJs:
|
||||
return JoinZonesJs([], [], [], [], [])
|
||||
return JoinZonesJs([], [], [], [], [], [])
|
||||
|
||||
@classmethod
|
||||
def for_flight(cls, flight: Flight, game: Game) -> JoinZonesJs:
|
||||
@ -919,15 +926,14 @@ class JoinZonesJs(QObject):
|
||||
if flight.package.waypoints is None:
|
||||
return JoinZonesJs.empty()
|
||||
ip = flight.package.waypoints.ingress
|
||||
geometry = JoinZoneGeometry(
|
||||
target.position, home.position, ip, game.blue, game.theater
|
||||
)
|
||||
geometry = JoinZoneGeometry(target.position, home.position, ip, game.blue)
|
||||
return JoinZonesJs(
|
||||
shapely_poly_to_leaflet_points(geometry.home_bubble, game.theater),
|
||||
shapely_poly_to_leaflet_points(geometry.target_bubble, game.theater),
|
||||
shapely_poly_to_leaflet_points(geometry.ip_bubble, game.theater),
|
||||
shapely_to_leaflet_polys(geometry.excluded_zones, game.theater),
|
||||
shapely_lines_to_leaflet_points(geometry.permissible_lines, game.theater),
|
||||
shapely_to_leaflet_polys(geometry.permissible_zones, game.theater),
|
||||
shapely_lines_to_leaflet_points(geometry.preferred_lines, game.theater),
|
||||
)
|
||||
|
||||
|
||||
@ -937,7 +943,7 @@ class HoldZonesJs(QObject):
|
||||
joinBubbleChanged = Signal()
|
||||
excludedZonesChanged = Signal()
|
||||
permissibleZonesChanged = Signal()
|
||||
permissibleLinesChanged = Signal()
|
||||
preferredLinesChanged = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -946,7 +952,7 @@ class HoldZonesJs(QObject):
|
||||
join_bubble: LeafletPoly,
|
||||
excluded_zones: list[LeafletPoly],
|
||||
permissible_zones: list[LeafletPoly],
|
||||
permissible_lines: list[list[LeafletLatLon]],
|
||||
preferred_lines: list[list[LeafletLatLon]],
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self._home_bubble = home_bubble
|
||||
@ -954,7 +960,7 @@ class HoldZonesJs(QObject):
|
||||
self._join_bubble = join_bubble
|
||||
self._excluded_zones = excluded_zones
|
||||
self._permissible_zones = permissible_zones
|
||||
self._permissible_lines = permissible_lines
|
||||
self._preferred_lines = preferred_lines
|
||||
|
||||
@Property(list, notify=homeBubbleChanged)
|
||||
def homeBubble(self) -> LeafletPoly:
|
||||
@ -976,9 +982,9 @@ class HoldZonesJs(QObject):
|
||||
def permissibleZones(self) -> list[LeafletPoly]:
|
||||
return self._permissible_zones
|
||||
|
||||
@Property(list, notify=permissibleLinesChanged)
|
||||
def permissibleLines(self) -> list[list[LeafletLatLon]]:
|
||||
return self._permissible_lines
|
||||
@Property(list, notify=preferredLinesChanged)
|
||||
def preferredLines(self) -> list[list[LeafletLatLon]]:
|
||||
return self._preferred_lines
|
||||
|
||||
@classmethod
|
||||
def empty(cls) -> HoldZonesJs:
|
||||
@ -1003,7 +1009,7 @@ class HoldZonesJs(QObject):
|
||||
shapely_poly_to_leaflet_points(geometry.join_bubble, game.theater),
|
||||
shapely_to_leaflet_polys(geometry.excluded_zones, game.theater),
|
||||
shapely_to_leaflet_polys(geometry.permissible_zones, game.theater),
|
||||
[], # shapely_to_leaflet_polys(geometry.permissible_lines, game.theater),
|
||||
shapely_lines_to_leaflet_points(geometry.preferred_lines, game.theater),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -1066,7 +1066,14 @@ function drawJoinZones() {
|
||||
}).addTo(joinZones);
|
||||
}
|
||||
|
||||
for (const line of game.joinZones.permissibleLines) {
|
||||
for (const zone of game.joinZones.permissibleZones) {
|
||||
L.polygon(zone, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
}).addTo(joinZones);
|
||||
}
|
||||
|
||||
for (const line of game.joinZones.preferredLines) {
|
||||
L.polyline(line, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
@ -1114,6 +1121,13 @@ function drawHoldZones() {
|
||||
interactive: false,
|
||||
}).addTo(holdZones);
|
||||
}
|
||||
|
||||
for (const line of game.holdZones.preferredLines) {
|
||||
L.polyline(line, {
|
||||
color: Colors.Green,
|
||||
interactive: false,
|
||||
}).addTo(holdZones);
|
||||
}
|
||||
}
|
||||
|
||||
function drawInitialMap() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user