Files
2026-06-20 06:41:40 -04:00

157 lines
5.6 KiB
Python

SWANSEA_FRZ_POLYGONS = [
{
"name": "EGR1U003A SWANSEA",
"coordinates": [
[51.6385691199, -4.0677777778],
[51.6383925433, -4.0732789905],
[51.6378646894, -4.0787217619],
[51.6369911656, -4.0840482758],
[51.6357812508, -4.0892019586],
[51.6342477966, -4.0941280843],
[51.6324070894, -4.0987743581],
[51.6302786768, -4.1030914745],
[51.6278851591, -4.1070336417],
[51.6252519474, -4.1105590688],
[51.6224069933, -4.1136304084],
[51.6193804903, -4.1162151518],
[51.6162045529, -4.1182859716],
[51.6129128741, -4.1198210079],
[51.6095403677, -4.1208040969],
[51.606122797, -4.1212249367],
[51.6026963949, -4.1210791924],
[51.5992974802, -4.120368536],
[51.595962072, -4.1191006239],
[51.592725509, -4.1172890099],
[51.5896220749, -4.1149529973],
[51.5866846367, -4.1121174298],
[51.5839442973, -4.1088124245],
[51.5814300673, -4.1050730509],
[51.5791685587, -4.1009389566],
[51.5771837053, -4.0964539477],
[51.5754965099, -4.0916655245],
[51.5741248235, -4.0866243798],
[51.5730831575, -4.0813838645],
[51.572382531, -4.0759994259],
[51.5720303553, -4.0705280237],
[51.5720303553, -4.0650275318],
[51.572382531, -4.0595561297],
[51.5730831575, -4.054171691],
[51.5741248235, -4.0489311758],
[51.5754965099, -4.0438900311],
[51.5771837053, -4.0391016078],
[51.5791685587, -4.0346165989],
[51.5814300673, -4.0304825047],
[51.5839442973, -4.026743131],
[51.5866846367, -4.0234381258],
[51.5896220749, -4.0206025582],
[51.592725509, -4.0182665456],
[51.595962072, -4.0164549317],
[51.5992974802, -4.0151870195],
[51.6026963949, -4.0144763632],
[51.606122797, -4.0143306189],
[51.6095403677, -4.0147514587],
[51.6129128741, -4.0157345476],
[51.6162045529, -4.017269584],
[51.6193804903, -4.0193404037],
[51.6224069933, -4.0219251472],
[51.6252519474, -4.0249964868],
[51.6278851591, -4.0285219138],
[51.6302786768, -4.0324640811],
[51.6324070894, -4.0367811974],
[51.6342477966, -4.0414274713],
[51.6357812508, -4.0463535969],
[51.6369911656, -4.0515072798],
[51.6378646894, -4.0568337937],
[51.6383925433, -4.0622765651],
[51.6385691199, -4.0677777778],
],
},
{
"name": "EGR1U003B SWANSEA RWY 04",
"coordinates": [
[51.5614305556, -4.1105694444],
[51.5760447778, -4.0933516667],
[51.5775992074, -4.0974772875],
[51.5793789018, -4.1013615228],
[51.5813693889, -4.1049727778],
[51.5667527778, -4.1221888889],
[51.5614305556, -4.1105694444],
],
},
{
"name": "EGR1U003C SWANSEA RWY 22",
"coordinates": [
[51.6483027778, -4.0259555556],
[51.6345286389, -4.0422406389],
[51.632975828, -4.0381074205],
[51.631197314, -4.0342163026],
[51.6292076111, -4.030599],
[51.6429805556, -4.0143111111],
[51.6483027778, -4.0259555556],
],
},
{
"name": "EGR1U003D SWANSEA RWY 10",
"coordinates": [
[51.6016305556, -4.1483194444],
[51.5997253611, -4.1204896111],
[51.602737017, -4.1210842429],
[51.605769878, -4.1212361072],
[51.60879875, -4.1209438611],
[51.6105638889, -4.1467305556],
[51.6016305556, -4.1483194444],
],
},
{
"name": "EGR1U003E SWANSEA RWY 28",
"coordinates": [
[51.5998777778, -3.9918916667],
[51.6014628333, -4.0146683056],
[51.5984676719, -4.015448363],
[51.5955291688, -4.0166629251],
[51.5926717222, -4.0183018333],
[51.5909444444, -3.9934777778],
[51.5998777778, -3.9918916667],
],
},
]
def point_inside_swansea_frz(lat: float, lng: float) -> bool:
"""Return whether a point is inside the Swansea UAS FRZ polygons from the KML source."""
return any(_point_inside_polygon(lat, lng, polygon["coordinates"]) for polygon in SWANSEA_FRZ_POLYGONS)
def swansea_frz_geojson() -> dict:
return {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"name": polygon["name"]},
"geometry": {
"type": "Polygon",
"coordinates": [[
[lng, lat] for lat, lng in polygon["coordinates"]
]],
},
}
for polygon in SWANSEA_FRZ_POLYGONS
],
}
def _point_inside_polygon(lat: float, lng: float, coordinates: list[list[float]]) -> bool:
inside = False
j = len(coordinates) - 1
for i, (point_lat, point_lng) in enumerate(coordinates):
previous_lat, previous_lng = coordinates[j]
intersects = (
(point_lat > lat) != (previous_lat > lat)
and lng < (previous_lng - point_lng) * (lat - point_lat) / (previous_lat - point_lat) + point_lng
)
if intersects:
inside = not inside
j = i
return inside