Skip to content

Commit

Permalink
pyproj/[geod.py, _geod.pyi, _geod.pyx] - add fwd_npts functions, si…
Browse files Browse the repository at this point in the history
…milar to `inv_npts` but using forward calculation
  • Loading branch information
idanmiara committed May 9, 2021
1 parent 47b00ef commit d5acdf3
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
13 changes: 13 additions & 0 deletions pyproj/_geod.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ class Geod:
include_initial: bool = False,
include_terminus: bool = False,
) -> None: ...
def _fwd_npts(
self,
out_lons: Any,
out_lats: Any,
out_azis: Any,
lon1: float,
lat1: float,
az1: float,
npts: int,
radians: bool = False,
include_initial: bool = False,
include_terminus: bool = False,
) -> None: ...
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
60 changes: 60 additions & 0 deletions pyproj/_geod.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,66 @@ cdef class Geod:
if store_az:
azis_buff.data[iii] = pazi2

@cython.boundscheck(False)
@cython.wraparound(False)
def _fwd_npts(
self,
object out_lons,
object out_lats,
object out_azis,
double lon1,
double lat1,
double az1,
int npts,
bint radians=False,
bint include_initial=False,
bint include_terminus=False,
):
"""
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
cdef double s12
cdef double plon2
cdef double plat2
cdef geod_geodesicline line

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:
lon1 *= _RAD2DG
lat1 *= _RAD2DG
# do fwd computation to set azimuths, distance.
geod_lineinit(&line, &self._geod_geodesic, lat1, lon1, azi1, 0u)
# distance increment.
del_s = line.s13 / (npts - include_initial - include_terminus + 1)
# loop over intermediate points, compute lat/lons.
for iii in range(0, npts):
s12 = (iii + (not include_initial)) * del_s
geod_position(&line, s12, &plat2, &plon2, &pazi2)
if radians:
plat2 *= _DG2RAD
plon2 *= _DG2RAD
lats_buff.data[iii] = plat2
lons_buff.data[iii] = plon2
if store_az:
azis_buff.data[iii] = pazi2

@cython.boundscheck(False)
@cython.wraparound(False)
Expand Down
29 changes: 29 additions & 0 deletions pyproj/geod.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,35 @@ def inv_npts(
include_terminus=include_terminus,
)

def fwd_npts(
self,
out_lons: Any,
out_lats: Any,
out_azis: Any,
lon1: float,
lat1: float,
az1: float,
npts: int,
radians: bool = False,
include_initial: bool = False,
include_terminus: bool = False,
) -> None:
"""
Similar to npts_inv(), but using a forward computation to calculate geod_line
"""
super()._fwd_npts(
out_lons=out_lons,
out_lats=out_lats,
out_azis=out_azis,
lon1=lon1,
lat1=lat1,
az1=az1,
npts=npts,
radians=radians,
include_initial=include_initial,
include_terminus=include_terminus,
)

def line_length(self, lons: Any, lats: Any, radians: bool = False) -> float:
"""
.. versionadded:: 2.3.0
Expand Down

0 comments on commit d5acdf3

Please sign in to comment.