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