Geometry

Geospatial utilities: coordinate wrapping, haversine distances, UTM transforms, magnetic declination, and coordinate format conversions.

Geodesic geometry utilities.

Coordinate conversions, distance calculations, and geometric operations on the WGS84 ellipsoid. All distance and bearing calculations use Vincenty’s inverse and direct formulae via the pymap3d library.

Geometry references

Vincenty, T. (1975). Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations. Survey Review, 23(176), 88-93. doi:10.1179/sre.1975.23.176.88

Hirsch, M. (2018). PyMap3D: 3-D coordinate conversions for terrestrial and geospace environments. Journal of Open Source Software, 3(23), 580. doi:10.21105/joss.00580

wrap_to_180(lon)[source]

Wrap angle(s) to the range [-180, 180) degrees.

Parameters:

lon (float or array-like) – Angle(s) in degrees.

Returns:

Angle(s) wrapped to [-180, 180).

Return type:

numpy.ndarray or float

wrap_to_360(angle)[source]

Wrap angle(s) to the range [0, 360) degrees.

Parameters:

angle (float or array-like) – Angle(s) in degrees.

Returns:

Angle(s) wrapped to [0, 360).

Return type:

numpy.ndarray

get_timezone(latitude, longitude)[source]

Return the IANA timezone name for a lat/lon (e.g. 'America/Los_Angeles').

Parameters:
  • latitude (float) – Latitude in decimal degrees, in [-90, 90].

  • longitude (float) – Longitude in decimal degrees, in [-180, 180].

Return type:

str

Returns:

IANA timezone name string. Coordinates over open ocean may return an 'Etc/GMT±N' zone.

Raises:
  • HyPlanValueError – If coordinates are out of range or no timezone can be determined for the location.

  • HyPlanRuntimeError – If the optional timezonefinder package is not installed.

calculate_geographic_mean(geometry)[source]

Calculate the geographic mean of coordinates from a Shapely geometry or a list of Shapely geometries using pymap3d.lox.meanm.

Parameters:

geometry (LineString, Polygon, Point, or list) – A single Shapely geometry or a list of Shapely geometries.

Returns:

Geographic mean as a Shapely Point.

Return type:

Point

get_utm_crs(lon, lat)[source]

Determine the UTM CRS for a given WGS84 coordinate.

UTM zones are determined arithmetically from longitude (6° wide) and hemisphere from latitude, so we compute the EPSG code directly instead of querying pyproj’s CRS database — this is both faster and exact.

Parameters:
  • lon (float) – Longitude in decimal degrees (WGS84).

  • lat (float) – Latitude in decimal degrees (WGS84).

Returns:

The appropriate UTM CRS for the coordinate.

Return type:

CRS

get_utm_transforms(geometry)[source]

Get the UTM CRS and transformation functions to/from WGS84 for a Shapely geometry or a list of geometries.

Parameters:

geometry (BaseGeometry or list of BaseGeometry) – A single Shapely geometry object or a list of geometries.

Returns:

Transformation functions:
  • wgs84_to_utm: Function to transform coordinates from WGS84 to UTM.

  • utm_to_wgs84: Function to transform coordinates from UTM to WGS84.

Return type:

Tuple[Callable, Callable]

Raises:

ValueError – If the geometry is invalid, empty, or has no valid centroid.

haversine(lat1, lon1, lat2, lon2, radius=6371000.0)[source]

Calculate the haversine (great-circle) distance between two points.

Accepts scalars or numpy arrays for any of the coordinate arguments, so it works both as a one-off distance and as a vectorized calculation over many candidate points (e.g. an array of airport latitudes against a single query point).

Parameters:
  • lat1 (Union[float, ndarray]) – Latitude of the first point(s) in decimal degrees.

  • lon1 (Union[float, ndarray]) – Longitude of the first point(s) in decimal degrees.

  • lat2 (Union[float, ndarray]) – Latitude of the second point(s) in decimal degrees.

  • lon2 (Union[float, ndarray]) – Longitude of the second point(s) in decimal degrees.

  • radius (float) – Radius of the Earth in meters (default: 6371e3).

Return type:

Union[float, ndarray]

Returns:

Distance(s) in the same unit as radius. Returns a scalar if all inputs are scalars, otherwise a numpy array broadcast to the inputs.

random_points_in_polygon(polygon, k)[source]

Generate k points chosen uniformly at random inside a polygon.

Uses Delaunay triangulation with area-weighted sampling to ensure uniform distribution across the polygon’s interior.

Parameters:
  • polygon (Polygon) – A Shapely Polygon to sample points from.

  • k (int) – Number of random points to generate.

Returns:

List of k Shapely Point objects inside the polygon.

Return type:

list[Point]

minimum_rotated_rectangle(polygon)[source]

Calculate the minimum rotated rectangle of a polygon in WGS84 coordinates.

Parameters:

polygon (Polygon) – Input polygon in WGS84 coordinates. Must be valid.

Returns:

A tuple containing:
  • lat0 (float): Latitude of the rectangle’s centroid.

  • lon0 (float): Longitude of the rectangle’s centroid.

  • azimuth (float): Azimuth of the rectangle in degrees, wrapped to [-180, 180].

  • length (float): Length of the rectangle’s longer side (meters).

  • width (float): Width of the rectangle’s shorter side (meters).

  • mrr_wgs84 (Polygon): Minimum rotated rectangle in WGS84 coordinates.

  • hull_wgs84 (Polygon): Convex hull of the polygon in WGS84 coordinates.

Return type:

tuple

Raises:

ValueError – If the input polygon is invalid or processing fails.

Notes

  • The input polygon is transformed to UTM for accurate geometry calculations.

  • Returns both the rectangle and the convex hull in WGS84 coordinates.

rotated_rectangle(polygon, azimuth)[source]

Compute a rotated bounding rectangle around a Shapely polygon in WGS84 coordinates at a specified azimuth.

Parameters:
  • polygon (Polygon) – Input polygon in WGS84 coordinates. Must be valid.

  • azimuth (float) – Desired azimuth for the bounding rectangle in degrees. Will be wrapped to [-180, 180].

Returns:

The rotated bounding rectangle in WGS84 coordinates.

Return type:

Polygon

Raises:

ValueError – If the input polygon is invalid or if an error occurs during processing.

Notes

  • The input polygon is transformed to UTM for accurate geometry calculations.

  • The bounding rectangle is rotated to align with the specified azimuth.

  • The result is returned in WGS84 coordinates.

rectangle_dimensions(rectangle, azimuth=None)[source]

Extract centroid, length, width and orientation from a rotated rectangle.

Given a 4-sided polygon (e.g. the output of minimum_rotated_rectangle() or rotated_rectangle()), this returns the centroid, the orientation in degrees, and the lengths of the long and short edges in meters.

If azimuth is None, the rectangle’s orientation is taken from the longer edge. If azimuth is supplied, length_m is the side most aligned with that azimuth and width_m is the perpendicular side; the returned orientation is still wrapped to [-180, 180].

Parameters:
  • rectangle (Polygon) – A Shapely Polygon assumed to be a (rotated) rectangle in WGS84 coordinates.

  • azimuth (Optional[float]) – Optional preferred orientation in degrees from true north.

Return type:

Tuple[float, float, float, float, float]

Returns:

Tuple (lat0, lon0, azimuth, length_m, width_m).

translate_polygon(polygon, distance, azimuth)[source]

Translate a Shapely polygon by a specified distance in a given rotational direction.

Parameters:
  • polygon (Polygon) – The input Shapely polygon to be translated

  • distance (float) – Distance to translate the polygon (in the same units as the polygon’s coordinates).

  • azimuth (float) – Angle of translation in degrees, measured clockwise from north.

Returns:

The translated Shapely polygon.

Return type:

Polygon

buffer_polygon_along_azimuth(polygon, along_track_distance, across_track_distance, azimuth)[source]

Translate a Shapely polygon in both a specified direction and its opposite, then compute the convex hull of the union of the two translated polygons.

Parameters:
  • polygon (Polygon) – The input Shapely polygon to be buffered in WGS84 coordinates. Must be valid.

  • distance (ureg.Quantity) – Distance to translate the polygon. Must be a positive length Quantity.

  • azimuth (float) – Angle of translation in degrees, measured clockwise from north.

  • along_track_distance (float)

  • across_track_distance (float)

Returns:

The convex hull of the union of the two translated polygons in WGS84 coordinates.

Return type:

Polygon

Raises:

ValueError – If the input polygon is invalid or if distance is not a valid length.

Notes

  • The input polygon is transformed to UTM for accurate geometry calculations.

  • The resulting convex hull is returned in WGS84 coordinates.

process_linestring(linestring)[source]

Process a LineString containing WGS84 coordinates to compute latitudes, longitudes, azimuths, and cumulative along-track distances.

Parameters:

linestring (LineString) – A shapely LineString containing WGS84 coordinates.

Returns:

A tuple containing:
  • numpy.ndarray: Latitudes of the track points.

  • numpy.ndarray: Longitudes of the track points.

  • numpy.ndarray: Azimuths between consecutive points.

  • numpy.ndarray: Cumulative along-track distances in meters.

Return type:

tuple

magnetic_declination(lat, lon, alt_m=0, date=None)[source]

Return magnetic declination in degrees (positive = east).

Uses the optional geomag library (WMM model). geomag is not on conda-forge, so it is an optional dependency — install it via pip install hyplan[mag] (or pip install geomag) when magnetic headings are required.

Parameters:
  • lat (float) – Latitude in decimal degrees.

  • lon (float) – Longitude in decimal degrees.

  • alt_m (float) – Altitude in meters above WGS-84 ellipsoid (default 0).

  • date (date | None) – Date for the calculation (default today).

Return type:

float

Returns:

Declination in degrees. Add to true heading to get magnetic heading would give the wrong sign — use true_to_magnetic() instead.

true_to_magnetic(heading, declination)[source]

Convert true heading to magnetic heading.

magnetic = (360 + true - declination) % 360

Parameters:
  • heading (float) – True heading in degrees.

  • declination (float) – Magnetic declination in degrees (positive = east).

Return type:

float

Returns:

Magnetic heading in degrees [0, 360).

dd_to_ddm(lat, lon)[source]

Decimal degrees → 'DD MM.MM' (e.g. '37 24.21', '-122 03.45').

This is the MovingLines 'DD MM' / pilot_format style.

Return type:

Tuple[str, str]

Parameters:
dd_to_ddms(lat, lon)[source]

Decimal degrees → 'DD MM SS.S' (e.g. '37 24 12.5').

Return type:

Tuple[str, str]

Parameters:
dd_to_nddmm(lat, lon)[source]

Decimal degrees → 'N37 24.21' / 'W122 03.45' (Honeywell FMS style).

Return type:

Tuple[str, str]

Parameters:
dd_to_foreflight_oneline(lat, lon)[source]

Decimal degrees → 'N3724.210/W12203.450' (ForeFlight one-liner).

Return type:

str

Parameters: