libera_utils.footprint_matching.geometry.bounding_box_from_points_batch#

libera_utils.footprint_matching.geometry.bounding_box_from_points_batch(center_lat_deg: ndarray, center_lon_deg: ndarray, lats: ndarray, lons: ndarray, truncated: ndarray) → list[BoundingBox]#

Build one lat/lon bounding box per footprint from its boundary points.

This is the box-assembly step shared by two producers:

  • the radiometer path (compute_footprint_bounding_boxes()), which passes the ray-traced PSF perimeter samples, and

  • the camera path (camera segmentation in the Camera Cloud Fraction algorithm), which passes the four corner pixels of a pseudo-footprint’s pixel block.

center_lat_deg/center_lon_deg is each footprint’s anchor (the radiometer boresight, or the camera block’s center pixel) and is used only for the pole-enclosure reach test, not for the box extent.

Handles the three structural edge cases:

  • Pole enclosure: if the footprint reaches a pole, all meridians are inside it, so longitude spans the full [-180, 180] and the bounding latitude is pinned to +/- 90. Detected when the surface distance from the anchor to the pole is within the footprint’s reach (the max anchor-to-boundary distance).

  • Dateline crossing: detected by comparing the longitude span in [-180, 180] vs in [0, 360); the smaller span wins. When it wraps, we return the [0, 360) representation (lon_max > 180) and set wraps_dateline.

  • Polar advisory: boxes touching very high latitudes are flagged is_polar so downstream code knows the rectangular box is a coarse over-approximation.

Parameters:
  • center_lat_deg (np.ndarray) – (N,) footprint anchors, degrees.

  • center_lon_deg (np.ndarray) – (N,) footprint anchors, degrees.

  • lats (np.ndarray) – (N, S) boundary points, degrees.

  • lons (np.ndarray) – (N, S) boundary points, degrees.

  • truncated (np.ndarray) – (N,) limb-truncation flags, carried onto the boxes.

Returns:

One box per footprint, in input order.

Return type:

list[BoundingBox]