Update upstream source from tag 'upstream/3.2.1_rc0'
Update to upstream version '3.2.1~rc0'
with Debian dir a27601f6a95c5dee4768b6c49a0e8c82795f9327
Bas Couwenberg
2 years ago
0 | 0 | Change Log |
1 | 1 | ========== |
2 | 2 | |
3 | 3.2.1 | |
4 | ------ | |
5 | - REF: declare specific python types in cython (pull #928) | |
6 | - REF: Use cython string decoding (pull #929) | |
7 | - BUG: Return multiple authorities with :attr:`pyproj.crs.CRS.list_authority` (pull #943) | |
8 | - BUG: CRS CF conversions ensure lon_0 = north_pole_grid_longitude + 180 (issue #927) | |
9 | - BUG: CRS CF conversions ensure Pole rotation (netCDF CF convention) conversion works (issue #927) | |
10 | ||
3 | 11 | 3.2.0 |
4 | 12 | ------ |
5 | * WHL: Wheels contain PROJ 8.1.1 | |
13 | - WHL: Wheels contain PROJ 8.1.1 | |
6 | 14 | - DOC: Add new pyproj logo (issue #700) |
7 | 15 | - REF: Handle deprecation of proj_context_set_autoclose_database (issue #866) |
8 | 16 | - REF: Make CRS methods inheritable (issue #847) |
0 | 0 | Documentation Archive |
1 | 1 | ===================== |
2 | 2 | |
3 | - `3.2.0 <https://pyproj4.github.io/pyproj/3.2.0/>`_ | |
3 | 4 | - `3.1.0 <https://pyproj4.github.io/pyproj/3.1.0/>`_ |
4 | 5 | - `3.0.1 <https://pyproj4.github.io/pyproj/3.0.1/>`_ |
5 | 6 | - `2.6.1 <https://pyproj4.github.io/pyproj/v2.6.1rel/>`_ |
27 | 27 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
28 | 28 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
29 | 29 | """ |
30 | __version__ = "3.2.0" | |
30 | __version__ = "3.2.1.rc0" | |
31 | 31 | __all__ = [ |
32 | 32 | "Proj", |
33 | 33 | "Geod", |
0 | from pyproj.compat import pystrdecode | |
0 | cdef str cstrdecode(const char *instring) | |
1 | cpdef bytes cstrencode(str pystr) | |
1 | 2 | |
3 | IF CTE_PYTHON_IMPLEMENTATION == "CPython": | |
4 | from cpython cimport array | |
5 | cdef array.array empty_array(int npts) | |
2 | 6 | |
3 | cdef cstrdecode(const char *instring) | |
7 | ELSE: | |
8 | # https://github.com/pyproj4/pyproj/issues/854 | |
9 | cdef empty_array(int npts) |
0 | def cstrencode(pystr: str) -> bytes: ... |
0 | 0 | import array |
1 | 1 | |
2 | from pyproj.compat import pystrdecode | |
2 | ||
3 | cpdef bytes cstrencode(str pystr): | |
4 | """ | |
5 | Encode a string into bytes. | |
6 | """ | |
7 | try: | |
8 | return pystr.encode("utf-8") | |
9 | except UnicodeDecodeError: | |
10 | return pystr.decode("utf-8").encode("utf-8") | |
3 | 11 | |
4 | 12 | |
5 | cdef cstrdecode(const char *instring): | |
13 | cdef str cstrdecode(const char *instring): | |
6 | 14 | if instring != NULL: |
7 | return pystrdecode(instring) | |
15 | return instring | |
8 | 16 | return None |
9 | 17 | |
10 | 18 | |
13 | 21 | |
14 | 22 | cdef array.array _ARRAY_TEMPLATE = array.array("d", []) |
15 | 23 | |
16 | def empty_array(int npts): | |
24 | cdef array.array empty_array(int npts): | |
17 | 25 | return array.clone(_ARRAY_TEMPLATE, npts, zero=False) |
18 | 26 | |
19 | 27 | ELSE: |
20 | 28 | # https://github.com/pyproj4/pyproj/issues/854 |
21 | def empty_array(int npts): | |
29 | cdef empty_array(int npts): | |
22 | 30 | return array.array("d", [float("NaN")] * npts) |
5 | 5 | const PJ* crs_2D) |
6 | 6 | |
7 | 7 | |
8 | cdef _get_concatenated_operations(PJ_CONTEXT*context, PJ*concatenated_operation) | |
8 | cdef tuple _get_concatenated_operations(PJ_CONTEXT*context, PJ*concatenated_operation) | |
9 | 9 | cdef _to_proj4( |
10 | 10 | PJ_CONTEXT* context, |
11 | 11 | PJ* projobj, |
12 | version, | |
13 | pretty, | |
12 | object version, | |
13 | bint pretty, | |
14 | 14 | ) |
15 | 15 | |
16 | 16 | cdef class Axis: |
17 | cdef readonly object name | |
18 | cdef readonly object abbrev | |
19 | cdef readonly object direction | |
17 | cdef readonly str name | |
18 | cdef readonly str abbrev | |
19 | cdef readonly str direction | |
20 | 20 | cdef readonly double unit_conversion_factor |
21 | cdef readonly object unit_name | |
22 | cdef readonly object unit_auth_code | |
23 | cdef readonly object unit_code | |
21 | cdef readonly str unit_name | |
22 | cdef readonly str unit_auth_code | |
23 | cdef readonly str unit_code | |
24 | 24 | |
25 | 25 | @staticmethod |
26 | 26 | cdef Axis create(PJ_CONTEXT* context, PJ* projobj, int index) |
30 | 30 | cdef class Base: |
31 | 31 | cdef PJ *projobj |
32 | 32 | cdef PJ_CONTEXT* context |
33 | cdef readonly object name | |
34 | cdef readonly object _remarks | |
35 | cdef readonly object _scope | |
33 | cdef readonly str name | |
34 | cdef readonly str _remarks | |
35 | cdef readonly str _scope | |
36 | 36 | cdef _set_base_info(self) |
37 | 37 | |
38 | 38 | cdef class _CRSParts(Base): |
42 | 42 | cdef class Ellipsoid(_CRSParts): |
43 | 43 | cdef readonly double semi_major_metre |
44 | 44 | cdef readonly double semi_minor_metre |
45 | cdef readonly object is_semi_minor_computed | |
45 | cdef readonly bint is_semi_minor_computed | |
46 | 46 | cdef readonly double inverse_flattening |
47 | 47 | |
48 | 48 | @staticmethod |
52 | 52 | cdef class PrimeMeridian(_CRSParts): |
53 | 53 | cdef readonly double longitude |
54 | 54 | cdef readonly double unit_conversion_factor |
55 | cdef readonly object unit_name | |
55 | cdef readonly str unit_name | |
56 | 56 | |
57 | 57 | @staticmethod |
58 | 58 | cdef PrimeMeridian create(PJ_CONTEXT* context, PJ* prime_meridian_pj) |
59 | 59 | |
60 | 60 | |
61 | 61 | cdef class Datum(_CRSParts): |
62 | cdef readonly object type_name | |
62 | cdef readonly str type_name | |
63 | 63 | cdef readonly object _ellipsoid |
64 | 64 | cdef readonly object _prime_meridian |
65 | 65 | |
68 | 68 | |
69 | 69 | |
70 | 70 | cdef class CoordinateSystem(_CRSParts): |
71 | cdef readonly object _axis_list | |
71 | cdef readonly list _axis_list | |
72 | 72 | |
73 | 73 | @staticmethod |
74 | 74 | cdef CoordinateSystem create(PJ_CONTEXT* context, PJ* coordinate_system_pj) |
75 | 75 | |
76 | 76 | |
77 | 77 | cdef class Param: |
78 | cdef readonly object name | |
79 | cdef readonly object auth_name | |
80 | cdef readonly object code | |
78 | cdef readonly str name | |
79 | cdef readonly str auth_name | |
80 | cdef readonly str code | |
81 | 81 | cdef readonly object value |
82 | 82 | cdef readonly double unit_conversion_factor |
83 | cdef readonly object unit_name | |
84 | cdef readonly object unit_auth_name | |
85 | cdef readonly object unit_code | |
86 | cdef readonly object unit_category | |
83 | cdef readonly str unit_name | |
84 | cdef readonly str unit_auth_name | |
85 | cdef readonly str unit_code | |
86 | cdef readonly str unit_category | |
87 | 87 | |
88 | 88 | @staticmethod |
89 | 89 | cdef Param create(PJ_CONTEXT* context, PJ* projobj, int param_idx) |
90 | 90 | |
91 | 91 | |
92 | 92 | cdef class Grid: |
93 | cdef readonly object short_name | |
94 | cdef readonly object full_name | |
95 | cdef readonly object package_name | |
96 | cdef readonly object url | |
97 | cdef readonly object direct_download | |
98 | cdef readonly object open_license | |
99 | cdef readonly object available | |
93 | cdef readonly str short_name | |
94 | cdef readonly str full_name | |
95 | cdef readonly str package_name | |
96 | cdef readonly str url | |
97 | cdef readonly bint direct_download | |
98 | cdef readonly bint open_license | |
99 | cdef readonly bint available | |
100 | 100 | |
101 | 101 | @staticmethod |
102 | 102 | cdef Grid create(PJ_CONTEXT* context, PJ* projobj, int grid_idx) |
103 | 103 | |
104 | 104 | |
105 | 105 | cdef class CoordinateOperation(_CRSParts): |
106 | cdef readonly object _params | |
107 | cdef readonly object _grids | |
106 | cdef readonly list _params | |
107 | cdef readonly list _grids | |
108 | 108 | cdef readonly object _area_of_use |
109 | cdef readonly object method_name | |
110 | cdef readonly object method_auth_name | |
111 | cdef readonly object method_code | |
109 | cdef readonly str method_name | |
110 | cdef readonly str method_auth_name | |
111 | cdef readonly str method_code | |
112 | 112 | cdef readonly double accuracy |
113 | cdef readonly object is_instantiable | |
114 | cdef readonly object has_ballpark_transformation | |
115 | cdef readonly object _towgs84 | |
116 | cdef readonly object _operations | |
117 | cdef readonly type_name | |
113 | cdef readonly bint is_instantiable | |
114 | cdef readonly bint has_ballpark_transformation | |
115 | cdef readonly list _towgs84 | |
116 | cdef readonly tuple _operations | |
117 | cdef readonly str type_name | |
118 | 118 | |
119 | 119 | @staticmethod |
120 | 120 | cdef CoordinateOperation create(PJ_CONTEXT* context, PJ* coordinate_operation_pj) |
123 | 123 | cdef class _CRS(Base): |
124 | 124 | cdef PJ_TYPE _type |
125 | 125 | cdef PJ_PROJ_INFO projpj_info |
126 | cdef readonly object srs | |
127 | cdef readonly object type_name | |
128 | cdef readonly object _ellipsoid | |
126 | cdef readonly str srs | |
127 | cdef readonly str type_name | |
128 | cdef readonly Ellipsoid _ellipsoid | |
129 | 129 | cdef readonly object _area_of_use |
130 | cdef readonly object _prime_meridian | |
131 | cdef readonly object _datum | |
132 | cdef readonly object _sub_crs_list | |
133 | cdef readonly object _source_crs | |
134 | cdef readonly object _target_crs | |
135 | cdef readonly object _geodetic_crs | |
136 | cdef readonly object _coordinate_system | |
137 | cdef readonly object _coordinate_operation | |
130 | cdef readonly PrimeMeridian _prime_meridian | |
131 | cdef readonly Datum _datum | |
132 | cdef readonly list _sub_crs_list | |
133 | cdef readonly _CRS _source_crs | |
134 | cdef readonly _CRS _target_crs | |
135 | cdef readonly _CRS _geodetic_crs | |
136 | cdef readonly CoordinateSystem _coordinate_system | |
137 | cdef readonly CoordinateOperation _coordinate_operation |
184 | 184 | ] = CoordinateOperationType.CONVERSION, |
185 | 185 | ) -> "CoordinateOperation": ... |
186 | 186 | |
187 | ||
188 | 187 | class AuthorityMatchInfo(NamedTuple): |
189 | 188 | auth_name: str |
190 | 189 | code: str |
191 | 190 | confidence: int |
192 | ||
193 | 191 | |
194 | 192 | class _CRS(Base): |
195 | 193 | srs: str |
2 | 2 | import warnings |
3 | 3 | from collections import OrderedDict, namedtuple |
4 | 4 | |
5 | from pyproj._compat cimport cstrdecode | |
5 | from pyproj._compat cimport cstrdecode, cstrencode | |
6 | 6 | from pyproj._datadir cimport pyproj_context_create, pyproj_context_destroy |
7 | 7 | |
8 | 8 | from pyproj.aoi import AreaOfUse |
9 | from pyproj.compat import cstrencode, pystrdecode | |
10 | 9 | from pyproj.crs.datum import CustomEllipsoid |
11 | 10 | from pyproj.crs.enums import CoordinateOperationType, DatumType |
12 | 11 | from pyproj.enums import ProjVersion, WktVersion |
14 | 13 | from pyproj.geod import pj_ellps |
15 | 14 | from pyproj.utils import NumpyEncoder |
16 | 15 | |
16 | ||
17 | 17 | # This is for looking up the ellipsoid parameters |
18 | 18 | # based on the long name |
19 | _PJ_ELLPS_NAME_MAP = { | |
19 | cdef dict _PJ_ELLPS_NAME_MAP = { | |
20 | 20 | ellps["description"]: ellps_id for ellps_id, ellps in pj_ellps.items() |
21 | 21 | } |
22 | 22 | |
23 | 23 | |
24 | cdef decode_or_undefined(const char* instring): | |
24 | cdef str decode_or_undefined(const char* instring): | |
25 | 25 | pystr = cstrdecode(instring) |
26 | 26 | if pystr is None: |
27 | 27 | return "undefined" |
28 | 28 | return pystr |
29 | 29 | |
30 | 30 | |
31 | def is_wkt(proj_string): | |
31 | def is_wkt(str proj_string not None): | |
32 | 32 | """ |
33 | 33 | .. versionadded:: 2.0.0 |
34 | 34 | |
43 | 43 | ------- |
44 | 44 | bool: True if the string is in the Well-Known Text format |
45 | 45 | """ |
46 | tmp_string = cstrencode(proj_string) | |
47 | return proj_context_guess_wkt_dialect(NULL, tmp_string) != PJ_GUESSED_NOT_WKT | |
48 | ||
49 | ||
50 | def is_proj(proj_string): | |
46 | cdef bytes b_proj_string = cstrencode(proj_string) | |
47 | return proj_context_guess_wkt_dialect(NULL, b_proj_string) != PJ_GUESSED_NOT_WKT | |
48 | ||
49 | ||
50 | def is_proj(str proj_string not None): | |
51 | 51 | """ |
52 | 52 | .. versionadded:: 2.2.2 |
53 | 53 | |
68 | 68 | cdef _to_wkt( |
69 | 69 | PJ_CONTEXT* context, |
70 | 70 | PJ* projobj, |
71 | version=WktVersion.WKT2_2019, | |
72 | pretty=False | |
71 | object version=WktVersion.WKT2_2019, | |
72 | bint pretty=False | |
73 | 73 | ): |
74 | 74 | """ |
75 | 75 | Convert a PJ object to a wkt string. |
100 | 100 | wkt_out_type = supported_wkt_types[WktVersion.create(version)] |
101 | 101 | |
102 | 102 | cdef const char* options_wkt[2] |
103 | multiline = b"MULTILINE=NO" | |
103 | cdef bytes multiline = b"MULTILINE=NO" | |
104 | 104 | if pretty: |
105 | 105 | multiline = b"MULTILINE=YES" |
106 | 106 | options_wkt[0] = multiline |
119 | 119 | cdef _to_proj4( |
120 | 120 | PJ_CONTEXT* context, |
121 | 121 | PJ* projobj, |
122 | version, | |
123 | pretty, | |
122 | object version, | |
123 | bint pretty, | |
124 | 124 | ): |
125 | 125 | """ |
126 | 126 | Convert the projection to a PROJ string. |
146 | 146 | proj_out_type = supported_prj_types[ProjVersion.create(version)] |
147 | 147 | |
148 | 148 | cdef const char* options[2] |
149 | multiline = b"MULTILINE=NO" | |
149 | cdef bytes multiline = b"MULTILINE=NO" | |
150 | 150 | if pretty: |
151 | 151 | multiline = b"MULTILINE=YES" |
152 | 152 | options[0] = multiline |
164 | 164 | return cstrdecode(proj_string) |
165 | 165 | |
166 | 166 | |
167 | cdef _get_concatenated_operations(PJ_CONTEXT* context, PJ* concatenated_operation): | |
167 | cdef tuple _get_concatenated_operations( | |
168 | PJ_CONTEXT* context, PJ* concatenated_operation | |
169 | ): | |
168 | 170 | """ |
169 | 171 | For a PJ* of type concatenated operation, get the operations |
170 | 172 | """ |
189 | 191 | |
190 | 192 | cdef PJ * _from_name( |
191 | 193 | PJ_CONTEXT* context, |
192 | name_string, | |
193 | auth_name, | |
194 | str name_string, | |
195 | str auth_name, | |
194 | 196 | PJ_TYPE pj_type, |
195 | 197 | ): |
196 | 198 | """ |
214 | 216 | """ |
215 | 217 | cdef PJ_TYPE[1] pj_types = [pj_type] |
216 | 218 | cdef char* c_auth_name = NULL |
219 | cdef bytes b_auth_name | |
217 | 220 | if auth_name is not None: |
218 | 221 | b_auth_name = cstrencode(auth_name) |
219 | 222 | c_auth_name = b_auth_name |
236 | 239 | return datum_pj |
237 | 240 | |
238 | 241 | |
239 | def _load_proj_json(in_proj_json): | |
242 | def _load_proj_json(str in_proj_json): | |
240 | 243 | try: |
241 | 244 | return json.loads(in_proj_json) |
242 | 245 | except ValueError: |
356 | 359 | cdef const char* proj_name = proj_get_name(self.projobj) |
357 | 360 | self.name = decode_or_undefined(proj_name) |
358 | 361 | cdef const char* scope = proj_get_scope(self.projobj) |
359 | if scope != NULL: | |
360 | py_scope = pystrdecode(scope) | |
361 | self._scope = py_scope if py_scope else self._scope | |
362 | if scope != NULL and scope != "": | |
363 | self._scope = scope | |
362 | 364 | cdef const char* remarks = proj_get_remarks(self.projobj) |
363 | if remarks != NULL: | |
364 | py_remarks = pystrdecode(remarks) | |
365 | self._remarks = py_remarks if py_remarks else self._remarks | |
365 | if remarks != NULL and remarks != "": | |
366 | self._remarks = remarks | |
366 | 367 | |
367 | 368 | @property |
368 | 369 | def remarks(self): |
414 | 415 | """ |
415 | 416 | return _to_wkt(self.context, self.projobj, version, pretty=pretty) |
416 | 417 | |
417 | def to_json(self, pretty=False, indentation=2): | |
418 | def to_json(self, bint pretty=False, int indentation=2): | |
418 | 419 | """ |
419 | 420 | .. versionadded:: 2.4.0 |
420 | 421 | |
535 | 536 | return self._is_equivalent(other) |
536 | 537 | |
537 | 538 | |
538 | _COORD_SYSTEM_TYPE_MAP = { | |
539 | cdef dict _COORD_SYSTEM_TYPE_MAP = { | |
539 | 540 | PJ_CS_TYPE_UNKNOWN: "unknown", |
540 | 541 | PJ_CS_TYPE_CARTESIAN: "cartesian", |
541 | 542 | PJ_CS_TYPE_ELLIPSOIDAL: "ellipsoidal", |
606 | 607 | return self._axis_list |
607 | 608 | |
608 | 609 | @staticmethod |
609 | def from_string(coordinate_system_string): | |
610 | def from_string(str coordinate_system_string not None): | |
610 | 611 | """ |
611 | 612 | .. versionadded:: 2.5.0 |
612 | 613 | |
636 | 637 | pyproj_context_destroy(context) |
637 | 638 | raise CRSError( |
638 | 639 | "Invalid coordinate system string: " |
639 | f"{pystrdecode(coordinate_system_string)}" | |
640 | f"{coordinate_system_string}" | |
640 | 641 | ) |
641 | 642 | CRSError.clear() |
642 | 643 | return CoordinateSystem.create(context, coordinate_system_pj) |
643 | 644 | |
644 | 645 | @staticmethod |
645 | def from_json_dict(coordinate_system_dict): | |
646 | def from_json_dict(dict coordinate_system_dict not None): | |
646 | 647 | """ |
647 | 648 | .. versionadded:: 2.5.0 |
648 | 649 | |
662 | 663 | ) |
663 | 664 | |
664 | 665 | @staticmethod |
665 | def from_json(coordinate_system_json_str): | |
666 | def from_json(str coordinate_system_json_str not None): | |
666 | 667 | """ |
667 | 668 | .. versionadded:: 2.5.0 |
668 | 669 | |
681 | 682 | _load_proj_json(coordinate_system_json_str) |
682 | 683 | ) |
683 | 684 | |
684 | def to_cf(self, rotated_pole=False): | |
685 | def to_cf(self, bint rotated_pole=False): | |
685 | 686 | """ |
686 | 687 | .. versionadded:: 3.0.0 |
687 | 688 | |
815 | 816 | return ellips |
816 | 817 | |
817 | 818 | @staticmethod |
818 | def from_authority(auth_name, code): | |
819 | def from_authority(str auth_name not None, code not None): | |
819 | 820 | """ |
820 | 821 | .. versionadded:: 2.2.0 |
821 | 822 | |
849 | 850 | return Ellipsoid.create(context, ellipsoid_pj) |
850 | 851 | |
851 | 852 | @staticmethod |
852 | def from_epsg(code): | |
853 | def from_epsg(code not None): | |
853 | 854 | """ |
854 | 855 | .. versionadded:: 2.2.0 |
855 | 856 | |
867 | 868 | return Ellipsoid.from_authority("EPSG", code) |
868 | 869 | |
869 | 870 | @staticmethod |
870 | def _from_string(ellipsoid_string): | |
871 | def _from_string(str ellipsoid_string not None): | |
871 | 872 | """ |
872 | 873 | Create an Ellipsoid from a string. |
873 | 874 | |
895 | 896 | proj_destroy(ellipsoid_pj) |
896 | 897 | pyproj_context_destroy(context) |
897 | 898 | raise CRSError( |
898 | f"Invalid ellipsoid string: {pystrdecode(ellipsoid_string)}" | |
899 | f"Invalid ellipsoid string: {ellipsoid_string}" | |
899 | 900 | ) |
900 | 901 | CRSError.clear() |
901 | 902 | return Ellipsoid.create(context, ellipsoid_pj) |
902 | 903 | |
903 | 904 | @staticmethod |
904 | def from_string(ellipsoid_string): | |
905 | def from_string(str ellipsoid_string not None): | |
905 | 906 | """ |
906 | 907 | .. versionadded:: 2.2.0 |
907 | 908 | |
932 | 933 | raise crs_err |
933 | 934 | |
934 | 935 | @staticmethod |
935 | def from_json_dict(ellipsoid_dict): | |
936 | def from_json_dict(dict ellipsoid_dict not None): | |
936 | 937 | """ |
937 | 938 | .. versionadded:: 2.4.0 |
938 | 939 | |
950 | 951 | return Ellipsoid._from_string(json.dumps(ellipsoid_dict, cls=NumpyEncoder)) |
951 | 952 | |
952 | 953 | @staticmethod |
953 | def from_json(ellipsoid_json_str): | |
954 | def from_json(str ellipsoid_json_str not None): | |
954 | 955 | """ |
955 | 956 | .. versionadded:: 2.4.0 |
956 | 957 | |
969 | 970 | |
970 | 971 | @staticmethod |
971 | 972 | def _from_name( |
972 | ellipsoid_name, | |
973 | auth_name, | |
973 | str ellipsoid_name, | |
974 | str auth_name, | |
974 | 975 | ): |
975 | 976 | """ |
976 | 977 | .. versionadded:: 2.5.0 |
998 | 999 | ) |
999 | 1000 | if ellipsoid_pj == NULL: |
1000 | 1001 | pyproj_context_destroy(context) |
1001 | raise CRSError(f"Invalid ellipsoid name: {pystrdecode(ellipsoid_name)}") | |
1002 | raise CRSError(f"Invalid ellipsoid name: {ellipsoid_name}") | |
1002 | 1003 | CRSError.clear() |
1003 | 1004 | return Ellipsoid.create(context, ellipsoid_pj) |
1004 | 1005 | |
1005 | 1006 | @staticmethod |
1006 | 1007 | def from_name( |
1007 | ellipsoid_name, | |
1008 | auth_name=None, | |
1008 | str ellipsoid_name not None, | |
1009 | str auth_name=None, | |
1009 | 1010 | ): |
1010 | 1011 | """ |
1011 | 1012 | .. versionadded:: 2.5.0 |
1093 | 1094 | return prime_meridian |
1094 | 1095 | |
1095 | 1096 | @staticmethod |
1096 | def from_authority(auth_name, code): | |
1097 | def from_authority(str auth_name not None, code not None): | |
1097 | 1098 | """ |
1098 | 1099 | .. versionadded:: 2.2.0 |
1099 | 1100 | |
1127 | 1128 | return PrimeMeridian.create(context, prime_meridian_pj) |
1128 | 1129 | |
1129 | 1130 | @staticmethod |
1130 | def from_epsg(code): | |
1131 | def from_epsg(code not None): | |
1131 | 1132 | """ |
1132 | 1133 | .. versionadded:: 2.2.0 |
1133 | 1134 | |
1145 | 1146 | return PrimeMeridian.from_authority("EPSG", code) |
1146 | 1147 | |
1147 | 1148 | @staticmethod |
1148 | def _from_string(prime_meridian_string): | |
1149 | def _from_string(str prime_meridian_string not None): | |
1149 | 1150 | """ |
1150 | 1151 | Create an PrimeMeridian from a string. |
1151 | 1152 | |
1176 | 1177 | proj_destroy(prime_meridian_pj) |
1177 | 1178 | pyproj_context_destroy(context) |
1178 | 1179 | raise CRSError( |
1179 | f"Invalid prime meridian string: {pystrdecode(prime_meridian_string)}" | |
1180 | f"Invalid prime meridian string: {prime_meridian_string}" | |
1180 | 1181 | ) |
1181 | 1182 | CRSError.clear() |
1182 | 1183 | return PrimeMeridian.create(context, prime_meridian_pj) |
1183 | 1184 | |
1184 | 1185 | @staticmethod |
1185 | def from_string(prime_meridian_string): | |
1186 | def from_string(str prime_meridian_string not None): | |
1186 | 1187 | """ |
1187 | 1188 | .. versionadded:: 2.2.0 |
1188 | 1189 | |
1213 | 1214 | raise crs_err |
1214 | 1215 | |
1215 | 1216 | @staticmethod |
1216 | def from_json_dict(prime_meridian_dict): | |
1217 | def from_json_dict(dict prime_meridian_dict not None): | |
1217 | 1218 | """ |
1218 | 1219 | .. versionadded:: 2.4.0 |
1219 | 1220 | |
1233 | 1234 | ) |
1234 | 1235 | |
1235 | 1236 | @staticmethod |
1236 | def from_json(prime_meridian_json_str): | |
1237 | def from_json(str prime_meridian_json_str not None): | |
1237 | 1238 | """ |
1238 | 1239 | .. versionadded:: 2.4.0 |
1239 | 1240 | |
1252 | 1253 | |
1253 | 1254 | @staticmethod |
1254 | 1255 | def from_name( |
1255 | prime_meridian_name, | |
1256 | auth_name=None, | |
1256 | str prime_meridian_name not None, | |
1257 | str auth_name=None, | |
1257 | 1258 | ): |
1258 | 1259 | """ |
1259 | 1260 | .. versionadded:: 2.5.0 |
1285 | 1286 | if prime_meridian_pj == NULL: |
1286 | 1287 | pyproj_context_destroy(context) |
1287 | 1288 | raise CRSError( |
1288 | f"Invalid prime meridian name: {pystrdecode(prime_meridian_name)}" | |
1289 | f"Invalid prime meridian name: {prime_meridian_name}" | |
1289 | 1290 | ) |
1290 | 1291 | CRSError.clear() |
1291 | 1292 | return PrimeMeridian.create(context, prime_meridian_pj) |
1292 | 1293 | |
1293 | 1294 | |
1294 | _DATUM_TYPE_MAP = { | |
1295 | cdef dict _DATUM_TYPE_MAP = { | |
1295 | 1296 | PJ_TYPE_GEODETIC_REFERENCE_FRAME: "Geodetic Reference Frame", |
1296 | 1297 | PJ_TYPE_DYNAMIC_GEODETIC_REFERENCE_FRAME: "Dynamic Geodetic Reference Frame", |
1297 | 1298 | PJ_TYPE_VERTICAL_REFERENCE_FRAME: "Vertical Reference Frame", |
1302 | 1303 | PJ_TYPE_PARAMETRIC_DATUM: "Parametric Datum", |
1303 | 1304 | } |
1304 | 1305 | |
1305 | _PJ_DATUM_TYPE_MAP = { | |
1306 | cdef dict _PJ_DATUM_TYPE_MAP = { | |
1306 | 1307 | DatumType.DATUM_ENSEMBLE: PJ_TYPE_DATUM_ENSEMBLE, |
1307 | 1308 | DatumType.GEODETIC_REFERENCE_FRAME: PJ_TYPE_GEODETIC_REFERENCE_FRAME, |
1308 | 1309 | DatumType.DYNAMIC_GEODETIC_REFERENCE_FRAME: |
1344 | 1345 | return datum |
1345 | 1346 | |
1346 | 1347 | @staticmethod |
1347 | def _from_authority(auth_name, code, PJ_CATEGORY category): | |
1348 | def _from_authority(str auth_name not None, code not None, PJ_CATEGORY category): | |
1348 | 1349 | """ |
1349 | 1350 | Create a Datum from an authority code. |
1350 | 1351 | |
1363 | 1364 | |
1364 | 1365 | cdef PJ* datum_pj = proj_create_from_database( |
1365 | 1366 | context, |
1366 | cstrencode(str(auth_name)), | |
1367 | cstrencode(auth_name), | |
1367 | 1368 | cstrencode(str(code)), |
1368 | 1369 | category, |
1369 | 1370 | False, |
1377 | 1378 | return Datum.create(context, datum_pj) |
1378 | 1379 | |
1379 | 1380 | @staticmethod |
1380 | def from_authority(auth_name, code): | |
1381 | def from_authority(str auth_name not None, code not None): | |
1381 | 1382 | """ |
1382 | 1383 | Create a Datum from an authority code. |
1383 | 1384 | |
1398 | 1399 | return Datum._from_authority(auth_name, code, PJ_CATEGORY_DATUM) |
1399 | 1400 | |
1400 | 1401 | @staticmethod |
1401 | def from_epsg(code): | |
1402 | def from_epsg(code not None): | |
1402 | 1403 | """ |
1403 | 1404 | Create a Datum from an EPSG code. |
1404 | 1405 | |
1414 | 1415 | return Datum.from_authority("EPSG", code) |
1415 | 1416 | |
1416 | 1417 | @staticmethod |
1417 | def _from_string(datum_string): | |
1418 | def _from_string(str datum_string not None): | |
1418 | 1419 | """ |
1419 | 1420 | Create a Datum from a string. |
1420 | 1421 | |
1445 | 1446 | ): |
1446 | 1447 | proj_destroy(datum_pj) |
1447 | 1448 | pyproj_context_destroy(context) |
1448 | raise CRSError(f"Invalid datum string: {pystrdecode(datum_string)}") | |
1449 | raise CRSError(f"Invalid datum string: {datum_string}") | |
1449 | 1450 | CRSError.clear() |
1450 | 1451 | return Datum.create(context, datum_pj) |
1451 | 1452 | |
1452 | 1453 | @staticmethod |
1453 | def from_string(datum_string): | |
1454 | def from_string(str datum_string not None): | |
1454 | 1455 | """ |
1455 | 1456 | Create a Datum from a string. |
1456 | 1457 | |
1481 | 1482 | |
1482 | 1483 | @staticmethod |
1483 | 1484 | def _from_name( |
1484 | datum_name, | |
1485 | auth_name, | |
1486 | datum_type, | |
1485 | str datum_name, | |
1486 | str auth_name, | |
1487 | object datum_type, | |
1487 | 1488 | ): |
1488 | 1489 | """ |
1489 | 1490 | .. versionadded:: 2.5.0 |
1514 | 1515 | ) |
1515 | 1516 | if datum_pj == NULL: |
1516 | 1517 | pyproj_context_destroy(context) |
1517 | raise CRSError(f"Invalid datum name: {pystrdecode(datum_name)}") | |
1518 | raise CRSError(f"Invalid datum name: {datum_name}") | |
1518 | 1519 | CRSError.clear() |
1519 | 1520 | return Datum.create(context, datum_pj) |
1520 | 1521 | |
1521 | 1522 | @staticmethod |
1522 | 1523 | def from_name( |
1523 | datum_name, | |
1524 | auth_name=None, | |
1524 | str datum_name not None, | |
1525 | str auth_name=None, | |
1525 | 1526 | datum_type=None, |
1526 | 1527 | ): |
1527 | 1528 | """ |
1570 | 1571 | ) |
1571 | 1572 | |
1572 | 1573 | @staticmethod |
1573 | def from_json_dict(datum_dict): | |
1574 | def from_json_dict(dict datum_dict not None): | |
1574 | 1575 | """ |
1575 | 1576 | .. versionadded:: 2.4.0 |
1576 | 1577 | |
1588 | 1589 | return Datum._from_string(json.dumps(datum_dict, cls=NumpyEncoder)) |
1589 | 1590 | |
1590 | 1591 | @staticmethod |
1591 | def from_json(datum_json_str): | |
1592 | def from_json(str datum_json_str not None): | |
1592 | 1593 | """ |
1593 | 1594 | .. versionadded:: 2.4.0 |
1594 | 1595 | |
1823 | 1824 | ) |
1824 | 1825 | |
1825 | 1826 | |
1826 | _COORDINATE_OPERATION_TYPE_MAP = { | |
1827 | cdef dict _COORDINATE_OPERATION_TYPE_MAP = { | |
1827 | 1828 | PJ_TYPE_UNKNOWN: "Unknown", |
1828 | 1829 | PJ_TYPE_CONVERSION: "Conversion", |
1829 | 1830 | PJ_TYPE_TRANSFORMATION: "Transformation", |
1831 | 1832 | PJ_TYPE_OTHER_COORDINATE_OPERATION: "Other Coordinate Operation", |
1832 | 1833 | } |
1833 | 1834 | |
1834 | _PJ_COORDINATE_OPERATION_TYPE_MAP = { | |
1835 | cdef dict _PJ_COORDINATE_OPERATION_TYPE_MAP = { | |
1835 | 1836 | CoordinateOperationType.CONVERSION: PJ_TYPE_CONVERSION, |
1836 | 1837 | CoordinateOperationType.TRANSFORMATION: PJ_TYPE_TRANSFORMATION, |
1837 | 1838 | CoordinateOperationType.CONCATENATED_OPERATION: PJ_TYPE_CONCATENATED_OPERATION, |
1924 | 1925 | return coord_operation |
1925 | 1926 | |
1926 | 1927 | @staticmethod |
1927 | def from_authority(auth_name, code, use_proj_alternative_grid_names=False): | |
1928 | def from_authority( | |
1929 | str auth_name not None, | |
1930 | code not None, | |
1931 | bint use_proj_alternative_grid_names=False, | |
1932 | ): | |
1928 | 1933 | """ |
1929 | 1934 | Create a CoordinateOperation from an authority code. |
1930 | 1935 | |
1958 | 1963 | return CoordinateOperation.create(context, coord_operation_pj) |
1959 | 1964 | |
1960 | 1965 | @staticmethod |
1961 | def from_epsg(code, use_proj_alternative_grid_names=False): | |
1966 | def from_epsg(code not None, bint use_proj_alternative_grid_names= False): | |
1962 | 1967 | """ |
1963 | 1968 | Create a CoordinateOperation from an EPSG code. |
1964 | 1969 | |
1978 | 1983 | ) |
1979 | 1984 | |
1980 | 1985 | @staticmethod |
1981 | def _from_string(coordinate_operation_string): | |
1986 | def _from_string(str coordinate_operation_string not None): | |
1982 | 1987 | """ |
1983 | 1988 | Create a CoordinateOperation from a string. |
1984 | 1989 | |
2012 | 2017 | pyproj_context_destroy(context) |
2013 | 2018 | raise CRSError( |
2014 | 2019 | "Invalid coordinate operation string: " |
2015 | f"{pystrdecode(coordinate_operation_string)}" | |
2020 | f"{coordinate_operation_string}" | |
2016 | 2021 | ) |
2017 | 2022 | CRSError.clear() |
2018 | 2023 | return CoordinateOperation.create(context, coord_operation_pj) |
2019 | 2024 | |
2020 | 2025 | @staticmethod |
2021 | def from_string(coordinate_operation_string): | |
2026 | def from_string(str coordinate_operation_string not None): | |
2022 | 2027 | """ |
2023 | 2028 | Create a CoordinateOperation from a string. |
2024 | 2029 | |
2045 | 2050 | raise crs_err |
2046 | 2051 | |
2047 | 2052 | @staticmethod |
2048 | def from_json_dict(coordinate_operation_dict): | |
2053 | def from_json_dict(dict coordinate_operation_dict not None): | |
2049 | 2054 | """ |
2050 | 2055 | Create CoordinateOperation from a JSON dictionary. |
2051 | 2056 | |
2065 | 2070 | ) |
2066 | 2071 | |
2067 | 2072 | @staticmethod |
2068 | def from_json(coordinate_operation_json_str): | |
2073 | def from_json(str coordinate_operation_json_str not None): | |
2069 | 2074 | """ |
2070 | 2075 | Create CoordinateOperation from a JSON string. |
2071 | 2076 | |
2086 | 2091 | |
2087 | 2092 | @staticmethod |
2088 | 2093 | def from_name( |
2089 | coordinate_operation_name, | |
2090 | auth_name=None, | |
2091 | coordinate_operation_type=CoordinateOperationType.CONVERSION, | |
2094 | str coordinate_operation_name not None, | |
2095 | str auth_name=None, | |
2096 | coordinate_operation_type not None=CoordinateOperationType.CONVERSION, | |
2092 | 2097 | ): |
2093 | 2098 | """ |
2094 | 2099 | .. versionadded:: 2.5.0 |
2127 | 2132 | pyproj_context_destroy(context) |
2128 | 2133 | raise CRSError( |
2129 | 2134 | "Invalid coordinate operation name: " |
2130 | f"{pystrdecode(coordinate_operation_name)}" | |
2135 | f"{coordinate_operation_name}" | |
2131 | 2136 | ) |
2132 | 2137 | CRSError.clear() |
2133 | 2138 | return CoordinateOperation.create(context, coordinate_operation_pj) |
2199 | 2204 | self._area_of_use = create_area_of_use(self.context, self.projobj) |
2200 | 2205 | return self._area_of_use |
2201 | 2206 | |
2202 | def to_proj4(self, version=ProjVersion.PROJ_5, pretty=False): | |
2207 | def to_proj4(self, version not None=ProjVersion.PROJ_5, bint pretty=False): | |
2203 | 2208 | """ |
2204 | 2209 | Convert the projection to a PROJ string. |
2205 | 2210 | |
2297 | 2302 | """ |
2298 | 2303 | |
2299 | 2304 | |
2300 | _CRS_TYPE_MAP = { | |
2305 | cdef dict _CRS_TYPE_MAP = { | |
2301 | 2306 | PJ_TYPE_UNKNOWN: "Unknown CRS", |
2302 | 2307 | PJ_TYPE_CRS: "CRS", |
2303 | 2308 | PJ_TYPE_GEODETIC_CRS: "Geodetic CRS", |
2335 | 2340 | self._coordinate_operation = None |
2336 | 2341 | self.type_name = "undefined" |
2337 | 2342 | |
2338 | def __init__(self, proj_string): | |
2343 | def __init__(self, const char *proj_string): | |
2339 | 2344 | self.context = pyproj_context_create() |
2340 | 2345 | # initialize projection |
2341 | 2346 | self.projobj = proj_create( |
2342 | 2347 | self.context, |
2343 | cstrencode(proj_string), | |
2348 | proj_string, | |
2344 | 2349 | ) |
2345 | 2350 | if self.projobj == NULL: |
2346 | raise CRSError(f"Invalid projection: {pystrdecode(proj_string)}") | |
2351 | raise CRSError(f"Invalid projection: {proj_string}") | |
2347 | 2352 | # make sure the input is a CRS |
2348 | 2353 | if not proj_is_crs(self.projobj): |
2349 | 2354 | raise CRSError(f"Input is not a CRS: {proj_string}") |
2350 | 2355 | # set proj information |
2351 | self.srs = pystrdecode(proj_string) | |
2356 | self.srs = proj_string | |
2352 | 2357 | self._type = proj_get_type(self.projobj) |
2353 | 2358 | self.type_name = _CRS_TYPE_MAP[self._type] |
2354 | 2359 | self._set_base_info() |
2666 | 2671 | ) |
2667 | 2672 | return _to_proj4(self.context, self.projobj, version=version, pretty=False) |
2668 | 2673 | |
2669 | def to_epsg(self, min_confidence=70): | |
2674 | def to_epsg(self, int min_confidence=70): | |
2670 | 2675 | """ |
2671 | 2676 | Return the EPSG code best matching the CRS |
2672 | 2677 | or None if it a match is not found. |
2709 | 2714 | return int(auth_info[1]) |
2710 | 2715 | return None |
2711 | 2716 | |
2712 | def to_authority(self, auth_name=None, min_confidence=70): | |
2717 | def to_authority(self, str auth_name=None, int min_confidence=70): | |
2713 | 2718 | """ |
2714 | 2719 | .. versionadded:: 2.2.0 |
2715 | 2720 | |
2755 | 2760 | except IndexError: |
2756 | 2761 | return None |
2757 | 2762 | |
2758 | def list_authority(self, auth_name=None, min_confidence=70): | |
2763 | def list_authority(self, str auth_name=None, int min_confidence=70): | |
2759 | 2764 | """ |
2760 | 2765 | .. versionadded:: 3.2.0 |
2761 | 2766 | |
2796 | 2801 | # get list of possible matching projections |
2797 | 2802 | cdef PJ_OBJ_LIST *proj_list = NULL |
2798 | 2803 | cdef int *c_out_confidence_list = NULL |
2799 | cdef int out_confidence = -9999 | |
2800 | 2804 | cdef int num_proj_objects = -9999 |
2805 | cdef bytes b_auth_name | |
2801 | 2806 | cdef char *user_auth_name = NULL |
2802 | 2807 | cdef int iii = 0 |
2803 | 2808 | |
2835 | 2840 | if out_confidence_list[iii] < min_confidence: |
2836 | 2841 | continue |
2837 | 2842 | proj = proj_list_get(self.context, proj_list, iii) |
2838 | code = proj_get_id_code(proj, iii) | |
2839 | out_auth_name = proj_get_id_auth_name(proj, iii) | |
2843 | code = proj_get_id_code(proj, 0) | |
2844 | out_auth_name = proj_get_id_auth_name(proj, 0) | |
2840 | 2845 | if out_auth_name != NULL and code != NULL: |
2841 | 2846 | authority_list.append( |
2842 | 2847 | AuthorityMatchInfo( |
2843 | pystrdecode(out_auth_name), | |
2844 | pystrdecode(code), | |
2848 | out_auth_name, | |
2849 | code, | |
2845 | 2850 | out_confidence_list[iii] |
2846 | 2851 | ) |
2847 | 2852 | ) |
2852 | 2857 | CRSError.clear() |
2853 | 2858 | return authority_list |
2854 | 2859 | |
2855 | def to_3d(self, name=None): | |
2860 | def to_3d(self, str name=None): | |
2856 | 2861 | """ |
2857 | 2862 | .. versionadded:: 3.1.0 |
2858 | 2863 | |
2872 | 2877 | ------- |
2873 | 2878 | _CRS |
2874 | 2879 | """ |
2875 | cdef char* name_3D = NULL | |
2880 | cdef char* c_name = NULL | |
2881 | cdef bytes b_name | |
2876 | 2882 | if name is not None: |
2877 | 2883 | b_name = cstrencode(name) |
2878 | name_3D = b_name | |
2884 | c_name = b_name | |
2879 | 2885 | |
2880 | 2886 | cdef PJ * projobj = proj_crs_promote_to_3D( |
2881 | self.context, name_3D, self.projobj | |
2887 | self.context, c_name, self.projobj | |
2882 | 2888 | ) |
2883 | 2889 | CRSError.clear() |
2884 | 2890 | if projobj == NULL: |
2889 | 2895 | proj_destroy(projobj) |
2890 | 2896 | return crs_3d |
2891 | 2897 | |
2892 | def _is_crs_property(self, property_name, property_types, sub_crs_index=0): | |
2898 | def _is_crs_property( | |
2899 | self, str property_name, tuple property_types, int sub_crs_index=0 | |
2900 | ): | |
2893 | 2901 | """ |
2894 | 2902 | .. versionadded:: 2.2.0 |
2895 | 2903 |
1 | 1 | import os |
2 | 2 | import warnings |
3 | 3 | |
4 | from libc.stdlib cimport free, malloc | |
5 | ||
6 | from pyproj._compat cimport cstrencode | |
7 | ||
8 | from pyproj.exceptions import DataDirError, ProjError | |
4 | 9 | from pyproj.utils import strtobool |
5 | ||
6 | from libc.stdlib cimport free, malloc | |
7 | ||
8 | from pyproj.compat import cstrencode, pystrdecode | |
9 | from pyproj.exceptions import DataDirError, ProjError | |
10 | 10 | |
11 | 11 | # for logging the internal PROJ messages |
12 | 12 | # https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library |
84 | 84 | str: |
85 | 85 | The user writable data directory. |
86 | 86 | """ |
87 | return pystrdecode(proj_context_get_user_writable_directory( | |
87 | return proj_context_get_user_writable_directory( | |
88 | 88 | PYPROJ_GLOBAL_CONTEXT, bool(create) |
89 | )) | |
89 | ) | |
90 | 90 | |
91 | 91 | |
92 | 92 | cdef void pyproj_log_function(void *user_data, int level, const char *error_msg) nogil: |
98 | 98 | # PROJ_DEBUG environment variable. |
99 | 99 | if level == PJ_LOG_ERROR: |
100 | 100 | with gil: |
101 | ProjError.internal_proj_error = pystrdecode(error_msg) | |
101 | ProjError.internal_proj_error = error_msg | |
102 | 102 | _LOGGER.debug(f"PROJ_ERROR: {ProjError.internal_proj_error}") |
103 | 103 | elif level == PJ_LOG_DEBUG: |
104 | 104 | with gil: |
105 | _LOGGER.debug(f"PROJ_DEBUG: {pystrdecode(error_msg)}") | |
105 | _LOGGER.debug(f"PROJ_DEBUG: {error_msg}") | |
106 | 106 | elif level == PJ_LOG_TRACE: |
107 | 107 | with gil: |
108 | _LOGGER.debug(f"PROJ_TRACE: {pystrdecode(error_msg)}") | |
108 | _LOGGER.debug(f"PROJ_TRACE: {error_msg}") | |
109 | 109 | |
110 | 110 | |
111 | 111 | cdef void set_context_data_dir(PJ_CONTEXT* context) except *: |
116 | 116 | |
117 | 117 | data_dir_list = get_data_dir().split(os.pathsep) |
118 | 118 | # the first path will always have the database |
119 | b_database_path = cstrencode(os.path.join(data_dir_list[0], "proj.db")) | |
119 | cdef bytes b_database_path = cstrencode(os.path.join(data_dir_list[0], "proj.db")) | |
120 | 120 | cdef const char* c_database_path = b_database_path |
121 | 121 | if not proj_context_set_database_path(context, c_database_path, NULL, NULL): |
122 | 122 | warnings.warn("pyproj unable to set database path.") |
124 | 124 | cdef const char **c_data_dir = <const char **>malloc( |
125 | 125 | (dir_list_len + 1) * sizeof(const char*) |
126 | 126 | ) |
127 | cdef bytes b_data_dir | |
127 | 128 | try: |
128 | 129 | for iii in range(dir_list_len): |
129 | 130 | b_data_dir = cstrencode(data_dir_list[iii]) |
191 | 192 | proj_context_destroy(context) |
192 | 193 | |
193 | 194 | |
194 | def _pyproj_global_context_initialize(): | |
195 | cpdef _pyproj_global_context_initialize(): | |
195 | 196 | pyproj_context_initialize(PYPROJ_GLOBAL_CONTEXT) |
196 | 197 | |
197 | 198 | |
198 | def _global_context_set_data_dir(): | |
199 | cpdef _global_context_set_data_dir(): | |
199 | 200 | set_context_data_dir(PYPROJ_GLOBAL_CONTEXT) |
2 | 2 | cimport cython |
3 | 3 | from libc.math cimport ceil, isnan, round |
4 | 4 | |
5 | from pyproj._compat cimport cstrencode, empty_array | |
6 | ||
5 | 7 | from collections import namedtuple |
6 | 8 | |
7 | from pyproj._compat import empty_array | |
8 | from pyproj.compat import cstrencode, pystrdecode | |
9 | 9 | from pyproj.enums import GeodIntermediateFlag |
10 | 10 | from pyproj.exceptions import GeodError |
11 | 11 | |
72 | 72 | # convert 'a' only for initstring |
73 | 73 | a_str = int(a) if a.is_integer() else a |
74 | 74 | f_str = int(f) if f.is_integer() else f |
75 | self.initstring = pystrdecode(cstrencode(f"+a={a_str} +f={f_str}")) | |
75 | self.initstring = f"+a={a_str} +f={f_str}" | |
76 | 76 | self.sphere = sphere |
77 | 77 | self.b = b |
78 | 78 | self.es = es |
3 | 3 | |
4 | 4 | from pyproj.utils import strtobool |
5 | 5 | |
6 | from pyproj._compat cimport cstrencode | |
6 | 7 | from pyproj._datadir cimport PYPROJ_GLOBAL_CONTEXT |
7 | 8 | |
8 | from pyproj.compat import cstrencode | |
9 | 9 | |
10 | ||
11 | def _set_ca_bundle_path(ca_bundle_path): | |
10 | def _set_ca_bundle_path(str ca_bundle_path): | |
12 | 11 | """ |
13 | 12 | Sets the path to the CA Bundle used by the `curl` |
14 | 13 | built into PROJ. |
0 | 0 | include "proj.pxi" |
1 | ||
2 | from pyproj.compat import pystrdecode | |
3 | 1 | |
4 | 2 | from pyproj._datadir cimport PYPROJ_GLOBAL_CONTEXT |
5 | 3 | |
11 | 9 | str: |
12 | 10 | URL of the endpoint where PROJ grids are stored. |
13 | 11 | """ |
14 | return pystrdecode(proj_context_get_url_endpoint(PYPROJ_GLOBAL_CONTEXT)) | |
12 | return proj_context_get_url_endpoint(PYPROJ_GLOBAL_CONTEXT) |
0 | 0 | include "proj.pxi" |
1 | 1 | |
2 | from pyproj._crs cimport _CRS, Base | |
2 | from pyproj._crs cimport Base | |
3 | 3 | |
4 | 4 | |
5 | 5 | cdef class _TransformerGroup: |
6 | 6 | cdef PJ_CONTEXT* context |
7 | cdef readonly _transformers | |
8 | cdef readonly _unavailable_operations | |
9 | cdef readonly _best_available | |
7 | cdef readonly list _transformers | |
8 | cdef readonly list _unavailable_operations | |
9 | cdef readonly list _best_available | |
10 | 10 | |
11 | 11 | cdef class _Transformer(Base): |
12 | 12 | cdef PJ_PROJ_INFO proj_info |
13 | 13 | cdef readonly _area_of_use |
14 | cdef readonly type_name | |
15 | cdef readonly object _operations | |
14 | cdef readonly str type_name | |
15 | cdef readonly tuple _operations | |
16 | 16 | |
17 | 17 | @staticmethod |
18 | 18 | cdef _Transformer _from_pj( |
19 | 19 | PJ_CONTEXT* context, |
20 | 20 | PJ *transform_pj, |
21 | always_xy, | |
21 | bint always_xy, | |
22 | 22 | ) |
65 | 65 | ) -> str: ... |
66 | 66 | @staticmethod |
67 | 67 | def from_crs( |
68 | crs_from: str, | |
69 | crs_to: str, | |
68 | crs_from: bytes, | |
69 | crs_to: bytes, | |
70 | 70 | always_xy: bool = False, |
71 | 71 | area_of_interest: Optional[AreaOfInterest] = None, |
72 | 72 | authority: Optional[str] = None, |
73 | accuracy: Optional[float] = None, | |
73 | accuracy: Optional[str] = None, | |
74 | 74 | allow_ballpark: Optional[bool] = None, |
75 | 75 | ) -> "_Transformer": ... |
76 | 76 | @staticmethod |
77 | def from_pipeline(proj_pipeline: str) -> "_Transformer": ... | |
77 | def from_pipeline(proj_pipeline: bytes) -> "_Transformer": ... | |
78 | 78 | def _transform( |
79 | 79 | self, |
80 | 80 | inx: Any, |
7 | 7 | import warnings |
8 | 8 | from collections import namedtuple |
9 | 9 | |
10 | from pyproj._compat cimport cstrencode | |
10 | 11 | from pyproj._crs cimport ( |
11 | 12 | _CRS, |
12 | 13 | Base, |
19 | 20 | |
20 | 21 | from pyproj._datadir import _LOGGER |
21 | 22 | from pyproj.aoi import AreaOfInterest |
22 | from pyproj.compat import cstrencode, pystrdecode | |
23 | 23 | from pyproj.enums import ProjVersion, TransformDirection |
24 | 24 | from pyproj.exceptions import ProjError |
25 | 25 | |
28 | 28 | _AUTH_CODE_RE = re.compile(r"(?P<authority>\w+)\:(?P<code>\w+)") |
29 | 29 | |
30 | 30 | |
31 | cdef pyproj_errno_string(PJ_CONTEXT* ctx, int err): | |
31 | cdef str pyproj_errno_string(PJ_CONTEXT* ctx, int err): | |
32 | 32 | # https://github.com/pyproj4/pyproj/issues/760 |
33 | 33 | IF CTE_PROJ_VERSION_MAJOR >= 8: |
34 | return pystrdecode(proj_context_errno_string(ctx, err)) | |
34 | return proj_context_errno_string(ctx, err) | |
35 | 35 | ELSE: |
36 | return pystrdecode(proj_errno_string(err)) | |
37 | ||
38 | ||
39 | _PJ_DIRECTION_MAP = { | |
36 | return proj_errno_string(err) | |
37 | ||
38 | ||
39 | cdef dict _PJ_DIRECTION_MAP = { | |
40 | 40 | TransformDirection.FORWARD: PJ_FWD, |
41 | 41 | TransformDirection.INVERSE: PJ_INV, |
42 | 42 | TransformDirection.IDENT: PJ_IDENT, |
43 | 43 | } |
44 | 44 | |
45 | _TRANSFORMER_TYPE_MAP = { | |
45 | cdef dict _TRANSFORMER_TYPE_MAP = { | |
46 | 46 | PJ_TYPE_UNKNOWN: "Unknown Transformer", |
47 | 47 | PJ_TYPE_CONVERSION: "Conversion Transformer", |
48 | 48 | PJ_TYPE_TRANSFORMATION: "Transformation Transformer", |
119 | 119 | |
120 | 120 | def __init__( |
121 | 121 | self, |
122 | _CRS crs_from, | |
123 | _CRS crs_to, | |
124 | always_xy=False, | |
122 | _CRS crs_from not None, | |
123 | _CRS crs_to not None, | |
124 | bint always_xy=False, | |
125 | 125 | area_of_interest=None, |
126 | 126 | ): |
127 | 127 | """ |
236 | 236 | const char *source_crs_str, |
237 | 237 | const char *target_crs_str, |
238 | 238 | PJ_AREA *area, |
239 | authority, | |
240 | accuracy, | |
239 | str authority, | |
240 | str accuracy, | |
241 | 241 | allow_ballpark, |
242 | 242 | ): |
243 | 243 | """ |
262 | 262 | return NULL |
263 | 263 | |
264 | 264 | cdef const char* options[4] |
265 | cdef bytes b_authority | |
266 | cdef bytes b_accuracy | |
265 | 267 | cdef int options_index = 0 |
266 | 268 | options[0] = NULL |
267 | 269 | options[1] = NULL |
511 | 513 | |
512 | 514 | @property |
513 | 515 | def id(self): |
514 | return pystrdecode(self.proj_info.id) | |
516 | return self.proj_info.id | |
515 | 517 | |
516 | 518 | @property |
517 | 519 | def description(self): |
518 | return pystrdecode(self.proj_info.description) | |
520 | return self.proj_info.description | |
519 | 521 | |
520 | 522 | @property |
521 | 523 | def definition(self): |
522 | return pystrdecode(self.proj_info.definition) | |
524 | return self.proj_info.definition | |
523 | 525 | |
524 | 526 | @property |
525 | 527 | def has_inverse(self): |
565 | 567 | """ |
566 | 568 | return proj_context_is_network_enabled(self.context) == 1 |
567 | 569 | |
568 | def to_proj4(self, version=ProjVersion.PROJ_5, pretty=False): | |
570 | def to_proj4(self, version=ProjVersion.PROJ_5, bint pretty=False): | |
569 | 571 | """ |
570 | 572 | Convert the projection to a PROJ string. |
571 | 573 | |
590 | 592 | def from_crs( |
591 | 593 | const char* crs_from, |
592 | 594 | const char* crs_to, |
593 | always_xy=False, | |
595 | bint always_xy=False, | |
594 | 596 | area_of_interest=None, |
595 | authority=None, | |
596 | accuracy=None, | |
597 | str authority=None, | |
598 | str accuracy=None, | |
597 | 599 | allow_ballpark=None, |
598 | 600 | ): |
599 | 601 | """ |
648 | 650 | cdef _Transformer _from_pj( |
649 | 651 | PJ_CONTEXT* context, |
650 | 652 | PJ *transform_pj, |
651 | always_xy, | |
653 | bint always_xy, | |
652 | 654 | ): |
653 | 655 | """ |
654 | 656 | Create a Transformer from a PJ* object |
671 | 673 | cdef _Transformer transformer = _Transformer() |
672 | 674 | transformer.context = pyproj_context_create() |
673 | 675 | |
674 | auth_match = _AUTH_CODE_RE.match(pystrdecode(proj_pipeline.strip())) | |
676 | auth_match = _AUTH_CODE_RE.match(proj_pipeline.strip()) | |
675 | 677 | if auth_match: |
676 | 678 | # attempt to create coordinate operation from AUTH:CODE |
677 | 679 | match_data = auth_match.groupdict() |
705 | 707 | proj_destroy(self.projobj) |
706 | 708 | self.projobj = always_xy_pj |
707 | 709 | |
708 | def _init_from_crs(self, always_xy): | |
710 | def _init_from_crs(self, bint always_xy): | |
709 | 711 | """ |
710 | 712 | Finish initializing transformer properties from CRS objects |
711 | 713 | """ |
0 | """ | |
1 | This module is for compatibility between string types | |
2 | """ | |
3 | ||
4 | ||
5 | def cstrencode(pystr): | |
6 | """ | |
7 | encode a string into bytes. If already bytes, do nothing. | |
8 | """ | |
9 | try: | |
10 | return pystr.encode("utf-8") | |
11 | except UnicodeDecodeError: | |
12 | return pystr.decode("utf-8").encode("utf-8") | |
13 | except AttributeError: | |
14 | return pystr # already bytes | |
15 | ||
16 | ||
17 | def pystrdecode(cstr): | |
18 | """ | |
19 | Decode a string to a python string. | |
20 | """ | |
21 | try: | |
22 | return cstr.decode("utf-8") | |
23 | except AttributeError: | |
24 | return cstr |
335 | 335 | return RotatedLatitudeLongitudeConversion( |
336 | 336 | o_lat_p=cf_params["grid_north_pole_latitude"], |
337 | 337 | o_lon_p=cf_params["grid_north_pole_longitude"], |
338 | lon_0=cf_params.get("north_pole_grid_longitude", 0.0), | |
338 | # https://github.com/pyproj4/pyproj/issues/927 | |
339 | lon_0=cf_params.get("north_pole_grid_longitude", 0.0) + 180, | |
339 | 340 | ) |
340 | 341 | |
341 | 342 | |
625 | 626 | "grid_mapping_name": "rotated_latitude_longitude", |
626 | 627 | "grid_north_pole_latitude": params["o_lat_p"], |
627 | 628 | "grid_north_pole_longitude": params["o_lon_p"], |
628 | "north_pole_grid_longitude": params["lon_0"], | |
629 | # https://github.com/pyproj4/pyproj/issues/927 | |
630 | "north_pole_grid_longitude": params["lon_0"] - 180, | |
631 | } | |
632 | ||
633 | ||
634 | def _pole_rotation_netcdf__to_cf(conversion): | |
635 | """ | |
636 | http://cfconventions.org/cf-conventions/cf-conventions.html#_rotated_pole | |
637 | ||
638 | https://github.com/OSGeo/PROJ/pull/2835 | |
639 | """ | |
640 | params = _to_dict(conversion) | |
641 | return { | |
642 | "grid_mapping_name": "rotated_latitude_longitude", | |
643 | "grid_north_pole_latitude": params[ | |
644 | "grid_north_pole_latitude_(netcdf_cf_convention)" | |
645 | ], | |
646 | "grid_north_pole_longitude": params[ | |
647 | "grid_north_pole_longitude_(netcdf_cf_convention)" | |
648 | ], | |
649 | "north_pole_grid_longitude": params[ | |
650 | "north_pole_grid_longitude_(netcdf_cf_convention)" | |
651 | ], | |
629 | 652 | } |
630 | 653 | |
631 | 654 | |
655 | 678 | "proj ob_tran o_proj=lonlat": _rotated_latitude_longitude__to_cf, |
656 | 679 | "proj ob_tran o_proj=latlon": _rotated_latitude_longitude__to_cf, |
657 | 680 | "proj ob_tran o_proj=latlong": _rotated_latitude_longitude__to_cf, |
681 | "pole rotation (netcdf cf convention)": _pole_rotation_netcdf__to_cf, | |
658 | 682 | } |
5 | 5 | |
6 | 6 | from libc.stdlib cimport free, malloc |
7 | 7 | |
8 | from pyproj._compat cimport cstrdecode | |
8 | from pyproj._compat cimport cstrdecode, cstrencode | |
9 | 9 | from pyproj._datadir cimport pyproj_context_create, pyproj_context_destroy |
10 | 10 | |
11 | 11 | from pyproj.aoi import AreaOfUse |
12 | from pyproj.compat import cstrencode, pystrdecode | |
13 | 12 | from pyproj.enums import PJType |
14 | 13 | |
15 | _PJ_TYPE_MAP = { | |
14 | ||
15 | cdef dict _PJ_TYPE_MAP = { | |
16 | 16 | PJType.UNKNOWN: PJ_TYPE_UNKNOWN, |
17 | 17 | PJType.ELLIPSOID: PJ_TYPE_ELLIPSOID, |
18 | 18 | PJType.PRIME_MERIDIAN: PJ_TYPE_PRIME_MERIDIAN, |
39 | 39 | PJType.CONCATENATED_OPERATION: PJ_TYPE_CONCATENATED_OPERATION, |
40 | 40 | PJType.OTHER_COORDINATE_OPERATION: PJ_TYPE_OTHER_COORDINATE_OPERATION, |
41 | 41 | } |
42 | _INV_PJ_TYPE_MAP = {value: key for key, value in _PJ_TYPE_MAP.items()} | |
42 | cdef dict _INV_PJ_TYPE_MAP = {value: key for key, value in _PJ_TYPE_MAP.items()} | |
43 | 43 | |
44 | 44 | |
45 | 45 | def get_authorities(): |
60 | 60 | try: |
61 | 61 | auth_list = [] |
62 | 62 | while proj_auth_list[iii] != NULL: |
63 | auth_list.append(pystrdecode(proj_auth_list[iii])) | |
63 | auth_list.append(proj_auth_list[iii]) | |
64 | 64 | iii += 1 |
65 | 65 | finally: |
66 | 66 | pyproj_context_destroy(context) |
68 | 68 | return auth_list |
69 | 69 | |
70 | 70 | |
71 | def get_codes(auth_name, pj_type, allow_deprecated=False): | |
71 | def get_codes(str auth_name not None, pj_type not None, bint allow_deprecated=False): | |
72 | 72 | """ |
73 | 73 | .. versionadded:: 2.4.0 |
74 | 74 | |
105 | 105 | try: |
106 | 106 | code_list = [] |
107 | 107 | while proj_code_list[iii] != NULL: |
108 | code_list.append(pystrdecode(proj_code_list[iii])) | |
108 | code_list.append(proj_code_list[iii]) | |
109 | 109 | iii += 1 |
110 | 110 | finally: |
111 | 111 | proj_string_list_destroy(proj_code_list) |
149 | 149 | |
150 | 150 | |
151 | 151 | def query_crs_info( |
152 | auth_name=None, | |
152 | str auth_name=None, | |
153 | 153 | pj_types=None, |
154 | 154 | area_of_interest=None, |
155 | contains=False, | |
156 | allow_deprecated=False, | |
155 | bint contains=False, | |
156 | bint allow_deprecated=False, | |
157 | 157 | ): |
158 | 158 | """ |
159 | 159 | .. versionadded:: 3.0.0 |
190 | 190 | cdef int result_count = 0 |
191 | 191 | cdef int pj_type_count = 0 |
192 | 192 | cdef int iii = 0 |
193 | cdef bytes b_auth_name | |
193 | 194 | if auth_name is not None: |
194 | 195 | b_auth_name = cstrencode(auth_name) |
195 | 196 | c_auth_name = b_auth_name |
244 | 245 | name=cstrdecode(crs_info_list[iii].area_name), |
245 | 246 | ) |
246 | 247 | code_list.append(CRSInfo( |
247 | auth_name=pystrdecode(crs_info_list[iii].auth_name), | |
248 | code=pystrdecode(crs_info_list[iii].code), | |
249 | name=pystrdecode(crs_info_list[iii].name), | |
248 | auth_name=crs_info_list[iii].auth_name, | |
249 | code=crs_info_list[iii].code, | |
250 | name=crs_info_list[iii].name, | |
250 | 251 | type=_INV_PJ_TYPE_MAP[crs_info_list[iii].type], |
251 | 252 | deprecated=bool(crs_info_list[iii].deprecated), |
252 | 253 | area_of_use=area_of_use, |
261 | 262 | |
262 | 263 | |
263 | 264 | def query_utm_crs_info( |
264 | datum_name=None, | |
265 | str datum_name=None, | |
265 | 266 | area_of_interest=None, |
266 | contains=False, | |
267 | bint contains=False, | |
267 | 268 | ): |
268 | 269 | """ |
269 | 270 | .. versionadded:: 3.0.0 |
340 | 341 | """ |
341 | 342 | |
342 | 343 | |
343 | def get_units_map(auth_name=None, category=None, allow_deprecated=False): | |
344 | def get_units_map(str auth_name=None, str category=None, bint allow_deprecated=False): | |
344 | 345 | """ |
345 | 346 | .. versionadded:: 2.2.0 |
346 | 347 | .. versionadded:: 3.0.0 query PROJ database. |
363 | 364 | """ |
364 | 365 | cdef const char* c_auth_name = NULL |
365 | 366 | cdef const char* c_category = NULL |
367 | cdef bytes b_auth_name | |
368 | cdef bytes b_category | |
366 | 369 | if auth_name is not None: |
367 | auth_name = cstrencode(auth_name) | |
368 | c_auth_name = auth_name | |
370 | b_auth_name = cstrencode(auth_name) | |
371 | c_auth_name = b_auth_name | |
369 | 372 | if category is not None: |
370 | category = cstrencode(category) | |
371 | c_category = category | |
373 | b_category = cstrencode(category) | |
374 | c_category = b_category | |
372 | 375 | |
373 | 376 | cdef int num_units = 0 |
374 | 377 | cdef PJ_CONTEXT* context = pyproj_context_create() |
384 | 387 | for iii in range(num_units): |
385 | 388 | proj_short_name = None |
386 | 389 | if db_unit_list[iii].proj_short_name != NULL: |
387 | proj_short_name = pystrdecode(db_unit_list[iii].proj_short_name) | |
388 | name = pystrdecode(db_unit_list[iii].name) | |
390 | proj_short_name = db_unit_list[iii].proj_short_name | |
391 | name = db_unit_list[iii].name | |
389 | 392 | units_map[name] = Unit( |
390 | auth_name=pystrdecode(db_unit_list[iii].auth_name), | |
391 | code=pystrdecode(db_unit_list[iii].code), | |
393 | auth_name=db_unit_list[iii].auth_name, | |
394 | code=db_unit_list[iii].code, | |
392 | 395 | name=name, |
393 | category=pystrdecode(db_unit_list[iii].category), | |
396 | category=db_unit_list[iii].category, | |
394 | 397 | conv_factor=db_unit_list[iii].conv_factor, |
395 | 398 | proj_short_name=proj_short_name, |
396 | 399 | deprecated=bool(db_unit_list[iii].deprecated), |
0 | 0 | include "proj.pxi" |
1 | ||
2 | from pyproj.compat import pystrdecode | |
3 | 1 | |
4 | 2 | |
5 | 3 | def get_proj_operations_map(): |
13 | 11 | cdef int iii = 0 |
14 | 12 | operations_map = {} |
15 | 13 | while proj_operations[iii].id != NULL: |
16 | operations_map[pystrdecode(proj_operations[iii].id)] = \ | |
17 | pystrdecode(proj_operations[iii].descr[0]).split("\n\t")[0] | |
14 | operations_map[proj_operations[iii].id] = \ | |
15 | proj_operations[iii].descr[0].split("\n\t")[0] | |
18 | 16 | iii += 1 |
19 | 17 | return operations_map |
20 | 18 | |
30 | 28 | cdef int iii = 0 |
31 | 29 | ellps_map = {} |
32 | 30 | while proj_ellps[iii].id != NULL: |
33 | major_key, major_val = pystrdecode(proj_ellps[iii].major).split("=") | |
34 | ell_key, ell_val = pystrdecode(proj_ellps[iii].ell).split("=") | |
35 | ellps_map[pystrdecode(proj_ellps[iii].id)] = { | |
31 | major_key, major_val = proj_ellps[iii].major.split("=") | |
32 | ell_key, ell_val = proj_ellps[iii].ell.split("=") | |
33 | ellps_map[proj_ellps[iii].id] = { | |
36 | 34 | major_key: float(major_val), |
37 | 35 | ell_key: float(ell_val), |
38 | "description": pystrdecode(proj_ellps[iii].name) | |
36 | "description": proj_ellps[iii].name | |
39 | 37 | } |
40 | 38 | iii += 1 |
41 | 39 | return ellps_map |
52 | 50 | cdef int iii = 0 |
53 | 51 | prime_meridians_map = {} |
54 | 52 | while prime_meridians[iii].id != NULL: |
55 | prime_meridians_map[pystrdecode(prime_meridians[iii].id)] = \ | |
56 | pystrdecode(prime_meridians[iii].defn) | |
53 | prime_meridians_map[prime_meridians[iii].id] = \ | |
54 | prime_meridians[iii].defn | |
57 | 55 | iii += 1 |
58 | 56 | return prime_meridians_map |
17 | 17 | import warnings |
18 | 18 | from typing import Any, Optional, Tuple, Type |
19 | 19 | |
20 | from pyproj._compat import cstrencode | |
20 | 21 | from pyproj._transformer import Factors |
21 | from pyproj.compat import pystrdecode | |
22 | 22 | from pyproj.crs import CRS |
23 | 23 | from pyproj.enums import TransformDirection |
24 | 24 | from pyproj.list import get_proj_operations_map |
130 | 130 | projstring = self.crs.to_proj4() or self.crs.srs |
131 | 131 | |
132 | 132 | self.srs = re.sub(r"\s\+?type=crs", "", projstring).strip() |
133 | super().__init__(TransformerFromPipeline(self.srs)) | |
133 | super().__init__(TransformerFromPipeline(cstrencode(self.srs))) | |
134 | 134 | |
135 | 135 | def __call__( |
136 | 136 | self, |
255 | 255 | >>> Proj("epsg:4326").definition_string() |
256 | 256 | 'proj=longlat datum=WGS84 no_defs ellps=WGS84 towgs84=0,0,0' |
257 | 257 | """ |
258 | return pystrdecode(self.definition) | |
258 | return self.definition | |
259 | 259 | |
260 | 260 | def to_latlong_def(self) -> Optional[str]: |
261 | 261 | """return the definition string of the geographic (lat/lon) |
17 | 17 | from typing import Any, Iterable, Iterator, List, Optional, Tuple, Union, overload |
18 | 18 | |
19 | 19 | from pyproj import CRS |
20 | from pyproj._compat import cstrencode | |
20 | 21 | from pyproj._crs import AreaOfUse, CoordinateOperation |
21 | 22 | from pyproj._transformer import ( # noqa: F401 pylint: disable=unused-import |
22 | 23 | AreaOfInterest, |
24 | 25 | _TransformerGroup, |
25 | 26 | proj_version_str, |
26 | 27 | ) |
27 | from pyproj.compat import cstrencode | |
28 | 28 | from pyproj.datadir import get_user_data_dir |
29 | 29 | from pyproj.enums import ProjVersion, TransformDirection, WktVersion |
30 | 30 | from pyproj.exceptions import ProjError |
79 | 79 | Generates a Cython _Transformer class from input CRS data. |
80 | 80 | """ |
81 | 81 | |
82 | crs_from: str | |
83 | crs_to: str | |
82 | crs_from: bytes | |
83 | crs_to: bytes | |
84 | 84 | always_xy: bool |
85 | 85 | area_of_interest: Optional[AreaOfInterest] |
86 | 86 | authority: Optional[str] |
87 | accuracy: Optional[float] | |
87 | accuracy: Optional[str] | |
88 | 88 | allow_ballpark: Optional[bool] |
89 | 89 | |
90 | 90 | def __call__(self) -> _Transformer: |
94 | 94 | _Transformer |
95 | 95 | """ |
96 | 96 | return _Transformer.from_crs( |
97 | cstrencode(self.crs_from), | |
98 | cstrencode(self.crs_to), | |
97 | self.crs_from, | |
98 | self.crs_to, | |
99 | 99 | always_xy=self.always_xy, |
100 | 100 | area_of_interest=self.area_of_interest, |
101 | 101 | authority=self.authority, |
112 | 112 | Generates a Cython _Transformer class from input pipeline data. |
113 | 113 | """ |
114 | 114 | |
115 | proj_pipeline: str | |
115 | proj_pipeline: bytes | |
116 | 116 | |
117 | 117 | def __call__(self) -> _Transformer: |
118 | 118 | """ |
120 | 120 | ------- |
121 | 121 | _Transformer |
122 | 122 | """ |
123 | return _Transformer.from_pipeline(cstrencode(self.proj_pipeline)) | |
123 | return _Transformer.from_pipeline(self.proj_pipeline) | |
124 | 124 | |
125 | 125 | |
126 | 126 | class TransformerGroup(_TransformerGroup): |
532 | 532 | |
533 | 533 | return Transformer( |
534 | 534 | TransformerFromCRS( |
535 | CRS.from_user_input(crs_from).srs, | |
536 | CRS.from_user_input(crs_to).srs, | |
535 | cstrencode(CRS.from_user_input(crs_from).srs), | |
536 | cstrencode(CRS.from_user_input(crs_to).srs), | |
537 | 537 | always_xy=always_xy, |
538 | 538 | area_of_interest=area_of_interest, |
539 | 539 | authority=authority, |
540 | accuracy=accuracy, | |
540 | accuracy=accuracy if accuracy is None else str(accuracy), | |
541 | 541 | allow_ballpark=allow_ballpark, |
542 | 542 | ) |
543 | 543 | ) |
573 | 573 | Transformer |
574 | 574 | |
575 | 575 | """ |
576 | return Transformer(TransformerFromPipeline(proj_pipeline)) | |
576 | return Transformer(TransformerFromPipeline(cstrencode(proj_pipeline))) | |
577 | 577 | |
578 | 578 | @overload |
579 | 579 | def transform( # pylint: disable=invalid-name |
658 | 658 | instead of returning a new array. This will fail if the input |
659 | 659 | is not an array in C order with the double data type. |
660 | 660 | |
661 | Example: | |
661 | Example | |
662 | -------- | |
662 | 663 | |
663 | 664 | >>> from pyproj import Transformer |
664 | 665 | >>> transformer = Transformer.from_crs("epsg:4326", "epsg:3857") |
768 | 769 | Default is :attr:`pyproj.enums.TransformDirection.FORWARD`. |
769 | 770 | |
770 | 771 | |
771 | Example: | |
772 | Example | |
773 | -------- | |
772 | 774 | |
773 | 775 | >>> from pyproj import Transformer |
774 | 776 | >>> transformer = Transformer.from_crs(4326, 2100) |
874 | 876 | Transform boundary densifying the edges to account for nonlinear |
875 | 877 | transformations along these edges and extracting the outermost bounds. |
876 | 878 | |
879 | If the destination CRS is geographic and right < left then the bounds | |
880 | crossed the antimeridian. In this scenario there are two polygons, | |
881 | one on each side of the antimeridian. The first polygon should be | |
882 | constructed with (left, bottom, 180, top) and the second with | |
883 | (-180, bottom, top, right). | |
884 | ||
885 | To construct the bounding polygons with shapely:: | |
886 | ||
887 | def bounding_polygon(left, bottom, right, top): | |
888 | if right < left: | |
889 | return shapely.geometry.MultiPolygon( | |
890 | [ | |
891 | shapely.geometry.box(left, bottom, 180, top), | |
892 | shapely.geometry.box(-180, bottom, right, top), | |
893 | ] | |
894 | ) | |
895 | return shapely.geometry.box(left, bottom, right, top) | |
896 | ||
897 | ||
877 | 898 | Parameters |
878 | 899 | ---------- |
879 | 900 | left: float |
5 | 5 | author = Jeff Whitaker |
6 | 6 | author_email = jeffrey.s.whitaker@noaa.gov |
7 | 7 | license = MIT |
8 | license-file = LICENSE | |
8 | license_file = LICENSE | |
9 | 9 | platform = any |
10 | 10 | keywords = GIS, map, geospatial, coordinate-systems, coordinate-transformation, cartographic-projection, geodesic |
11 | 11 | classifiers = |
109 | 109 | # Configure optional Cython coverage. |
110 | 110 | cythonize_options = { |
111 | 111 | "language_level": sys.version_info[0], |
112 | "compiler_directives": {"embedsignature": True}, | |
112 | "compiler_directives": { | |
113 | "c_string_type": "str", | |
114 | "c_string_encoding": "utf-8", | |
115 | "embedsignature": True, | |
116 | }, | |
113 | 117 | } |
114 | 118 | if os.environ.get("PYPROJ_FULL_COVERAGE"): |
115 | 119 | cythonize_options["compiler_directives"].update(linetrace=True) |
1441 | 1441 | pass |
1442 | 1442 | |
1443 | 1443 | |
1444 | def test_crs_multiprocess(): | |
1445 | # https://github.com/pyproj4/pyproj/issues/933 | |
1446 | with concurrent.futures.ProcessPoolExecutor(max_workers=2) as executor: | |
1447 | for result in executor.map(CRS, [4326 for _ in range(10)]): | |
1448 | pass | |
1449 | ||
1450 | ||
1444 | 1451 | def test_coordinate_operation__to_proj4(): |
1445 | 1452 | operation = CoordinateOperation.from_string( |
1446 | 1453 | "+proj=pipeline +step +proj=axisswap +order=2,1 +step " |
1528 | 1535 | assert CRS("+proj=utm +zone=15").list_authority() == [ |
1529 | 1536 | AuthorityMatchInfo(auth_name="EPSG", code="32615", confidence=70) |
1530 | 1537 | ] |
1538 | ||
1539 | ||
1540 | def test_list_authority__multiple(): | |
1541 | auth_list = CRS("+proj=longlat").list_authority() | |
1542 | assert AuthorityMatchInfo(auth_name="OGC", code="CRS84", confidence=70) in auth_list | |
1543 | assert AuthorityMatchInfo(auth_name="EPSG", code="4326", confidence=70) in auth_list |
391 | 391 | "o_proj": "longlat", |
392 | 392 | "o_lat_p": 32.5, |
393 | 393 | "o_lon_p": 170.0, |
394 | "lon_0": 0, | |
394 | "lon_0": 180, | |
395 | 395 | "datum": "WGS84", |
396 | 396 | "no_defs": None, |
397 | 397 | "type": "crs", |
414 | 414 | "o_proj": "longlat", |
415 | 415 | "o_lat_p": 32.5, |
416 | 416 | "o_lon_p": 170.0, |
417 | "lon_0": 1.0, | |
417 | "lon_0": 181.0, | |
418 | 418 | "datum": "WGS84", |
419 | 419 | "no_defs": None, |
420 | 420 | "type": "crs", |
421 | 421 | } |
422 | ||
423 | ||
424 | def test_rotated_pole_to_cf(): | |
425 | rotated_pole_wkt = ( | |
426 | 'GEOGCRS["undefined",\n' | |
427 | ' BASEGEOGCRS["Unknown datum based upon the GRS 1980 ellipsoid",\n' | |
428 | ' DATUM["Not specified (based on GRS 1980 ellipsoid)",\n' | |
429 | ' ELLIPSOID["GRS 1980",6378137,298.257222101,\n' | |
430 | ' LENGTHUNIT["metre",1]]],\n' | |
431 | ' PRIMEM["Greenwich",0,\n' | |
432 | ' ANGLEUNIT["degree",0.0174532925199433]]],\n' | |
433 | ' DERIVINGCONVERSION["Pole rotation (netCDF CF convention)",\n' | |
434 | ' METHOD["Pole rotation (netCDF CF convention)"],\n' | |
435 | ' PARAMETER["Grid north pole latitude (netCDF CF ' | |
436 | 'convention)",2,\n' | |
437 | ' ANGLEUNIT["degree",0.0174532925199433,\n' | |
438 | ' ID["EPSG",9122]]],\n' | |
439 | ' PARAMETER["Grid north pole longitude (netCDF CF ' | |
440 | 'convention)",3,\n' | |
441 | ' ANGLEUNIT["degree",0.0174532925199433,\n' | |
442 | ' ID["EPSG",9122]]],\n' | |
443 | ' PARAMETER["North pole grid longitude (netCDF CF ' | |
444 | 'convention)",4,\n' | |
445 | ' ANGLEUNIT["degree",0.0174532925199433,\n' | |
446 | ' ID["EPSG",9122]]]],\n' | |
447 | " CS[ellipsoidal,2],\n" | |
448 | ' AXIS["geodetic latitude (Lat)",north,\n' | |
449 | " ORDER[1],\n" | |
450 | ' ANGLEUNIT["degree",0.0174532925199433,\n' | |
451 | ' ID["EPSG",9122]]],\n' | |
452 | ' AXIS["geodetic longitude (Lon)",east,\n' | |
453 | " ORDER[2],\n" | |
454 | ' ANGLEUNIT["degree",0.0174532925199433,\n' | |
455 | ' ID["EPSG",9122]]]]' | |
456 | ) | |
457 | crs = CRS(rotated_pole_wkt) | |
458 | expected_cf = { | |
459 | "semi_major_axis": 6378137.0, | |
460 | "semi_minor_axis": 6356752.314140356, | |
461 | "inverse_flattening": 298.257222101, | |
462 | "reference_ellipsoid_name": "GRS 1980", | |
463 | "longitude_of_prime_meridian": 0.0, | |
464 | "prime_meridian_name": "Greenwich", | |
465 | "geographic_crs_name": "undefined", | |
466 | "grid_mapping_name": "rotated_latitude_longitude", | |
467 | "grid_north_pole_latitude": 2.0, | |
468 | "grid_north_pole_longitude": 3.0, | |
469 | "north_pole_grid_longitude": 4.0, | |
470 | "horizontal_datum_name": "Not specified (based on GRS 1980 ellipsoid)", | |
471 | } | |
472 | cf_dict = crs.to_cf() | |
473 | assert cf_dict.pop("crs_wkt").startswith("GEOGCRS[") | |
474 | assert cf_dict == expected_cf | |
475 | # test roundtrip | |
476 | _test_roundtrip(expected_cf, "GEOGCRS[") | |
422 | 477 | |
423 | 478 | |
424 | 479 | def test_cf_lambert_conformal_conic_1sp(): |