Skip to content
Commits on Source (4)
......@@ -5,6 +5,7 @@ include LICENSE
include create_docs.sh
include pyproj/*.pyd
include pyproj/*.pyx
include pyproj/*.pxd
include pyproj/*.pxi
include test/test.py
include test/test2.py
......
......@@ -10,6 +10,8 @@ pyproj
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/pyproj/badges/version.svg)](https://anaconda.org/conda-forge/pyproj)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2592233.svg)](https://doi.org/10.5281/zenodo.2592233)
Python interface to [PROJ.4](https://github.com/OSGeo/proj.4).
......
python-pyproj (2.0.1+ds-1~exp2) UNRELEASED; urgency=medium
python-pyproj (2.0.2+ds-1~exp1) experimental; urgency=medium
* New upstream release.
* Ignore test failures on i386, hppa & hurd-i386.
-- Bas Couwenberg <sebastic@debian.org> Sun, 10 Mar 2019 21:03:31 +0100
-- Bas Couwenberg <sebastic@debian.org> Wed, 13 Mar 2019 15:36:35 +0100
python-pyproj (2.0.1+ds-1~exp1) experimental; urgency=medium
......
......@@ -47,7 +47,7 @@ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """
__version__ = "2.0.1"
__version__ = "2.0.2"
__all__ = ["Proj", "Geod", "CRS", "transform", "itransform", "pj_ellps", "pj_list"]
import re
......@@ -416,7 +416,7 @@ class Proj(_proj.Proj):
return Proj(self.crs.to_geodetic())
def transform(p1, p2, x, y, z=None):
def transform(p1, p2, x, y, z=None, radians=False):
"""
x2, y2, z2 = transform(p1, p2, x1, y1, z1)
......@@ -427,7 +427,10 @@ def transform(p1, p2, x, y, z=None):
transformed to x2,y2,z2 in the coordinate system defined by p2.
z1 is optional, if it is not set it is assumed to be zero (and
only x2 and y2 are returned).
only x2 and y2 are returned). If the optional keyword
'radians' is True (default is False), then all input and
output coordinates will be in radians instead of the default
of degrees for geographic input/output projections.
In addition to converting between cartographic and geographic
projection coordinates, this function can take care of datum
......@@ -489,6 +492,11 @@ def transform(p1, p2, x, y, z=None):
>>> x3, y3 = transform("epsg:4326", "epsg:3857", 33, 98)
>>> "%.3f %.3f" % (x3, y3)
'10909310.098 3895303.963'
>>> pj = Proj(init="epsg:4214")
>>> pjx, pjy = pj(116.366, 39.867)
>>> xr, yr = transform(pj, Proj(4326), pjx, pjy, radians=True)
>>> "%.3f %.3f" % (xr, yr)
'2.031 0.696'
"""
# check that p1 and p2 are valid
if not isinstance(p1, Proj):
......@@ -504,7 +512,7 @@ def transform(p1, p2, x, y, z=None):
else:
inz = None
# call pj_transform. inx,iny,inz buffers modified in place.
_proj._transform(p1, p2, inx, iny, inz)
_proj._transform(p1, p2, inx, iny, inz, radians)
# if inputs were lists, tuples or floats, convert back.
outx = _convertback(xisfloat, xislist, xistuple, inx)
outy = _convertback(yisfloat, yislist, xistuple, iny)
......@@ -515,7 +523,7 @@ def transform(p1, p2, x, y, z=None):
return outx, outy
def itransform(p1, p2, points, switch=False):
def itransform(p1, p2, points, switch=False, radians=False):
"""
points2 = transform(p1, p2, points1)
Iterator/generator version of the function pyproj.transform.
......@@ -534,7 +542,9 @@ def itransform(p1, p2, points, switch=False):
- a generator of coordinates (xi,yi) for 2d points or (xi,yi,zi) for 3d
If optional keyword 'switch' is True (default is False) then x, y or lon,lat coordinates
of points are switched to y, x or lat, lon.
of points are switched to y, x or lat, lon. If the optional keyword 'radians' is True
(default is False), then all input and output coordinates will be in radians instead
of the default of degrees for geographic input/output projections.
Example usage:
......@@ -555,6 +565,10 @@ def itransform(p1, p2, points, switch=False):
'2221638.801 2637034.372'
'2212924.125 2619851.898'
'2238294.779 2703763.736'
>>> pj = Proj(init="epsg:4214")
>>> pjx, pjy = pj(116.366, 39.867)
>>> for pt in itransform(pj, Proj(4326), [(pjx, pjy)]): '{:.3f} {:.3f}'.format(*pt)
'2.031 0.696'
"""
if not isinstance(p1, Proj):
p1 = CRS.from_user_input(p1)
......@@ -582,7 +596,7 @@ def itransform(p1, p2, points, switch=False):
if len(buff) == 0:
break
_proj._transform_sequence(p1, p2, stride, buff, switch)
_proj._transform_sequence(p1, p2, stride, buff, switch, radians)
for pt in zip(*([iter(buff)] * stride)):
yield pt
......
......@@ -298,7 +298,14 @@ cdef class TransProj:
return in_proj.definition
return cstrencode(CRS.from_user_input(in_proj).to_wkt())
def _transform(p1, p2, inx, iny, inz):
def is_geographic(proj):
if hasattr(proj, "crs"):
proj = proj.crs
return proj.is_geographic
def _transform(p1, p2, inx, iny, inz, radians):
pj_trans = TransProj(p1, p2)
# private function to call pj_transform
cdef void *xdata
......@@ -327,10 +334,11 @@ def _transform(p1, p2, inx, iny, inz):
else:
zz = NULL
npts = buflenx//8
if proj_angular_input(pj_trans.projpj, PJ_FWD):
if radians and is_geographic(p1):
for i from 0 <= i < npts:
xx[i] = xx[i]*_DG2RAD
yy[i] = yy[i]*_DG2RAD
xx[i] = xx[i]*_RAD2DG
yy[i] = yy[i]*_RAD2DG
proj_trans_generic(
pj_trans.projpj,
......@@ -344,13 +352,13 @@ def _transform(p1, p2, inx, iny, inz):
if errno:
raise ProjError("proj_trans_generic error: {}".format(
pystrdecode(proj_errno_string(errno))))
if proj_angular_output(pj_trans.projpj, PJ_FWD):
for i from 0 <= i < npts:
xx[i] = xx[i]*_RAD2DG
yy[i] = yy[i]*_RAD2DG
if radians and is_geographic(p2):
for i from 0 <= i < npts:
xx[i] = xx[i]*_DG2RAD
yy[i] = yy[i]*_DG2RAD
def _transform_sequence(p1, p2, Py_ssize_t stride, inseq, bint switch):
def _transform_sequence(p1, p2, Py_ssize_t stride, inseq, bint switch, radians):
pj_trans = TransProj(p1, p2)
# private function to itransform function
cdef:
......@@ -370,11 +378,11 @@ def _transform_sequence(p1, p2, Py_ssize_t stride, inseq, bint switch):
coords = <double*>buffer
npts = buflen // (stride * _DOUBLESIZE)
if proj_angular_input(pj_trans.projpj, PJ_FWD):
if radians and is_geographic(p1):
for i from 0 <= i < npts:
j = stride*i
coords[j] *= _DG2RAD
coords[j+1] *= _DG2RAD
coords[j] *= _RAD2DG
coords[j+1] *= _RAD2DG
if not switch:
x = coords
......@@ -402,8 +410,8 @@ def _transform_sequence(p1, p2, Py_ssize_t stride, inseq, bint switch):
raise ProjError("proj_trans_generic error: {}".format(
proj_errno_string(errno)))
if proj_angular_output(pj_trans.projpj, PJ_FWD):
if radians and is_geographic(p2):
for i from 0 <= i < npts:
j = stride*i
coords[j] *= _RAD2DG
coords[j+1] *= _RAD2DG
coords[j] *= _DG2RAD
coords[j+1] *= _DG2RAD
......@@ -33,6 +33,12 @@ def _dict2string(projparams):
# convert a dict to a proj4 string.
pjargs = []
for key, value in projparams.items():
# issue 183 (+ no_rot)
if value is None or value is True:
pjargs.append("+" + key + " ")
elif value is False:
pass
else:
pjargs.append("+" + key + "=" + str(value) + " ")
return "".join(pjargs)
......
Change Log
==========
2.0.2
~~~~~
* add filter for boolean values in dict2string so "no_rot=True" works (issue #183).
* make sure .pxd files included in source tarball.
* add radians flag back in for transform/itransform (issue #185).
2.0.1
~~~~~
* Ensure data path set properly for TransProj (pull request #179, addressed
......
......@@ -94,6 +94,30 @@ class BasicTest(unittest.TestCase):
self.assertAlmostEqual(point_geog[0], point_geog2[0])
self.assertAlmostEqual(point_geog[1], point_geog2[1])
def test_from_dict_with_bool(self):
# issue #183
p_d = {'proj': 'omerc',
'lat_2': 80.27942,
'lat_0': 62.87671,
'lat_1': 42.751232,
'ellps': 'WGS84',
'no_rot': True,
'lon_1': 33.793186,
'lon_2': -18.374414}
p=Proj(p_d)
self.assertTrue('+no_rot' in p.srs.split())
p_d = {'proj': 'omerc',
'lat_2': 80.27942,
'lat_0': 62.87671,
'lat_1': 42.751232,
'ellps': 'WGS84',
'no_rot': False,
'lon_1': 33.793186,
'lon_2': -18.374414}
p=Proj(p_d)
self.assertFalse('+no_rot' in p.srs.split())
class InverseHammerTest(unittest.TestCase):
# This is a unit test of the inverse of the hammer projection, which
......