@@ -222,127 +222,55 @@ def _convert_state(state: list[Any]) -> dict[str, Any]:
222222 return dict (zip (keys , state , strict = True ))
223223
224224 @staticmethod
225- # pylint: disable=too-many-locals
226- def calculate_point (
225+ def get_bounding_box (
227226 latitude : float ,
228227 longitude : float ,
229- distance : float ,
230- degrees : float ,
231- ) -> tuple [float , float ]:
232- """Calculate a point from an origin point, direction in degrees and distance."""
233- # ruff: noqa: N806
234- # pylint: disable=invalid-name
235- pi_d4 = math .atan (1.0 )
236- two_pi = pi_d4 * 8.0
237- latitude = latitude * pi_d4 / 45.0
238- longitude = longitude * pi_d4 / 45.0
239- degrees = degrees * pi_d4 / 45.0
240- if degrees < 0.0 :
241- degrees = degrees + two_pi
242- if degrees > two_pi :
243- degrees = degrees - two_pi
244- axis_a = 6378137
245- flattening = 1 / 298.257223563
246- axis_b = axis_a * (1.0 - flattening )
247- tan_u1 = (1 - flattening ) * math .tan (latitude )
248- u1 = math .atan (tan_u1 )
249- sigma1 = math .atan2 (tan_u1 , math .cos (degrees ))
250- sinalpha = math .cos (u1 ) * math .sin (degrees )
251- cosalpha_sq = 1.0 - sinalpha * sinalpha
252- u2 = cosalpha_sq * (axis_a * axis_a - axis_b * axis_b ) / (axis_b * axis_b )
253- A = 1.0 + (u2 / 16384 ) * (4096 + u2 * (- 768 + u2 * (320 - 175 * u2 )))
254- B = (u2 / 1024 ) * (256 + u2 * (- 128 + u2 * (74 - 47 * u2 )))
255- # Starting with the approx
256- sigma = distance / (axis_b * A )
257- last_sigma = 2.0 * sigma + 2.0 # something impossible
258-
259- # Iterate the following 3 eqs until no sig change in sigma
260- # two_sigma_m , delta_sigma
261- while abs ((last_sigma - sigma ) / sigma ) > 1.0e-9 :
262- two_sigma_m = 2 * sigma1 + sigma
263- delta_sigma = (
264- B
265- * math .sin (sigma )
266- * (
267- math .cos (two_sigma_m )
268- + (B / 4 )
269- * (
270- math .cos (sigma )
271- * (
272- - 1
273- + 2 * math .pow (math .cos (two_sigma_m ), 2 )
274- - (B / 6 )
275- * math .cos (two_sigma_m )
276- * (- 3 + 4 * math .pow (math .sin (sigma ), 2 ))
277- * (- 3 + 4 * math .pow (math .cos (two_sigma_m ), 2 ))
278- )
279- )
280- )
281- )
282- last_sigma = sigma
283- sigma = (distance / (axis_b * A )) + delta_sigma
284- phi2 = math .atan2 (
285- (
286- math .sin (u1 ) * math .cos (sigma )
287- + math .cos (u1 ) * math .sin (sigma ) * math .cos (degrees )
288- ),
289- (
290- (1 - flattening )
291- * math .sqrt (
292- math .pow (sinalpha , 2 )
293- + pow (
294- math .sin (u1 ) * math .sin (sigma )
295- - math .cos (u1 ) * math .cos (sigma ) * math .cos (degrees ),
296- 2 ,
297- ),
298- )
299- ),
228+ radius : float ,
229+ ) -> BoundingBox :
230+ """Get bounding box from radius and a point."""
231+ half_side_in_km = abs (radius ) / 1000
232+
233+ lat = math .radians (latitude )
234+ lon = math .radians (longitude )
235+
236+ approx_earth_radius = 6371
237+ hypotenuse_distance = math .sqrt (2 * (math .pow (half_side_in_km , 2 )))
238+
239+ lat_min = math .asin (
240+ math .sin (lat ) * math .cos (hypotenuse_distance / approx_earth_radius )
241+ + math .cos (lat )
242+ * math .sin (hypotenuse_distance / approx_earth_radius )
243+ * math .cos (225 * (math .pi / 180 )),
300244 )
301- lembda = math .atan2 (
302- ( math .sin (sigma ) * math .sin ( degrees )),
303- (
304- math . cos ( u1 ) * math .cos (sigma )
305- - math .sin ( u1 ) * math . sin ( sigma ) * math . cos ( degrees )
306- ),
245+ lon_min = lon + math .atan2 (
246+ math .sin (225 * ( math .pi / 180 ))
247+ * math . sin ( hypotenuse_distance / approx_earth_radius )
248+ * math .cos (lat ),
249+ math .cos ( hypotenuse_distance / approx_earth_radius )
250+ - math . sin ( lat ) * math . sin ( lat_min ),
307251 )
308- C = (flattening / 16 ) * cosalpha_sq * (4 + flattening * (4 - 3 * cosalpha_sq ))
309- omega = lembda - (1 - C ) * flattening * sinalpha * (
310- sigma
311- + C
312- * math .sin (sigma )
313- * (
314- math .cos (two_sigma_m )
315- + C * math .cos (sigma ) * (- 1 + 2 * math .pow (math .cos (two_sigma_m ), 2 ))
316- )
252+
253+ lat_max = math .asin (
254+ math .sin (lat ) * math .cos (hypotenuse_distance / approx_earth_radius )
255+ + math .cos (lat )
256+ * math .sin (hypotenuse_distance / approx_earth_radius )
257+ * math .cos (45 * (math .pi / 180 )),
317258 )
318- lembda2 = longitude + omega
319- math .atan2 (
320- sinalpha ,
321- (
322- - math .sin (u1 ) * math .sin (sigma )
323- + math .cos (u1 ) * math .cos (sigma ) * math .cos (degrees )
324- ),
259+ lon_max = lon + math .atan2 (
260+ math .sin (45 * (math .pi / 180 ))
261+ * math .sin (hypotenuse_distance / approx_earth_radius )
262+ * math .cos (lat ),
263+ math .cos (hypotenuse_distance / approx_earth_radius )
264+ - math .sin (lat ) * math .sin (lat_max ),
325265 )
326- phi2 = phi2 * 45.0 / pi_d4
327- lembda2 = lembda2 * 45.0 / pi_d4
328- return phi2 , lembda2
329266
330- @staticmethod
331- def get_bounding_box (
332- latitude : float ,
333- longitude : float ,
334- radius : float ,
335- ) -> BoundingBox :
336- """Get bounding box from radius and a point."""
337- north = OpenSky .calculate_point (latitude , longitude , radius , 0 )
338- east = OpenSky .calculate_point (latitude , longitude , radius , 90 )
339- south = OpenSky .calculate_point (latitude , longitude , radius , 180 )
340- west = OpenSky .calculate_point (latitude , longitude , radius , 270 )
267+ rad2deg = math .degrees
268+
341269 return BoundingBox (
342- min_latitude = min ( north [ 0 ], south [ 0 ] ),
343- max_latitude = max ( north [ 0 ], south [ 0 ] ),
344- min_longitude = min ( east [ 1 ], west [ 1 ] ),
345- max_longitude = max ( east [ 1 ], west [ 1 ] ),
270+ min_latitude = rad2deg ( lat_min ),
271+ max_latitude = rad2deg ( lat_max ),
272+ min_longitude = rad2deg ( lon_min ),
273+ max_longitude = rad2deg ( lon_max ),
346274 )
347275
348276 async def close (self ) -> None :
0 commit comments