Source code for sargeom.coordinates.transforms
import numpy as np
[docs]
class LambertConicConformal:
"""
Lambert Conic Conformal projection class.
This class implements the Lambert Conic Conformal projection, a conformal
map projection that preserves angles and is commonly used for mapping
regions in the middle latitudes with primarily east-west extent.
Parameters
----------
ellipsoid : :class:`sargom.coordinates.ellipsoids.Ellipsoid`
Reference ellipsoid used for the projection.
lon_origin_rad : :class:`float`
Longitude of the origin of the Lambert Conic Conformal projection in radians.
lat_origin_rad : :class:`float`
Latitude of the origin of the Lambert Conic Conformal projection in radians.
scale : :class:`float`, optional
Scale factor of the projection. Default is 1.0.
x_offset_m : :class:`float`, optional
Offset from the projection origin in the x-direction in meters. Default is 0.0.
y_offset_m : :class:`float`, optional
Offset from the projection origin in the y-direction in meters. Default is 0.0.
Attributes
----------
ellipsoid : :class:`sargom.coordinates.ellipsoids.Ellipsoid`
The reference ellipsoid.
lon_origin_rad : :class:`float`
The longitude origin in radians.
lat_origin_rad : :class:`float`
The latitude origin in radians.
scale : :class:`float`
The scale factor.
x_offset_m : :class:`float`
The x-offset in meters.
y_offset_m : :class:`float`
The y-offset in meters.
"""
def __init__(
self,
ellipsoid, lon_origin_rad, lat_origin_rad,
scale=1.0, x_offset_m=0.0, y_offset_m=0.0
):
R0 = (
scale * ellipsoid.prime_vertical_curvature_radius(lat_origin_rad)
/ np.tan(lat_origin_rad)
)
self.ellipsoid = ellipsoid
self.lon_origin_rad = lon_origin_rad
self.lat_origin_rad = lat_origin_rad
self.scale = scale
self.x_offset_m = x_offset_m
self.y_offset_m = y_offset_m + R0
# Precompute constants
self._sin_lat_origin = np.sin(self.lat_origin_rad)
self._C = R0 * np.exp(
self._sin_lat_origin * self.ellipsoid.isometric_latitude(self.lat_origin_rad)
)
[docs]
def forward(self, lon_rad, lat_rad):
"""
Forward transformation from geographic coordinates to projected coordinates.
Transforms geographic coordinates (longitude, latitude) to projected coordinates
(x, y) in the Lambert Conic Conformal projection.
Parameters
----------
lon_rad : array_like
The geographic longitude in radians.
lat_rad : array_like
The geographic latitude in radians.
Returns
-------
x_m : :class:`numpy.ndarray`
The projected x-coordinate in meters.
y_m : :class:`numpy.ndarray`
The projected y-coordinate in meters.
Notes
-----
The transformation uses the standard Lambert Conic Conformal projection
formulas with the ellipsoid parameters and projection constants.
"""
theta = self._sin_lat_origin * (lon_rad - self.lon_origin_rad)
R = self._C * np.exp(-self._sin_lat_origin * self.ellipsoid.isometric_latitude(lat_rad))
x_m = self.x_offset_m + R * np.sin(theta)
y_m = self.y_offset_m - R * np.cos(theta)
return x_m, y_m
[docs]
def inverse(self, x_m, y_m):
"""
Inverse transformation from projected coordinates to geographic coordinates.
Transforms projected coordinates (x, y) in the Lambert Conic Conformal
projection to geographic coordinates (longitude, latitude).
Parameters
----------
x_m : array_like
The projected x-coordinate in meters.
y_m : array_like
The projected y-coordinate in meters.
Returns
-------
lon_rad : :class:`numpy.ndarray`
The geographic longitude in radians.
lat_rad : :class:`numpy.ndarray`
The geographic latitude in radians.
Notes
-----
The transformation uses the inverse Lambert Conic Conformal projection
formulas with the ellipsoid parameters and projection constants.
"""
if self._sin_lat_origin >= 0.0:
dx = x_m - self.x_offset_m
dy = self.y_offset_m - y_m
else:
dx = self.x_offset_m - x_m
dy = y_m - self.y_offset_m
# Longitude
lon_rad = self.lon_origin_rad + np.arctan2(dx, dy) / self._sin_lat_origin
# Latitude
lat_rad = self.ellipsoid.inverse_isometric_latitude(
-np.log(np.abs(np.hypot(dx, dy) / self._C)) / self._sin_lat_origin
)
return lon_rad, lat_rad
if __name__ == "__main__":
import doctest
doctest.testmod()