Skip to content

Commit

Permalink
Fix getting Ellipsoid.semi_minor_metre when not computed (#506)
Browse files Browse the repository at this point in the history
  • Loading branch information
snowman2 committed Jan 14, 2020
1 parent 7e7bcd2 commit 67ff137
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 60 deletions.
1 change: 1 addition & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Change Log
* ENH: Added :class:`pyproj.crs.CoordinateSystem` to `pyproj.crs` namespace (pull #501)
* ENH: Added :meth:`pyproj.crs.CoordinateSystem.from_user_input`, :meth:`pyproj.crs.CoordinateOperation.from_user_input`, :meth:`pyproj.crs.Datum.from_user_input`, :meth:`pyproj.crs.PrimeMeridian.from_user_input`, :meth:`pyproj.crs.Ellipsoid.from_user_input` (pull #502)
* ENH: Added :meth:`pyproj.crs.CoordinateSystem.from_name`, :meth:`pyproj.crs.CoordinateOperation.from_name`, :meth:`pyproj.crs.Datum.from_name`, :meth:`pyproj.crs.PrimeMeridian.from_name`, :meth:`pyproj.crs.Ellipsoid.from_name` (pull #505)
* BUG: Fix getting :attr:`pyproj.crs.Ellipsoid.semi_minor_metre` when not computed (issue #457)

2.4.2
~~~~~
Expand Down
7 changes: 3 additions & 4 deletions pyproj/_crs.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ cdef class _CRSParts(Base):


cdef class Ellipsoid(_CRSParts):
cdef double _semi_major_metre
cdef double _semi_minor_metre
cdef readonly double semi_major_metre
cdef readonly double semi_minor_metre
cdef readonly object is_semi_minor_computed
cdef double _inv_flattening
cdef readonly object ellipsoid_loaded
cdef readonly double inverse_flattening

@staticmethod
cdef create(PJ_CONTEXT* context, PJ* ellipsoid_pj)
Expand Down
67 changes: 14 additions & 53 deletions pyproj/_crs.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -718,17 +718,20 @@ cdef class Ellipsoid(_CRSParts):
The name of the ellipsoid.
is_semi_minor_computed: int
1 if True, 0 if False
ellipsoid_loaded: bool
True if it is loaded without errors.
semi_major_metre: float
The semi major axis in meters of the ellipsoid.
semi_minor_metre: float
The semi minor axis in meters of the ellipsoid.
inverse_flattening: float
The inverse flattening of the ellipsoid.
"""
def __cinit__(self):
# load in ellipsoid information if applicable
self._semi_major_metre = float("NaN")
self._semi_minor_metre = float("NaN")
self.semi_major_metre = float("NaN")
self.semi_minor_metre = float("NaN")
self.is_semi_minor_computed = False
self._inv_flattening = float("NaN")
self.ellipsoid_loaded = False
self.inverse_flattening = float("NaN")

def __init__(self):
raise RuntimeError(
Expand All @@ -742,14 +745,13 @@ cdef class Ellipsoid(_CRSParts):
ellips.projobj = ellipsoid_pj
cdef int is_semi_minor_computed = 0
proj_ellipsoid_get_parameters(
ellips.context,
ellips.projobj,
&ellips._semi_major_metre,
&ellips._semi_minor_metre,
context,
ellipsoid_pj,
&ellips.semi_major_metre,
&ellips.semi_minor_metre,
&is_semi_minor_computed,
&ellips._inv_flattening,
&ellips.inverse_flattening,
)
ellips.ellipsoid_loaded = True
ellips.is_semi_minor_computed = is_semi_minor_computed == 1
ellips._set_base_info()
CRSError.clear()
Expand Down Expand Up @@ -954,47 +956,6 @@ cdef class Ellipsoid(_CRSParts):
CRSError.clear()
return Ellipsoid.create(context, ellipsoid_pj)

@property
def semi_major_metre(self):
"""
The ellipsoid semi major metre.
Returns
-------
float or None: The semi major metre if the projection is an ellipsoid.
"""
if self.ellipsoid_loaded:
return self._semi_major_metre
return float("NaN")

@property
def semi_minor_metre(self):
"""
The ellipsoid semi minor metre.
Returns
-------
float or None: The semi minor metre if the projection is an ellipsoid
and the value was com
puted.
"""
if self.ellipsoid_loaded and self.is_semi_minor_computed:
return self._semi_minor_metre
return float("NaN")

@property
def inverse_flattening(self):
"""
The ellipsoid inverse flattening.
Returns
-------
float or None: The inverse flattening if the projection is an ellipsoid.
"""
if self.ellipsoid_loaded:
return self._inv_flattening
return float("NaN")


cdef class PrimeMeridian(_CRSParts):
"""
Expand Down
5 changes: 2 additions & 3 deletions pyproj/crs.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,14 +463,13 @@ def get_geod(self):
-------
pyproj.geod.Geod: Geod object based on the ellipsoid.
"""
if self.ellipsoid is None or not self.ellipsoid.ellipsoid_loaded:
if self.ellipsoid is None:
return None
in_kwargs = {
"a": self.ellipsoid.semi_major_metre,
"rf": self.ellipsoid.inverse_flattening,
"b": self.ellipsoid.semi_minor_metre,
}
if self.ellipsoid.is_semi_minor_computed:
in_kwargs["b"] = self.ellipsoid.semi_minor_metre
return Geod(**in_kwargs)

@classmethod
Expand Down
7 changes: 7 additions & 0 deletions test/test_crs.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,13 @@ def test_ellipsoid():
assert "{:.3f}".format(crs1.ellipsoid.semi_minor_metre) == "6356752.314"


def test_ellipsoid__semi_minor_not_computed():
cc = CRS("+proj=geos +lon_0=-89.5 +a=6378137.0 +b=6356752.31 h=12345")
assert cc.datum.ellipsoid.semi_minor_metre == 6356752.31
assert cc.datum.ellipsoid.semi_major_metre == 6378137.0
assert not cc.datum.ellipsoid.is_semi_minor_computed


def test_area_of_use():
crs1 = CRS.from_epsg(4326)
assert crs1.area_of_use.bounds == (-180.0, -90.0, 180.0, 90.0)
Expand Down

0 comments on commit 67ff137

Please sign in to comment.