Skip to content

Commit

Permalink
pyproj/[geod.py, _geod.pyi, _geod.pyx] - add `inv_intermediate_by_npt…
Browse files Browse the repository at this point in the history
…s` functions that uses given buffers `out_lons`, `out_lats` (and `out_azis`) buffers instead of creating new buffers

test/test_geod.py - add tests for `inv_intermediate_by_npts`
  • Loading branch information
idanmiara committed May 10, 2021
1 parent 4a195fb commit 527c0b5
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 6 deletions.
14 changes: 14 additions & 0 deletions pyproj/_geod.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ class Geod:
initial_idx: int = 1,
terminus_idx: int = 1,
) -> Tuple[Tuple[float], Tuple[float]]: ...
def _inv_intermediate_by_npts(
self,
out_lons: Any,
out_lats: Any,
out_azis: Any,
lon1: float,
lat1: float,
lon2: float,
lat2: float,
npts: int,
radians: bool = False,
initial_idx: int = 1,
terminus_idx: int = 1,
) -> int: ...
def _line_length(self, lons: Any, lats: Any, radians: bool = False) -> float: ...
def _polygon_area_perimeter(
self, lons: Any, lats: Any, radians: bool = False
Expand Down
53 changes: 47 additions & 6 deletions pyproj/_geod.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,38 @@ cdef class Geod:
given initial and terminus lat/lon, find npts intermediate points.
returns lons, lats buffers
"""
cdef array.array array_template = array.array("d", [])
cdef array.array out_lons = array.clone(array_template, npts, zero=False)
cdef array.array out_lats = array.clone(array_template, npts, zero=False)

self._inv_intermediate_by_npts(
out_lons=out_lons, out_lats=out_lats, out_azis=None,
lon1=lon1, lat1=lat1, lon2=lon2, lat2=lat2,
npts=npts, initial_idx=initial_idx, terminus_idx=terminus_idx,
radians=radians)

return out_lons, out_lats

@cython.boundscheck(False)
@cython.wraparound(False)
def _inv_intermediate_by_npts(
self,
object out_lons,
object out_lats,
object out_azis,
double lon1,
double lat1,
double lon2,
double lat2,
int npts,
bint radians=False,
int initial_idx=1,
int terminus_idx=1,
) -> int:
"""
given initial and terminus lat/lon, find npts intermediate points.
using given lons, lats buffers
"""
cdef Py_ssize_t iii
cdef double del_s
cdef double pazi2
Expand All @@ -176,12 +208,19 @@ cdef class Geod:
cdef double plat2
cdef geod_geodesicline line

cdef array.array array_template = array.array("d", [])
cdef array.array out_lons = array.clone(array_template, npts, zero=False)
cdef array.array out_lats = array.clone(array_template, npts, zero=False)

cdef PyBuffWriteManager lats_buff = PyBuffWriteManager(out_lats)
cdef PyBuffWriteManager lons_buff = PyBuffWriteManager(out_lons)
cdef PyBuffWriteManager lats_buff = PyBuffWriteManager(out_lats)

if lons_buff.len < npts or lats_buff.len < npts:
raise GeodError("lons or lats arrays are not long enough.")

cdef PyBuffWriteManager azis_buff
cdef bint store_az = out_azis is not None

if store_az:
azis_buff = PyBuffWriteManager(out_azis)
if azis_buff.len < npts:
raise GeodError("az array is not long enough.")

with nogil:
if radians:
Expand All @@ -204,8 +243,10 @@ cdef class Geod:
plon2 *= _DG2RAD
lats_buff.data[iii] = plat2
lons_buff.data[iii] = plon2
if store_az:
azis_buff.data[iii] = pazi2

return out_lons, out_lats
return npts

@cython.boundscheck(False)
@cython.wraparound(False)
Expand Down
32 changes: 32 additions & 0 deletions pyproj/geod.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,38 @@ def npts(
)
return list(zip(lons, lats)) if return_points else (lons, lats)

def inv_intermediate_by_npts(
self,
out_lons: Any,
out_lats: Any,
out_azis: Any,
lon1: float,
lat1: float,
lon2: float,
lat2: float,
npts: int,
initial_idx: int = 1,
terminus_idx: int = 1,
radians: bool = False,
) -> None:
"""
Similar to npts(), but using the given buffers for the output.
out_lons, out_lats, and out_az are the output buffers (out_azis is optional)
"""
super()._inv_intermediate_by_npts(
out_lons=out_lons,
out_lats=out_lats,
out_azis=out_azis,
lon1=lon1,
lat1=lat1,
lon2=lon2,
lat2=lat2,
npts=npts,
radians=radians,
initial_idx=initial_idx,
terminus_idx=terminus_idx,
)

def line_length(self, lons: Any, lats: Any, radians: bool = False) -> float:
"""
.. versionadded:: 2.3.0
Expand Down
43 changes: 43 additions & 0 deletions test/test_geod.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from contextlib import contextmanager
from itertools import permutations

import numpy as np
import pytest
from numpy.testing import assert_almost_equal

Expand Down Expand Up @@ -132,6 +133,48 @@ def test_geod_inverse_transform():
(lat2pt, lon2pt, o_dist), (45.517, -123.683, 832838.542), decimal=3
)

if include_initial and include_terminus:
lons, lats, azis12, azis21, dists = np.hstack(
(lonlats, res_az12_az21_dists)
).transpose()

lons_a = np.empty(point_count)
lats_a = np.empty(point_count)
azis_a = np.empty(point_count)

gg.inv_intermediate_by_npts(
out_lons=lons_a,
out_lats=lats_a,
out_azis=azis_a,
lon1=lon1pt,
lat1=lat1pt,
lon2=lon2pt,
lat2=lat2pt,
npts=point_count,
initial_idx=0,
terminus_idx=0,
)

assert_almost_equal(lons_a, lons)
assert_almost_equal(lats_a, lats)
assert_almost_equal(lats_a, azis12)

gg.inv_intermediate_by_npts(
out_lons=lons_a,
out_lats=lats_a,
out_azis=None,
lon1=lon1pt,
lat1=lat1pt,
lon2=lon2pt,
lat2=lat2pt,
npts=point_count,
initial_idx=0,
terminus_idx=0,
)

assert_almost_equal(lons_a, lons)
assert_almost_equal(lats_a, lats)


def test_geod_cities():
# specify the lat/lons of some cities.
Expand Down

0 comments on commit 527c0b5

Please sign in to comment.