From 67558d9f0e6e0c05b4c2a0e83923cc96a41dcd7c Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Thu, 15 Dec 2022 20:51:14 -0700 Subject: [PATCH] ENH: Add inplace kwarg to Geod.fwd and Geod.inv (#1201) --- pyproj/geod.py | 37 ++++++++++++++++++++++++++++--------- test/test_geod.py | 18 ++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/pyproj/geod.py b/pyproj/geod.py index 39402a69e..ed4b24fb0 100644 --- a/pyproj/geod.py +++ b/pyproj/geod.py @@ -240,7 +240,13 @@ def __init__(self, initstring: Optional[str] = None, **kwargs) -> None: ) def fwd( # pylint: disable=invalid-name - self, lons: Any, lats: Any, az: Any, dist: Any, radians: bool = False + self, + lons: Any, + lats: Any, + az: Any, + dist: Any, + radians: bool = False, + inplace: bool = False, ) -> Tuple[Any, Any, Any]: """ Forward transformation @@ -249,6 +255,8 @@ def fwd( # pylint: disable=invalid-name points given longitudes and latitudes of initial points, plus forward azimuths and distances. + .. versionadded:: 3.5.0 inplace + Accepted numeric scalar or array: - :class:`int` @@ -276,6 +284,10 @@ def fwd( # pylint: disable=invalid-name radians: bool, default=False If True, the input data is assumed to be in radians. Otherwise, the data is assumed to be in degrees. + inplace: bool, default=False + If True, will attempt to write the results to the input array + instead of returning a new array. This will fail if the input + is not an array in C order with the double data type. Returns ------- @@ -287,10 +299,10 @@ def fwd( # pylint: disable=invalid-name Back azimuth(s) """ # process inputs, making copies that support buffer API. - inx, x_data_type = _copytobuffer(lons) - iny, y_data_type = _copytobuffer(lats) - inz, z_data_type = _copytobuffer(az) - ind = _copytobuffer(dist)[0] + inx, x_data_type = _copytobuffer(lons, inplace=inplace) + iny, y_data_type = _copytobuffer(lats, inplace=inplace) + inz, z_data_type = _copytobuffer(az, inplace=inplace) + ind = _copytobuffer(dist, inplace=inplace)[0] self._fwd(inx, iny, inz, ind, radians=radians) # if inputs were lists, tuples or floats, convert back. outx = _convertback(x_data_type, inx) @@ -305,6 +317,7 @@ def inv( lons2: Any, lats2: Any, radians: bool = False, + inplace: bool = False, ) -> Tuple[Any, Any, Any]: """ Inverse transformation @@ -312,6 +325,8 @@ def inv( Determine forward and back azimuths, plus distances between initial points and terminus points. + .. versionadded:: 3.5.0 inplace + Accepted numeric scalar or array: - :class:`int` @@ -338,6 +353,10 @@ def inv( radians: bool, default=False If True, the input data is assumed to be in radians. Otherwise, the data is assumed to be in degrees. + inplace: bool, default=False + If True, will attempt to write the results to the input array + instead of returning a new array. This will fail if the input + is not an array in C order with the double data type. Returns ------- @@ -350,10 +369,10 @@ def inv( in meters """ # process inputs, making copies that support buffer API. - inx, x_data_type = _copytobuffer(lons1) - iny, y_data_type = _copytobuffer(lats1) - inz, z_data_type = _copytobuffer(lons2) - ind = _copytobuffer(lats2)[0] + inx, x_data_type = _copytobuffer(lons1, inplace=inplace) + iny, y_data_type = _copytobuffer(lats1, inplace=inplace) + inz, z_data_type = _copytobuffer(lons2, inplace=inplace) + ind = _copytobuffer(lats2, inplace=inplace)[0] self._inv(inx, iny, inz, ind, radians=radians) # if inputs were lists, tuples or floats, convert back. outx = _convertback(x_data_type, inx) diff --git a/test/test_geod.py b/test/test_geod.py index d4b5ee327..33cc1ad30 100644 --- a/test/test_geod.py +++ b/test/test_geod.py @@ -658,6 +658,24 @@ def test_geod_inv_honours_input_types(lons1, lats1, lons2): assert isinstance(outz, type(lons2)) +def test_geod_fwd_inv_inplace(): + gg = Geod(ellps="clrk66") + lon1pt = np.array([0], dtype=np.float64) + lat1pt = np.array([0], dtype=np.float64) + lon2pt = np.array([1], dtype=np.float64) + lat2pt = np.array([1], dtype=np.float64) + + az12, az21, dist = gg.inv(lon1pt, lat1pt, lon2pt, lat2pt, inplace=True) + assert az12 is lon1pt + assert az21 is lat1pt + assert dist is lon2pt + + endlon, endlat, backaz = gg.fwd(lon1pt, lat1pt, az12, dist, inplace=True) + assert endlon is lon1pt + assert endlat is lat1pt + assert backaz is az12 + + @pytest.mark.parametrize("kwarg", ["b", "f", "es", "rf", "e"]) def test_geod__build_kwargs(kwarg): gg = Geod(ellps="clrk66")