New upstream version 2.6.0~rc0+ds
Bas Couwenberg
4 years ago
67 | 67 | "doc", |
68 | 68 | "code", |
69 | 69 | "ideas", |
70 | "review" | |
70 | "review", | |
71 | "question" | |
71 | 72 | ] |
72 | 73 | }, |
73 | 74 | { |
183 | 184 | "profile": "https://github.com/sebastic", |
184 | 185 | "contributions": [ |
185 | 186 | "code", |
186 | "platform" | |
187 | "platform", | |
188 | "test" | |
187 | 189 | ] |
188 | 190 | }, |
189 | 191 | { |
316 | 318 | "contributions": [ |
317 | 319 | "doc" |
318 | 320 | ] |
321 | }, | |
322 | { | |
323 | "login": "jranalli", | |
324 | "name": "Joe Ranalli", | |
325 | "avatar_url": "https://avatars2.githubusercontent.com/u/7864460?v=4", | |
326 | "profile": "http://www.personal.psu.edu/jar339", | |
327 | "contributions": [ | |
328 | "bug", | |
329 | "code", | |
330 | "test" | |
331 | ] | |
332 | }, | |
333 | { | |
334 | "login": "gberardinelli", | |
335 | "name": "Greg Berardinelli", | |
336 | "avatar_url": "https://avatars0.githubusercontent.com/u/13799588?v=4", | |
337 | "profile": "https://github.com/gberardinelli", | |
338 | "contributions": [ | |
339 | "bug", | |
340 | "code", | |
341 | "ideas", | |
342 | "test" | |
343 | ] | |
319 | 344 | } |
320 | 345 | ], |
321 | 346 | "contributorsPerLine": 7 |
13 | 13 | |
14 | 14 | ```python |
15 | 15 | # Your code here |
16 | ||
17 | 16 | ``` |
18 | 17 | #### Problem description |
19 | 18 | |
59 | 58 | |
60 | 59 | ``` |
61 | 60 | </details> |
62 |
5 | 5 | |
6 | 6 | <!-- Please search existing issues to avoid creating duplicates. --> |
7 | 7 | |
8 | <!-- Describe the feature you'd like. -->⏎ | |
8 | <!-- Describe the feature you'd like. --> |
9 | 9 | |
10 | 10 | Issues installing pyproj? |
11 | 11 | Have you seen: http://pyproj4.github.io/pyproj/stable/installation.html |
12 | -->⏎ | |
12 | --> |
1 | 1 | |
2 | 2 | - [ ] Closes #xxxx |
3 | 3 | - [ ] Tests added |
4 | - [ ] Fully documented, including `history.rst` for all changes and `api/*.rst` for new API⏎ | |
4 | - [ ] Fully documented, including `history.rst` for all changes and `api/*.rst` for new API |
0 | [settings] | |
1 | line_length=88 | |
2 | multi_line_output=3 | |
3 | known_third_party=mock,numpy,pkg_resources,pytest,setuptools,test | |
4 | include_trailing_comma=true |
0 | repos: | |
1 | - repo: https://github.com/pre-commit/pre-commit-hooks | |
2 | rev: v2.5.0 | |
3 | hooks: | |
4 | - id: check-yaml | |
5 | - id: end-of-file-fixer | |
6 | - id: trailing-whitespace | |
7 | - repo: https://github.com/psf/black | |
8 | rev: 19.10b0 | |
9 | hooks: | |
10 | - id: black | |
11 | - repo: https://github.com/timothycrosley/isort | |
12 | rev: 4.3.21 | |
13 | hooks: | |
14 | - id: isort | |
15 | args: [setup.py, pyproj/, test/, docs/] | |
16 | - repo: https://github.com/asottile/blacken-docs | |
17 | rev: v1.6.0 | |
18 | hooks: | |
19 | - id: blacken-docs | |
20 | args: [--skip-errors] |
6 | 6 | - $PROJ_BASE_DIR |
7 | 7 | - $HOME/.cache/pip |
8 | 8 | |
9 | env: | |
10 | global: | |
9 | env: | |
10 | global: | |
11 | 11 | - PROJ_BASE_DIR=$HOME/proj_install |
12 | 12 | - CYTHON_COVERAGE=True |
13 | - PROJSOURCE=6.3.1 | |
13 | - PROJSOURCE=7.0.0 | |
14 | 14 | # Following generated with |
15 | 15 | - WHEELHOUSE_UPLOADER_USERNAME=travis-worker |
16 | 16 | # Following generated by |
36 | 36 | - python: 3.6 |
37 | 37 | env: |
38 | 38 | - PROJSOURCE=6.3.0 |
39 | - python: 3.6 | |
40 | env: | |
41 | - PROJSOURCE=6.3.1 | |
39 | 42 | - python: 3.7 |
40 | 43 | env: |
41 | 44 | - DOC=true |
46 | 49 | # - python: "nightly" |
47 | 50 | # env: |
48 | 51 | # - PROJSOURCE=git |
49 | ||
52 | ||
50 | 53 | allow_failures: |
51 | 54 | # - python: "nightly" |
52 | 55 | # env: |
60 | 63 | - | |
61 | 64 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then |
62 | 65 | brew update |
63 | brew install sqlite3 wget openssl readline | |
66 | brew install sqlite3 wget openssl readline libtiff | |
64 | 67 | # from https://pythonhosted.org/CodeChat/.travis.yml.html |
65 | 68 | brew outdated pyenv || brew upgrade pyenv |
66 | 69 | # virtualenv doesn't work without pyenv knowledge. venv in Python 3.3 |
77 | 80 | # A manual check that the correct version of Python is running. |
78 | 81 | python --version |
79 | 82 | else |
80 | sudo apt-get install -qq sqlite3 libsqlite3-dev | |
83 | sudo apt-get install -qq sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev | |
81 | 84 | fi |
82 | 85 | - | |
83 | 86 | if [[ "$TRAVIS_OS_NAME" == "osx" && -n "$PYPROJ_OMP" ]]; then |
114 | 117 | script: |
115 | 118 | - python -c "import pyproj; pyproj.Proj('epsg:4269')" |
116 | 119 | - make test-coverage |
120 | - | | |
121 | if [ "$TRAVIS_PYTHON_VERSION" = "3.5" ]; then | |
122 | make check-type; | |
123 | else | |
124 | make check; | |
125 | fi | |
117 | 126 | # Building and uploading docs with doctr |
118 | 127 | - set -e |
119 | 128 | - | |
0 | 0 | # Contributors Guide |
1 | ||
2 | Based on the guide from: https://github.com/Unidata/MetPy | |
1 | 3 | |
2 | 4 | Interested in helping build pyproj? Have code from your research that you believe others will find useful? Have a few minutes to tackle an issue? In this guide we will get you setup and integrated into contributing to pyproj! |
3 | 5 | |
74 | 76 | ``cd pyproj`` |
75 | 77 | * Connect your repository to the upstream (main project). |
76 | 78 | ``git remote add upstream https://github.com/pyproj4/pyproj.git`` |
77 | * Create the development environment by running ``conda create -n devel -c conda-forge python proj4``. | |
79 | * Create the development environment by running ``conda create -n devel -c conda-forge cython proj numpy shapely``. | |
78 | 80 | * Activate our new development environment ``conda activate devel`` on Mac/Linux or |
79 | 81 | ``activate devel`` on Windows. |
82 | * Install development requirements ``pip install -r requirements-dev.txt`` | |
80 | 83 | * Make an editable install of pyproj by running ``pip install -e .`` |
84 | * Setup pre-commit hooks ``pre-commit install`` and ``pre-commit autoupdate`` | |
81 | 85 | |
82 | 86 | Now you're all set! You have an environment called ``devel`` that you can work in. You'll need |
83 | 87 | to make sure to activate that environment next time you want to use it after closing the |
106 | 110 | |
107 | 111 | You can build the documentation locally to see how your changes will look. |
108 | 112 | * Install docs requirements: ``make install-docs`` |
109 | * Build the docs: ``make docs`` | |
113 | * Build the docs: ``make docs`` | |
110 | 114 | * Or, to build and open in a browser: ``make docs-browser`` |
111 | 115 | |
112 | 116 | ## Tests |
0 | 0 | |
1 | All source, data files and other contents of the PROJ.4 package are | |
1 | All source, data files and other contents of the PROJ.4 package are | |
2 | 2 | available under the following terms. Note that the PROJ 4.3 and earlier |
3 | 3 | was "public domain" as is common with US government work, but apparently |
4 | this is not a well defined legal term in many countries. I am placing | |
4 | this is not a well defined legal term in many countries. I am placing | |
5 | 5 | everything under the following MIT style license because I believe it is |
6 | 6 | effectively the same as public domain, allowing anyone to use the code as |
7 | they wish, including making proprietary derivatives. | |
7 | they wish, including making proprietary derivatives. | |
8 | 8 | |
9 | 9 | Though I have put my own name as copyright holder, I don't mean to imply |
10 | I did the work. Essentially all work was done by Gerald Evenden. | |
10 | I did the work. Essentially all work was done by Gerald Evenden. | |
11 | 11 | |
12 | 12 | -------------- |
13 | 13 | |
30 | 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
31 | 31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
32 | 32 | DEALINGS IN THE SOFTWARE. |
33 |
6 | 6 | include pyproj/*.pyx |
7 | 7 | include pyproj/*.pxd |
8 | 8 | include pyproj/*.pxi |
9 | include pyproj/*.pyi | |
9 | 10 | include test/sample.out |
10 | 11 | include test/conftest.py |
11 | 12 | recursive-include docs * |
62 | 62 | lint: ## check style with flake8 |
63 | 63 | flake8 --max-line-length 88 setup.py pyproj/ test/ docs/ |
64 | 64 | |
65 | check: lint ## flake8 black isort check | |
65 | check-type: | |
66 | mypy pyproj | |
67 | ||
68 | check: lint check-type ## flake8 black isort check | |
66 | 69 | black --check setup.py pyproj/ test/ docs/ |
67 | isort --check --recursive -m 3 -w 88 -tc -p test setup.py pyproj/ test/ docs/ | |
70 | isort --check --recursive setup.py pyproj/ test/ docs/ | |
68 | 71 | |
69 | 72 | isort: ## order imports |
70 | isort --recursive -m 3 -w 88 -tc -p test setup.py pyproj/ test/ docs/ | |
73 | isort --recursive setup.py pyproj/ test/ docs/ | |
71 | 74 | |
72 | 75 | black: ## black format files |
73 | 76 | black setup.py pyproj/ test/ docs/ |
0 | 0 | # pyproj |
1 | ||
1 | ||
2 | 2 | Python interface to [PROJ](http://proj.org) (cartographic projections and coordinate transformations library). |
3 | 3 | |
4 | 4 | <p align="center"> |
11 | 11 | <a href="https://pepy.tech/project/pyproj"><img alt="Downloads" src="https://pepy.tech/badge/pyproj"></a> |
12 | 12 | <a href="https://anaconda.org/conda-forge/pyproj"><img alt="Anaconda-Server Badge" src="https://anaconda.org/conda-forge/pyproj/badges/version.svg"></a> |
13 | 13 | <a href="https://github.com/python/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a> |
14 | <a href="https://github.com/pre-commit/pre-commit"><img alt="pre-commit" src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white"></a> | |
14 | 15 | <a href="https://zenodo.org/badge/latestdoi/28607354"><img alt="DOI" src="https://zenodo.org/badge/28607354.svg"></a> |
15 | 16 | </p> |
16 | 17 | |
38 | 39 | <td align="center"><a href="https://github.com/jswhit"><img src="https://avatars2.githubusercontent.com/u/579593?v=4" width="100px;" alt="Jeff Whitaker"/><br /><sub><b>Jeff Whitaker</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=jswhit" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jswhit" title="Tests">⚠️</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jswhit" title="Code">💻</a> <a href="#example-jswhit" title="Examples">💡</a> <a href="#ideas-jswhit" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-jswhit" title="Reviewed Pull Requests">👀</a> <a href="#question-jswhit" title="Answering Questions">💬</a> <a href="#maintenance-jswhit" title="Maintenance">🚧</a> <a href="#infra-jswhit" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td> |
39 | 40 | <td align="center"><a href="https://github.com/snowman2"><img src="https://avatars3.githubusercontent.com/u/8699967?v=4" width="100px;" alt="Alan D. Snow"/><br /><sub><b>Alan D. Snow</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=snowman2" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=snowman2" title="Tests">⚠️</a> <a href="https://github.com/pyproj4/pyproj/commits?author=snowman2" title="Code">💻</a> <a href="#example-snowman2" title="Examples">💡</a> <a href="#maintenance-snowman2" title="Maintenance">🚧</a> <a href="#infra-snowman2" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-snowman2" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-snowman2" title="Reviewed Pull Requests">👀</a> <a href="#question-snowman2" title="Answering Questions">💬</a></td> |
40 | 41 | <td align="center"><a href="https://github.com/micahcochran"><img src="https://avatars0.githubusercontent.com/u/7433104?v=4" width="100px;" alt="Micah Cochran"/><br /><sub><b>Micah Cochran</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=micahcochran" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=micahcochran" title="Tests">⚠️</a> <a href="https://github.com/pyproj4/pyproj/commits?author=micahcochran" title="Code">💻</a> <a href="#maintenance-micahcochran" title="Maintenance">🚧</a> <a href="#infra-micahcochran" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#review-micahcochran" title="Reviewed Pull Requests">👀</a> <a href="#question-micahcochran" title="Answering Questions">💬</a></td> |
41 | <td align="center"><a href="https://jorisvandenbossche.github.io/"><img src="https://avatars2.githubusercontent.com/u/1020496?v=4" width="100px;" alt="Joris Van den Bossche"/><br /><sub><b>Joris Van den Bossche</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=jorisvandenbossche" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jorisvandenbossche" title="Code">💻</a> <a href="#ideas-jorisvandenbossche" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-jorisvandenbossche" title="Reviewed Pull Requests">👀</a></td> | |
42 | <td align="center"><a href="https://jorisvandenbossche.github.io/"><img src="https://avatars2.githubusercontent.com/u/1020496?v=4" width="100px;" alt="Joris Van den Bossche"/><br /><sub><b>Joris Van den Bossche</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=jorisvandenbossche" title="Documentation">📖</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jorisvandenbossche" title="Code">💻</a> <a href="#ideas-jorisvandenbossche" title="Ideas, Planning, & Feedback">🤔</a> <a href="#review-jorisvandenbossche" title="Reviewed Pull Requests">👀</a> <a href="#question-jorisvandenbossche" title="Answering Questions">💬</a></td> | |
42 | 43 | <td align="center"><a href="https://github.com/cjmayo"><img src="https://avatars1.githubusercontent.com/u/921089?v=4" width="100px;" alt="Chris Mayo"/><br /><sub><b>Chris Mayo</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=cjmayo" title="Tests">⚠️</a></td> |
43 | 44 | <td align="center"><a href="https://www.petrel.org"><img src="https://avatars1.githubusercontent.com/u/2298266?v=4" width="100px;" alt="Charles Karney"/><br /><sub><b>Charles Karney</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=cffk" title="Code">💻</a> <a href="https://github.com/pyproj4/pyproj/commits?author=cffk" title="Tests">⚠️</a></td> |
44 | 45 | <td align="center"><a href="http://www.justaprogrammer.net/profile/justin"><img src="https://avatars3.githubusercontent.com/u/146930?v=4" width="100px;" alt="Justin Dearing"/><br /><sub><b>Justin Dearing</b></sub></a><br /><a href="#infra-zippy1981" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td> |
54 | 55 | </tr> |
55 | 56 | <tr> |
56 | 57 | <td align="center"><a href="https://github.com/heitorPB"><img src="https://avatars2.githubusercontent.com/u/13461702?v=4" width="100px;" alt="Heitor"/><br /><sub><b>Heitor</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=heitorPB" title="Documentation">📖</a></td> |
57 | <td align="center"><a href="https://github.com/sebastic"><img src="https://avatars3.githubusercontent.com/u/4605306?v=4" width="100px;" alt="Bas Couwenberg"/><br /><sub><b>Bas Couwenberg</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=sebastic" title="Code">💻</a> <a href="#platform-sebastic" title="Packaging/porting to new platform">📦</a></td> | |
58 | <td align="center"><a href="https://github.com/sebastic"><img src="https://avatars3.githubusercontent.com/u/4605306?v=4" width="100px;" alt="Bas Couwenberg"/><br /><sub><b>Bas Couwenberg</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=sebastic" title="Code">💻</a> <a href="#platform-sebastic" title="Packaging/porting to new platform">📦</a> <a href="https://github.com/pyproj4/pyproj/commits?author=sebastic" title="Tests">⚠️</a></td> | |
58 | 59 | <td align="center"><a href="https://github.com/nickeubank"><img src="https://avatars0.githubusercontent.com/u/9683693?v=4" width="100px;" alt="Nick Eubank"/><br /><sub><b>Nick Eubank</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=nickeubank" title="Code">💻</a></td> |
59 | 60 | <td align="center"><a href="https://www.math.uwaterloo.ca/~mdunphy/"><img src="https://avatars3.githubusercontent.com/u/9088426?v=4" width="100px;" alt="Michael Dunphy"/><br /><sub><b>Michael Dunphy</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=mdunphy" title="Documentation">📖</a></td> |
60 | 61 | <td align="center"><a href="http://matthew.dynevor.org"><img src="https://avatars2.githubusercontent.com/u/67612?v=4" width="100px;" alt="Matthew Brett"/><br /><sub><b>Matthew Brett</b></sub></a><br /><a href="#infra-matthew-brett" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#platform-matthew-brett" title="Packaging/porting to new platform">📦</a></td> |
73 | 74 | <tr> |
74 | 75 | <td align="center"><a href="https://github.com/glostis"><img src="https://avatars0.githubusercontent.com/u/25295717?v=4" width="100px;" alt="Guillaume Lostis"/><br /><sub><b>Guillaume Lostis</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=glostis" title="Documentation">📖</a></td> |
75 | 76 | <td align="center"><a href="https://github.com/edpop"><img src="https://avatars3.githubusercontent.com/u/13479292?v=4" width="100px;" alt="Eduard Popov"/><br /><sub><b>Eduard Popov</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/commits?author=edpop" title="Documentation">📖</a></td> |
77 | <td align="center"><a href="http://www.personal.psu.edu/jar339"><img src="https://avatars2.githubusercontent.com/u/7864460?v=4" width="100px;" alt="Joe Ranalli"/><br /><sub><b>Joe Ranalli</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/issues?q=author%3Ajranalli" title="Bug reports">🐛</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jranalli" title="Code">💻</a> <a href="https://github.com/pyproj4/pyproj/commits?author=jranalli" title="Tests">⚠️</a></td> | |
78 | <td align="center"><a href="https://github.com/gberardinelli"><img src="https://avatars0.githubusercontent.com/u/13799588?v=4" width="100px;" alt="Greg Berardinelli"/><br /><sub><b>Greg Berardinelli</b></sub></a><br /><a href="https://github.com/pyproj4/pyproj/issues?q=author%3Agberardinelli" title="Bug reports">🐛</a> <a href="https://github.com/pyproj4/pyproj/commits?author=gberardinelli" title="Code">💻</a> <a href="#ideas-gberardinelli" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/pyproj4/pyproj/commits?author=gberardinelli" title="Tests">⚠️</a></td> | |
76 | 79 | </tr> |
77 | 80 | </table> |
78 | 81 |
0 | 0 | platform: |
1 | 1 | - x64 |
2 | 2 | |
3 | # This is based on file and files in ci/appveyor are from | |
3 | # This is based on file and files in ci/appveyor are from | |
4 | 4 | # https://github.com/ogrisel/python-appveyor-demo |
5 | 5 | environment: |
6 | 6 | global: |
14 | 14 | # Pre-installed Python versions |
15 | 15 | # See: http://www.appveyor.com/docs/installed-software#python |
16 | 16 | # build is limited to 60 minutes, without caching each build takes 10-30 minutes |
17 | # with caching build takes less than 1 minute | |
18 | # - PYTHON: "C:\\Python35-x64" | |
19 | # PYTHON_VERSION: "3.5" | |
20 | # PYTHON_ARCH: "64" | |
21 | # VS_VERSION: Visual Studio 14 | |
22 | # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 | |
23 | # PROJSOURCE: 6.3.0 | |
17 | # with caching build takes less than 1 minute | |
24 | 18 | - PYTHON: "C:\\Python36-x64" |
25 | 19 | PYTHON_VERSION: "3.6" |
26 | 20 | PYTHON_ARCH: "64" |
27 | 21 | VS_VERSION: Visual Studio 14 |
28 | 22 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 |
29 | PROJSOURCE: 6.3.1 | |
23 | PROJSOURCE: 7.0.0 | |
30 | 24 | # - PYTHON: "C:\\Python37-x64" |
31 | 25 | # PYTHON_VERSION: "3.7" |
32 | 26 | # PYTHON_ARCH: "64" |
56 | 50 | |
57 | 51 | build_script: |
58 | 52 | # setup sqlite3 |
53 | - vcpkg install sqlite3[core,tool]:"%platform%"-windows | |
54 | - vcpkg install tiff:"%platform%"-windows | |
55 | - vcpkg install curl:"%platform%"-windows | |
56 | - dir C:\Tools\vcpkg\installed\%platform%-windows\bin | |
57 | - set PATH=C:\Tools\vcpkg\installed\%platform%-windows\bin;%PATH% | |
58 | # setup PROJ.4 | |
59 | 59 | - set PROJ_DIR=%PROJ_BASE_DIR%\proj-%PROJSOURCE:~0,5% |
60 | - vcpkg install sqlite3:"%platform%"-windows | |
61 | - set SQLITE3_BIN=%APPVEYOR_BUILD_FOLDER%\sqlite3\bin | |
62 | - mkdir %SQLITE3_BIN% | |
63 | - copy c:\tools\vcpkg\installed\"%platform%"-windows\bin\sqlite3.dll %SQLITE3_BIN% | |
64 | - ps: | | |
65 | appveyor DownloadFile https://sqlite.org/2018/sqlite-tools-win32-x86-3250100.zip | |
66 | 7z x sqlite-tools-win32-x86-3250100.zip | |
67 | - copy "%APPVEYOR_BUILD_FOLDER%"\sqlite-tools-win32-x86-3250100\sqlite3.exe %SQLITE3_BIN% | |
68 | - set PATH=%SQLITE3_BIN%;%PATH% | |
69 | # setup PROJ.4 | |
70 | 60 | - if "%PROJSOURCE%" == "git" git clone https://github.com/OSGeo/proj.4.git proj-git |
71 | 61 | - if not "%PROJSOURCE%" == "git" if not exist %PROJ_DIR% set BUILD_PROJ_STABLE=1 |
72 | 62 | - if defined BUILD_PROJ_STABLE curl -o "proj-%PROJSOURCE:~0,5%.zip" "https://download.osgeo.org/proj/proj-%PROJSOURCE%.zip" |
73 | 63 | - if defined BUILD_PROJ_STABLE 7z x -aoa -y "proj-%PROJSOURCE:~0,5%.zip" |
74 | 64 | - if not exist %PROJ_DIR% cd "%APPVEYOR_BUILD_FOLDER%\proj-%PROJSOURCE:~0,5%" |
75 | 65 | - if "%platform%" == "x64" SET VS_FULL=%VS_VERSION% Win64 |
76 | - if "%platform%" == "x64" SET BUILD_LIBPROJ_SHARED=ON | |
66 | - if "%platform%" == "x64" SET BUILD_SHARED_LIBS=ON | |
77 | 67 | - if "%platform%" == "x86" SET VS_FULL=%VS_VERSION% |
78 | - if "%platform%" == "x86" SET BUILD_LIBPROJ_SHARED=OFF | |
68 | - if "%platform%" == "x86" SET BUILD_SHARED_LIBS=OFF | |
79 | 69 | - echo "%VS_FULL%" |
80 | 70 | # |
81 | 71 | - if "%PROJSOURCE%" == "git" set BUILD_PROJ=1 |
82 | 72 | - if defined BUILD_PROJ_STABLE set BUILD_PROJ=1 |
83 | 73 | - if defined BUILD_PROJ mkdir build |
84 | 74 | - if defined BUILD_PROJ cd build |
85 | - if defined BUILD_PROJ cmake -G "%VS_FULL%" .. -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBPROJ_SHARED="%BUILD_LIBPROJ_SHARED%" -DCMAKE_C_FLAGS="/WX" -DCMAKE_CXX_FLAGS="/WX" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX="%PROJ_DIR%" | |
75 | - if defined BUILD_PROJ cmake -G "%VS_FULL%" .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="%BUILD_SHARED_LIBS%" -DCMAKE_C_FLAGS="/WX" -DCMAKE_CXX_FLAGS="/WX" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX="%PROJ_DIR%" | |
86 | 76 | - if defined BUILD_PROJ cmake --build . --config Release --target install |
87 | 77 | - set PATH=%PROJ_DIR%\bin;%PATH% |
88 | 78 | - set PROJ_LIB=%PROJ_DIR%\share\proj |
119 | 109 | # Upgrade to the latest version of pip to avoid it displaying warnings |
120 | 110 | # about it being out of date. |
121 | 111 | - "python -m pip install --disable-pip-version-check --user --upgrade pip==19.0.3" |
122 | ||
112 | ||
123 | 113 | # install wheel, caching |
124 | 114 | - "python -m pip install wheel" |
125 | 115 | # update vcpkg |
19 | 19 | # build using autotools |
20 | 20 | sh autogen.sh |
21 | 21 | ./configure --prefix=$PROJ_DIR |
22 | make | |
22 | make | |
23 | 23 | make install |
24 | 24 | # build using cmake |
25 | 25 | #cmake . -DCMAKE_INSTALL_PREFIX=$PROJ_DIR |
0 | gAAAAABcv0vdkreKT0kDO9nMioPyB2R66eYGDtTK08mBxWq1dvzZ_aK2HEVvJ0e7nZtpTGdQuR6GTq5_6yA2iYScVK7Z4LoOqw3dDaQX6ssnYdcmTzdiAVRDE-kZ9WXUxf7izcBsafLmNgizctJ2MT23AQ30CEYb0J4C1Akq9PThRoIdJ3P4jhyztlTjPv4PxcCrA2Gl_x0pJsAS-vpC38A6n41ZxiKQrkBqoKwem11p7Ui4vjv6mcARSuRXHWpiQSHuJXpLfMZv0_GM7VYxdVo04WZA-dPv6RyER4rPlJwvpdWQ2GNN3ZyfYW4-EiSdNuoCe8idQM2cZr5ZoMLSAtZUFlfORVqWV7eyU1HYbaoicfqwMTgOijy06u7ifn60Yg-C-D2GwWNHYgDZm-JPYoaarn47bJqlrdhQaCSif1mrGThGcbtsIhnnH0yJXpj6fdhi4QhaksoLe2cOi9mBYB0WbM-JYDyfIdRDyfnos40iOk5PJe-dj51AdDcDOLk7gegCiTt_MDQKrLt1GnEfPlo5EBa7BqT7Ws38mAY2UG28BoMfHDhV2JYWspDGGZ7EDi8T-IQAwe2z3swCLh1EW7TT9CcTwxYMqX-y0Kj99bcZHoiFvG76u78fsNe1fIPLmGFJ7zyfR_sTBt08rDyWR1B_Ssspk66xedVttWt_cCn_FHJQIyD7dufz_X4dnxV9qPykVzJ9T6Z45eLSSC38M8QPa9oZIuoTWJnbNKWjIC8B_0MZk3QXjI3ZiMFvrWic5CZjHk84VKEwbkxvfZhZwXiY5bK4bLI2eCJatipAhjH3TKwAZIzYiIQv_yswaUQ7I77pMGaFwgLx7cLjIFnBpOYzow9VeT7bTZWIydNMtwU7QeYCsLtcJj99bmj45egzlLWWsZQjasZ6uZ9atRKeQPpoqnCnTMpdx_v7WHTO2PuBaH6_9vvIJdi1foVmeGMmnbq-hvvdoFdt7bevlSFN_f1Izcf1OGME_3tEHvHp2gssbtaQ2kZw5Bfj4eBCnqC-GBLztg_aykKAs_A3DF2gXo-4j2Yc30dzdtXS2yscopJudW7GywEJD2wpVEX-zN8DXL_lfW7nCRSaMWi42EdrSIFNwxvMWKZXGAIhld_29U3zq-faxA6qq5nDsj1roygVu-oXUP2Icqstje2OucMOfdkOEDdB-mvGCnNYIffthdlw6NbCes82Zsjqmk08Ms1Hrwxeh_vrO3Vrip3IEgeGIdtu8I-K-pGUDRVikLeaNyrx88jggsog-GF1N86OsjdYueV-eCsuq3rV_fuFDt76v_a0HV3FjFq6eZc3bB7pgBarFlRTQsRGHM5q_XaVY_Tp_iJBYlZbFjsMY5RSF_OGvdeVtkL4g7Rgyhj8WgVYfz4Ykrp_vZuAYWQE3LYpuqCq5tjFOm9nFcPxpwjEoV3rlMijiOwTdCg7Kg3QMRcDjnloIDzBa7mpvuuNgou4tCehzh83kFlw3oskHQgQkRXwKDreLoxDlgxxXu-zQGRz7zLOf0xJii6ZGSIdCBEJvCndF8AAHSA5ReTyFPlLwiQAEQ5zvUAuQ9rVrYaYG1SeFqhtxkuAUvhxRdIzg2ICKpASkI52EpvhXbeJe8JcMBOwKRXiB6XcdtOffX9eYVm1gp0wZ-1rmWa8Uqg3flTzls9ug2kgRzbJN5vsBoSLVJXwzBZjacZ9ZQ7ZciwUK0_Dg-D2emCymkVcFUrnB2OsnE4rNIkfhUpTG9vXp-n1tVnzm8UXoLLvfldDtjxdz9sQsj9hORkxkVcpDpeqE1I7UdmBHCCz_bZ7bj230KTfdEXQMWcQWfWFl4U8KiaSnJBBjwAjMIHbT7UxJzbsOpl7cN_WuObrvGLWUnByXILW7QDe8XQwfSYwX75l05g9a7PHNXhfX61DUFcw2asY1m9UP4WPljFfgcR46xcHfkwQjGE232wfQ5hPfiVoskTLmBP-EdAd-gc6aWVb6hIv55p0iNRlkNs4fMmQNejmQjwIGRvZgYq99MSdhocG5yueJaEAMAaXpAawXm54Sh1Aw9fYSyMYe0p6glKqil-_Eck3Lx1RFaXfvOK0ICgsnSaqN7n7QDJ5TjE8yVxJjBTCEMbKJU5m57DRjRezKK35LN-ZfpQH3eINTLbjYN3FII-aycNrjP5uev9fSceNrq9JWGoYIVDeBqJV3akai9a2tvGXJh7Dn3alvMOzPzqJKhC4mO5T0bCtAcN_8SAI87E77Ver9D6nyvk1Jvul18Ax50ta7paJ1jZWKL_gjFCfVm5m9FWlXx3ytDzEO8HSNd4uI_u6iKqZf9btBFJZu0P8vtvSVAGBj-D5Gty99gTy9V0qZSPmOmf2vqMeIpFHXTzJ8HKEDvGms0o4ymSY3YP3UPvQivqnP5ggIccZgvGlaRoWHUOMyFNRRCc8gr_s2-gO4mixXtonjnaw1l1HOXKrykVvnWCdEgkMFsYJRl-2ob4BeJDisus3g7gRKBgP9h1KSMtFokkeFkRmnDvdWximbs5kXibfz_4GbK7sGuWUF6kbvE4lEKYADPdRbtSCEZCTqcVgyUOclz-fbUgaeXwazC-xMclXhdFfJl4eSGhs7-60GVHErJZBMoVTr3-fdPsEpJrGa4etr2MRtW-XuOrSIMxgiyAoLm6ZFu5gqoQCKTil69-rpHHGIDmLZeJ4mNckoq7VGHAIWooj35jnnExBqwzh6mKack6THi2W3buzFlKbI7BRpXxbRktDgOLCx8hRJe2B1RrdUHuraa8kEqq-UHSiL59YvhnVwWUXwQs_ppX6L0_qAg3AvCACrLNJV3FlChJ7H0xGT7ZhYmJzrTfE7gJnVweLTQQCxFJEnIyB7jBCaWArttTGJZ4tiX_Z3Du4KertA2sodEz7TPnPAuQH6ZWgRXsA0XsOWGVmBlT00REN7hIKGY41o-2zaLOJ0ATAMVNGg6572sge5M8QXPO24_ekWX82NWwKMdm0MfCuKMlTRdclFFgQ5YCEDENJyv3RYQ2hItX8hrBFJ-r8rcd-AUjHJnFNnHhQ9P6f6J7JzMl4vWTYD6lwWIV2SmlVZZlHtVIcMYKaCJTHorWs7RHhxa4sJBP8Z2h_U69Xs1KDBUJrRaA9--TT3MHNwFZVPAfsD0ARjyjoBc53mMMNOhyF9Zkwla90cezdKMPnKh0eE68-0AejMhpFFTdOnOLKSvmBHGDKo9I9tiDBgDKp_vamJIoxeBk1Tn1s6GVC0HSKJOGqBBfKqNtliIrJ0F4i_AAzYeIdJnDwpWIzanWZwm216N6gqHMZdIjl32rwfi5MiT9hcgySIwEe76R1WcVdhnMxtCtivbEWh-d7IzpoD8jEN6ljUG7D41mwPrfyQ0NpwzUubNPiFWApdAwsuiof7E70u4N-7eS1rIlUtlt5x_hGr6OB9eDES9THlK2zJqEojbv7Sx5SO9E3N1LT3-FCiLcZoHObW5hFe_MD4YRLO47nAoTcnmWPb6E2TK40glcepdZfcfam6sox3CX9e25QTs2yYm5pnDLvW6cqQOTkAJ5d2kcUXiUGTKAg4dCJDyjakquCwh5UZtfpKq9zusOrxGzq5Hv4p7oWfOCTjupxA2LHozt22Lv10uOTBiVdyJ0_Ik0T3tbDYegcHZlt5inXvtIc6drsNLQDCjCzSEWbdiyzq3VHHEeGgN9IP9NXOfwssWWxeJtD39IUL6SQ6C1LpVWXJ_oBQLnc131d0fBgT86iWHntC5w-zAbGvcxB2kz9CxzejBffCurVTXVh0dCm33CFd3DhGptn2oSI_r63YD8VFWtM0Q9NEWI61r9fuo6zIY6E1AQgNqsPQSkFExrcq6WqNqfbbq7BFR63MPiGhE2lBvIb6jIgn1B9R1hOB99lxaz6d-5FxqFfzUCyPILgX3kF3u509l4yd7ZXmjKJDo_YMEca5J21OAtmsqLVRQ4dYKsEMH7_SrvQLF2UY9fmkPD8OfW0tcDZHLMYZ-ZusqCPmpzwsTBQWxNkACwhuLBP_oeQbzuXIvhNl1mxQzz9NTImuRwfgr5S_E-zHiizdTqVzSTrVb1q2tsacOZn4Y9nPMVG4qejrcEq1qSZHpg1hYr_4D8g-0OOO3OrChRdWPS3T2IqTcqf74IBq-QZ_5nF_2csXUlOSv436G_LbS35jUz231rML25chdNGqVA16MM_huOWL6ertJoxMEiFt5mMSu7mi5ZfvRZVar5uf_yY4rU0_uafMPve45qIZJmGeHhqAdw1Moet0TFk3OuJKsQki37BGFjbYlFNpTp_3uKUuUmzdsbRnQGgMgQ9GwA1ICejVuYxCDOxGFr8LkXrZgiy8EaCLoxhvMWshHtzBmGua2c0fx-qfC3lY9be25ouFYv6gH_sIJQZRGpMR-t5AZ0GC2QdSCuEIfWCKX6pZQUZkYr5sfZQnYKwnVMufZGHHc_70Pcb90J3kVI-pNIlWqmRSw==⏎ | |
0 | gAAAAABcv0vdkreKT0kDO9nMioPyB2R66eYGDtTK08mBxWq1dvzZ_aK2HEVvJ0e7nZtpTGdQuR6GTq5_6yA2iYScVK7Z4LoOqw3dDaQX6ssnYdcmTzdiAVRDE-kZ9WXUxf7izcBsafLmNgizctJ2MT23AQ30CEYb0J4C1Akq9PThRoIdJ3P4jhyztlTjPv4PxcCrA2Gl_x0pJsAS-vpC38A6n41ZxiKQrkBqoKwem11p7Ui4vjv6mcARSuRXHWpiQSHuJXpLfMZv0_GM7VYxdVo04WZA-dPv6RyER4rPlJwvpdWQ2GNN3ZyfYW4-EiSdNuoCe8idQM2cZr5ZoMLSAtZUFlfORVqWV7eyU1HYbaoicfqwMTgOijy06u7ifn60Yg-C-D2GwWNHYgDZm-JPYoaarn47bJqlrdhQaCSif1mrGThGcbtsIhnnH0yJXpj6fdhi4QhaksoLe2cOi9mBYB0WbM-JYDyfIdRDyfnos40iOk5PJe-dj51AdDcDOLk7gegCiTt_MDQKrLt1GnEfPlo5EBa7BqT7Ws38mAY2UG28BoMfHDhV2JYWspDGGZ7EDi8T-IQAwe2z3swCLh1EW7TT9CcTwxYMqX-y0Kj99bcZHoiFvG76u78fsNe1fIPLmGFJ7zyfR_sTBt08rDyWR1B_Ssspk66xedVttWt_cCn_FHJQIyD7dufz_X4dnxV9qPykVzJ9T6Z45eLSSC38M8QPa9oZIuoTWJnbNKWjIC8B_0MZk3QXjI3ZiMFvrWic5CZjHk84VKEwbkxvfZhZwXiY5bK4bLI2eCJatipAhjH3TKwAZIzYiIQv_yswaUQ7I77pMGaFwgLx7cLjIFnBpOYzow9VeT7bTZWIydNMtwU7QeYCsLtcJj99bmj45egzlLWWsZQjasZ6uZ9atRKeQPpoqnCnTMpdx_v7WHTO2PuBaH6_9vvIJdi1foVmeGMmnbq-hvvdoFdt7bevlSFN_f1Izcf1OGME_3tEHvHp2gssbtaQ2kZw5Bfj4eBCnqC-GBLztg_aykKAs_A3DF2gXo-4j2Yc30dzdtXS2yscopJudW7GywEJD2wpVEX-zN8DXL_lfW7nCRSaMWi42EdrSIFNwxvMWKZXGAIhld_29U3zq-faxA6qq5nDsj1roygVu-oXUP2Icqstje2OucMOfdkOEDdB-mvGCnNYIffthdlw6NbCes82Zsjqmk08Ms1Hrwxeh_vrO3Vrip3IEgeGIdtu8I-K-pGUDRVikLeaNyrx88jggsog-GF1N86OsjdYueV-eCsuq3rV_fuFDt76v_a0HV3FjFq6eZc3bB7pgBarFlRTQsRGHM5q_XaVY_Tp_iJBYlZbFjsMY5RSF_OGvdeVtkL4g7Rgyhj8WgVYfz4Ykrp_vZuAYWQE3LYpuqCq5tjFOm9nFcPxpwjEoV3rlMijiOwTdCg7Kg3QMRcDjnloIDzBa7mpvuuNgou4tCehzh83kFlw3oskHQgQkRXwKDreLoxDlgxxXu-zQGRz7zLOf0xJii6ZGSIdCBEJvCndF8AAHSA5ReTyFPlLwiQAEQ5zvUAuQ9rVrYaYG1SeFqhtxkuAUvhxRdIzg2ICKpASkI52EpvhXbeJe8JcMBOwKRXiB6XcdtOffX9eYVm1gp0wZ-1rmWa8Uqg3flTzls9ug2kgRzbJN5vsBoSLVJXwzBZjacZ9ZQ7ZciwUK0_Dg-D2emCymkVcFUrnB2OsnE4rNIkfhUpTG9vXp-n1tVnzm8UXoLLvfldDtjxdz9sQsj9hORkxkVcpDpeqE1I7UdmBHCCz_bZ7bj230KTfdEXQMWcQWfWFl4U8KiaSnJBBjwAjMIHbT7UxJzbsOpl7cN_WuObrvGLWUnByXILW7QDe8XQwfSYwX75l05g9a7PHNXhfX61DUFcw2asY1m9UP4WPljFfgcR46xcHfkwQjGE232wfQ5hPfiVoskTLmBP-EdAd-gc6aWVb6hIv55p0iNRlkNs4fMmQNejmQjwIGRvZgYq99MSdhocG5yueJaEAMAaXpAawXm54Sh1Aw9fYSyMYe0p6glKqil-_Eck3Lx1RFaXfvOK0ICgsnSaqN7n7QDJ5TjE8yVxJjBTCEMbKJU5m57DRjRezKK35LN-ZfpQH3eINTLbjYN3FII-aycNrjP5uev9fSceNrq9JWGoYIVDeBqJV3akai9a2tvGXJh7Dn3alvMOzPzqJKhC4mO5T0bCtAcN_8SAI87E77Ver9D6nyvk1Jvul18Ax50ta7paJ1jZWKL_gjFCfVm5m9FWlXx3ytDzEO8HSNd4uI_u6iKqZf9btBFJZu0P8vtvSVAGBj-D5Gty99gTy9V0qZSPmOmf2vqMeIpFHXTzJ8HKEDvGms0o4ymSY3YP3UPvQivqnP5ggIccZgvGlaRoWHUOMyFNRRCc8gr_s2-gO4mixXtonjnaw1l1HOXKrykVvnWCdEgkMFsYJRl-2ob4BeJDisus3g7gRKBgP9h1KSMtFokkeFkRmnDvdWximbs5kXibfz_4GbK7sGuWUF6kbvE4lEKYADPdRbtSCEZCTqcVgyUOclz-fbUgaeXwazC-xMclXhdFfJl4eSGhs7-60GVHErJZBMoVTr3-fdPsEpJrGa4etr2MRtW-XuOrSIMxgiyAoLm6ZFu5gqoQCKTil69-rpHHGIDmLZeJ4mNckoq7VGHAIWooj35jnnExBqwzh6mKack6THi2W3buzFlKbI7BRpXxbRktDgOLCx8hRJe2B1RrdUHuraa8kEqq-UHSiL59YvhnVwWUXwQs_ppX6L0_qAg3AvCACrLNJV3FlChJ7H0xGT7ZhYmJzrTfE7gJnVweLTQQCxFJEnIyB7jBCaWArttTGJZ4tiX_Z3Du4KertA2sodEz7TPnPAuQH6ZWgRXsA0XsOWGVmBlT00REN7hIKGY41o-2zaLOJ0ATAMVNGg6572sge5M8QXPO24_ekWX82NWwKMdm0MfCuKMlTRdclFFgQ5YCEDENJyv3RYQ2hItX8hrBFJ-r8rcd-AUjHJnFNnHhQ9P6f6J7JzMl4vWTYD6lwWIV2SmlVZZlHtVIcMYKaCJTHorWs7RHhxa4sJBP8Z2h_U69Xs1KDBUJrRaA9--TT3MHNwFZVPAfsD0ARjyjoBc53mMMNOhyF9Zkwla90cezdKMPnKh0eE68-0AejMhpFFTdOnOLKSvmBHGDKo9I9tiDBgDKp_vamJIoxeBk1Tn1s6GVC0HSKJOGqBBfKqNtliIrJ0F4i_AAzYeIdJnDwpWIzanWZwm216N6gqHMZdIjl32rwfi5MiT9hcgySIwEe76R1WcVdhnMxtCtivbEWh-d7IzpoD8jEN6ljUG7D41mwPrfyQ0NpwzUubNPiFWApdAwsuiof7E70u4N-7eS1rIlUtlt5x_hGr6OB9eDES9THlK2zJqEojbv7Sx5SO9E3N1LT3-FCiLcZoHObW5hFe_MD4YRLO47nAoTcnmWPb6E2TK40glcepdZfcfam6sox3CX9e25QTs2yYm5pnDLvW6cqQOTkAJ5d2kcUXiUGTKAg4dCJDyjakquCwh5UZtfpKq9zusOrxGzq5Hv4p7oWfOCTjupxA2LHozt22Lv10uOTBiVdyJ0_Ik0T3tbDYegcHZlt5inXvtIc6drsNLQDCjCzSEWbdiyzq3VHHEeGgN9IP9NXOfwssWWxeJtD39IUL6SQ6C1LpVWXJ_oBQLnc131d0fBgT86iWHntC5w-zAbGvcxB2kz9CxzejBffCurVTXVh0dCm33CFd3DhGptn2oSI_r63YD8VFWtM0Q9NEWI61r9fuo6zIY6E1AQgNqsPQSkFExrcq6WqNqfbbq7BFR63MPiGhE2lBvIb6jIgn1B9R1hOB99lxaz6d-5FxqFfzUCyPILgX3kF3u509l4yd7ZXmjKJDo_YMEca5J21OAtmsqLVRQ4dYKsEMH7_SrvQLF2UY9fmkPD8OfW0tcDZHLMYZ-ZusqCPmpzwsTBQWxNkACwhuLBP_oeQbzuXIvhNl1mxQzz9NTImuRwfgr5S_E-zHiizdTqVzSTrVb1q2tsacOZn4Y9nPMVG4qejrcEq1qSZHpg1hYr_4D8g-0OOO3OrChRdWPS3T2IqTcqf74IBq-QZ_5nF_2csXUlOSv436G_LbS35jUz231rML25chdNGqVA16MM_huOWL6ertJoxMEiFt5mMSu7mi5ZfvRZVar5uf_yY4rU0_uafMPve45qIZJmGeHhqAdw1Moet0TFk3OuJKsQki37BGFjbYlFNpTp_3uKUuUmzdsbRnQGgMgQ9GwA1ICejVuYxCDOxGFr8LkXrZgiy8EaCLoxhvMWshHtzBmGua2c0fx-qfC3lY9be25ouFYv6gH_sIJQZRGpMR-t5AZ0GC2QdSCuEIfWCKX6pZQUZkYr5sfZQnYKwnVMufZGHHc_70Pcb90J3kVI-pNIlWqmRSw== |
46 | 46 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, |
47 | 47 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
48 | 48 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ |
49 | __version__ = "2.5.0" | |
49 | __version__ = "2.6.0rc0" | |
50 | 50 | __all__ = [ |
51 | 51 | "Proj", |
52 | 52 | "Geod", |
32 | 32 | cdef readonly object name |
33 | 33 | cdef readonly object _remarks |
34 | 34 | cdef readonly object _scope |
35 | ||
35 | cdef _set_base_info(self) | |
36 | 36 | |
37 | 37 | cdef class _CRSParts(Base): |
38 | 38 | pass |
0 | from typing import Any, Iterable, List, Optional, Tuple, Union | |
1 | ||
2 | from pyproj.crs.enums import CoordinateOperationType | |
3 | from pyproj.enums import ProjVersion, WktVersion | |
4 | ||
5 | class Axis: | |
6 | name: str | |
7 | abbrev: str | |
8 | direction: str | |
9 | unit_conversion_factor: float | |
10 | unit_name: str | |
11 | unit_auth_code: str | |
12 | unit_code: str | |
13 | def __str__(self) -> str: ... | |
14 | def __repr__(self) -> str: ... | |
15 | ||
16 | class AreaOfUse: | |
17 | west: float | |
18 | south: float | |
19 | east: float | |
20 | north: float | |
21 | name: str | |
22 | def __str__(self) -> str: ... | |
23 | def __repr__(self) -> str: ... | |
24 | @property | |
25 | def bounds(self) -> tuple[float]: ... | |
26 | ||
27 | class Base: | |
28 | name: str | |
29 | @property | |
30 | def remarks(self) -> str: ... | |
31 | @property | |
32 | def scope(self) -> str: ... | |
33 | def to_wkt( | |
34 | self, | |
35 | version: Union[WktVersion, str] = WktVersion.WKT2_2019, | |
36 | pretty: bool = False, | |
37 | ) -> str: ... | |
38 | def to_json(self, pretty: bool = False, indentation: int = 2) -> str: ... | |
39 | def to_json_dict(self) -> dict: ... | |
40 | def __str__(self) -> str: ... | |
41 | def __repr__(self) -> str: ... | |
42 | def __eq__(self, other: Any) -> bool: ... | |
43 | def is_exact_same(self, other: Any) -> bool: ... | |
44 | ||
45 | class _CRSParts(Base): | |
46 | @classmethod | |
47 | def from_user_input(cls, user_input: Any) -> "_CRSParts": ... | |
48 | ||
49 | class Ellipsoid(_CRSParts): | |
50 | semi_major_metre: float | |
51 | semi_minor_metre: float | |
52 | is_semi_minor_computed: float | |
53 | inverse_flattening: float | |
54 | @staticmethod | |
55 | def from_authority(auth_name: str, code: Union[int, str]) -> "Ellipsoid": ... | |
56 | @staticmethod | |
57 | def from_epsg(code: Union[int, str]) -> "Ellipsoid": ... | |
58 | @staticmethod | |
59 | def from_string(ellipsoid_string: str) -> "Ellipsoid": ... | |
60 | @staticmethod | |
61 | def from_json_dict(ellipsoid_dict: dict) -> "Ellipsoid": ... | |
62 | @staticmethod | |
63 | def from_json(ellipsoid_json_str: str) -> "Ellipsoid": ... | |
64 | @staticmethod | |
65 | def from_name( | |
66 | ellipsoid_name: str, auth_name: Optional[str] = None | |
67 | ) -> "Ellipsoid": ... | |
68 | ||
69 | class PrimeMeridian(_CRSParts): | |
70 | longitude: float | |
71 | unit_conversion_factor: str | |
72 | unit_name: str | |
73 | @staticmethod | |
74 | def from_authority(auth_name: str, code: Union[int, str]) -> "PrimeMeridian": ... | |
75 | @staticmethod | |
76 | def from_epsg(code: Union[int, str]) -> "PrimeMeridian": ... | |
77 | @staticmethod | |
78 | def from_string(prime_meridian_string: str) -> "PrimeMeridian": ... | |
79 | @staticmethod | |
80 | def from_json_dict(prime_meridian_dict: dict) -> "PrimeMeridian": ... | |
81 | @staticmethod | |
82 | def from_json(prime_meridian_json_str: str) -> "PrimeMeridian": ... | |
83 | @staticmethod | |
84 | def from_name( | |
85 | prime_meridian_name: str, auth_name: Optional[str] = None | |
86 | ) -> "PrimeMeridian": ... | |
87 | ||
88 | class Datum(_CRSParts): | |
89 | type_name: str | |
90 | @property | |
91 | def ellipsoid(self) -> Optional[Ellipsoid]: ... | |
92 | @property | |
93 | def prime_meridian(self) -> Optional[PrimeMeridian]: ... | |
94 | @staticmethod | |
95 | def from_authority(auth_name: str, code: Union[int, str]) -> "Datum": ... | |
96 | @staticmethod | |
97 | def from_epsg(code: Union[int, str]) -> "Datum": ... | |
98 | @staticmethod | |
99 | def from_string(datum_string: str) -> "Datum": ... | |
100 | @staticmethod | |
101 | def from_json_dict(datum_dict: dict) -> "Datum": ... | |
102 | @staticmethod | |
103 | def from_json(datum_json_str: str) -> "Datum": ... | |
104 | @staticmethod | |
105 | def from_name(datum_name: str, auth_name: Optional[str] = None) -> "Datum": ... | |
106 | ||
107 | class CoordinateSystem(_CRSParts): | |
108 | def __init__(self) -> None: ... | |
109 | @property | |
110 | def axis_list(self) -> Iterable[Axis]: ... | |
111 | @staticmethod | |
112 | def from_string(coordinate_system_string: str) -> "CoordinateSystem": ... | |
113 | @staticmethod | |
114 | def from_json_dict(coordinate_system_dict: dict) -> "CoordinateSystem": ... | |
115 | @staticmethod | |
116 | def from_json(coordinate_system_json_str: str) -> "CoordinateSystem": ... | |
117 | ||
118 | class Param: | |
119 | name: str | |
120 | auth_name: str | |
121 | code: str | |
122 | value: str | |
123 | unit_conversion_factor: float | |
124 | unit_name: str | |
125 | unit_auth_name: str | |
126 | unit_code: str | |
127 | unit_category: str | |
128 | def __str__(self) -> str: ... | |
129 | def __repr__(self) -> str: ... | |
130 | ||
131 | class Grid: | |
132 | short_name: str | |
133 | full_name: str | |
134 | package_name: str | |
135 | url: str | |
136 | direct_download: str | |
137 | open_license: str | |
138 | available: str | |
139 | def __str__(self) -> str: ... | |
140 | def __repr__(self) -> str: ... | |
141 | ||
142 | class CoordinateOperation(_CRSParts): | |
143 | method_name: str | |
144 | method_auth_name: str | |
145 | method_code: str | |
146 | accuracy: float | |
147 | is_instantiable: bool | |
148 | has_ballpark_transformation: bool | |
149 | type_name: str | |
150 | @property | |
151 | def params(self) -> Iterable[Param]: ... | |
152 | @property | |
153 | def grids(self) -> Iterable[Grid]: ... | |
154 | @property | |
155 | def area_of_use(self) -> Optional[AreaOfUse]: ... | |
156 | @property | |
157 | def towgs84(self) -> Iterable[float]: ... | |
158 | @property | |
159 | def operations(self) -> Tuple["CoordinateOperation"]: ... | |
160 | def __init__(self) -> None: ... | |
161 | def __repr__(self) -> str: ... | |
162 | @staticmethod | |
163 | def from_authority( | |
164 | auth_name: str, code: Union[int, str] | |
165 | ) -> "CoordinateOperation": ... | |
166 | @staticmethod | |
167 | def from_epsg(code: Union[int, str]) -> "CoordinateOperation": ... | |
168 | @staticmethod | |
169 | def from_string(ellipsoid_string: str) -> "CoordinateOperation": ... | |
170 | @staticmethod | |
171 | def from_json_dict(ellipsoid_dict: dict) -> "CoordinateOperation": ... | |
172 | @staticmethod | |
173 | def from_json(ellipsoid_json_str: str) -> "CoordinateOperation": ... | |
174 | def to_proj4( | |
175 | self, version: Union[ProjVersion, int] = ProjVersion.PROJ_5 | |
176 | ) -> str: ... | |
177 | @staticmethod | |
178 | def from_name( | |
179 | coordinate_operation_name: str, | |
180 | auth_name: Optional[str] = None, | |
181 | coordinate_operation_type: Union[ | |
182 | CoordinateOperationType, str | |
183 | ] = CoordinateOperationType.CONVERSION, | |
184 | ) -> "CoordinateOperation": ... | |
185 | ||
186 | class _CRS(Base): | |
187 | srs: str | |
188 | type_name: str | |
189 | def __init__(self, proj_string: str) -> None: ... | |
190 | @property | |
191 | def ellipsoid(self) -> Optional[Ellipsoid]: ... | |
192 | @property | |
193 | def area_of_use(self) -> Optional[AreaOfUse]: ... | |
194 | @property | |
195 | def axis_info(self) -> List[Axis]: ... | |
196 | @property | |
197 | def prime_meridian(self) -> Optional[PrimeMeridian]: ... | |
198 | @property | |
199 | def datum(self) -> Optional[Datum]: ... | |
200 | @property | |
201 | def sub_crs_list(self) -> Iterable["_CRS"]: ... | |
202 | @property | |
203 | def source_crs(self) -> Optional["_CRS"]: ... | |
204 | @property | |
205 | def target_crs(self) -> Optional["_CRS"]: ... | |
206 | @property | |
207 | def geodetic_crs(self) -> Optional["_CRS"]: ... | |
208 | @property | |
209 | def coordinate_system(self) -> Optional[CoordinateSystem]: ... | |
210 | @property | |
211 | def coordinate_operation(self) -> Optional[CoordinateOperation]: ... | |
212 | def to_proj4( | |
213 | self, version: Union[ProjVersion, int] = ProjVersion.PROJ_5 | |
214 | ) -> str: ... | |
215 | def to_epsg(self, min_confidence: int = 70) -> Optional[int]: ... | |
216 | def to_authority( | |
217 | self, auth_name: Optional[str] = None, min_confidence: int = 70 | |
218 | ): ... | |
219 | @property | |
220 | def is_geographic(self) -> bool: ... | |
221 | @property | |
222 | def is_projected(self) -> bool: ... | |
223 | @property | |
224 | def is_vertical(self) -> bool: ... | |
225 | @property | |
226 | def is_bound(self) -> bool: ... | |
227 | @property | |
228 | def is_engineering(self) -> bool: ... | |
229 | @property | |
230 | def is_geocentric(self) -> bool: ... | |
231 | def equals(self, other: Any, ignore_axis_order: bool) -> bool: ... | |
232 | ||
233 | def is_proj(proj_string: str) -> bool: ... | |
234 | def is_wkt(proj_string: str) -> bool: ... | |
235 | def _load_proj_json(in_proj_json: str) -> dict: ... |
101 | 101 | } |
102 | 102 | cdef PJ_WKT_TYPE wkt_out_type |
103 | 103 | wkt_out_type = supported_wkt_types[WktVersion.create(version)] |
104 | ||
104 | ||
105 | 105 | cdef const char* options_wkt[2] |
106 | 106 | multiline = b"MULTILINE=NO" |
107 | 107 | if pretty: |
128 | 128 | context: PJ_CONTEXT* |
129 | 129 | projobj: PJ* |
130 | 130 | version: pyproj.enums.ProjVersion |
131 | The version of the PROJ string output. | |
131 | The version of the PROJ string output. | |
132 | 132 | |
133 | 133 | Returns |
134 | 134 | ------- |
388 | 388 | if self.context != NULL: |
389 | 389 | proj_context_destroy(self.context) |
390 | 390 | |
391 | def _set_base_info(self): | |
391 | cdef _set_base_info(self): | |
392 | 392 | """ |
393 | 393 | Set the name of the PJ |
394 | 394 | """ |
409 | 409 | """ |
410 | 410 | .. versionadded:: 2.4.0 |
411 | 411 | |
412 | str: Remarks about object. | |
412 | Returns | |
413 | ------- | |
414 | str: | |
415 | Remarks about object. | |
413 | 416 | """ |
414 | 417 | return self._remarks |
415 | 418 | |
418 | 421 | """ |
419 | 422 | .. versionadded:: 2.4.0 |
420 | 423 | |
421 | str: Scope of object. | |
424 | Returns | |
425 | ------- | |
426 | str: | |
427 | Scope of object. | |
422 | 428 | """ |
423 | 429 | return self._scope |
424 | 430 | |
442 | 448 | Default is :attr:`pyproj.enums.WktVersion.WKT2_2019`. |
443 | 449 | pretty: bool |
444 | 450 | If True, it will set the output to be a multiline string. Defaults to False. |
445 | ||
446 | Returns | |
447 | ------- | |
448 | str: The WKT string. | |
451 | ||
452 | Returns | |
453 | ------- | |
454 | str | |
449 | 455 | """ |
450 | 456 | return _to_wkt(self.context, self.projobj, version, pretty=pretty) |
451 | 457 | |
461 | 467 | If True, it will set the output to be a multiline string. Defaults to False. |
462 | 468 | indentation: int |
463 | 469 | If pretty is True, it will set the width of the indentation. Default is 2. |
464 | ||
465 | Returns | |
466 | ------- | |
467 | str: The JSON string. | |
470 | ||
471 | Returns | |
472 | ------- | |
473 | str | |
468 | 474 | """ |
469 | 475 | cdef const char* options[3] |
470 | 476 | multiline = b"MULTILINE=NO" |
493 | 499 | |
494 | 500 | Returns |
495 | 501 | ------- |
496 | dict: The JSON dictionary. | |
502 | dict | |
497 | 503 | """ |
498 | 504 | return json.loads(self.to_json()) |
499 | 505 | |
618 | 624 | """ |
619 | 625 | Returns |
620 | 626 | ------- |
621 | list[Axis]: The Axis list for the coordinate system. | |
627 | list[Axis]: | |
628 | The Axis list for the coordinate system. | |
622 | 629 | """ |
623 | 630 | if self._axis_list is not None: |
624 | 631 | return self._axis_list |
682 | 689 | .. versionadded:: 2.5.0 |
683 | 690 | |
684 | 691 | Create Coordinate System from a JSON dictionary. |
685 | ||
692 | ||
686 | 693 | Parameters |
687 | 694 | ---------- |
688 | 695 | coordinate_system_dict: str |
893 | 900 | .. versionadded:: 2.4.0 |
894 | 901 | |
895 | 902 | Create Ellipsoid from a JSON dictionary. |
896 | ||
903 | ||
897 | 904 | Parameters |
898 | 905 | ---------- |
899 | 906 | ellipsoid_dict: str |
1593 | 1600 | """ |
1594 | 1601 | Returns |
1595 | 1602 | ------- |
1596 | Ellipsoid: The ellipsoid object with associated attributes. | |
1603 | Ellipsoid: | |
1604 | The ellipsoid object with associated attributes. | |
1597 | 1605 | """ |
1598 | 1606 | if self._ellipsoid is not None: |
1599 | 1607 | return None if self._ellipsoid is False else self._ellipsoid |
1616 | 1624 | """ |
1617 | 1625 | Returns |
1618 | 1626 | ------- |
1619 | PrimeMeridian: The CRS prime meridian object with associated attributes. | |
1627 | PrimeMeridian: | |
1628 | The CRS prime meridian object with associated attributes. | |
1620 | 1629 | """ |
1621 | 1630 | if self._prime_meridian is not None: |
1622 | 1631 | return None if self._prime_meridian is False else self._prime_meridian |
1663 | 1672 | unit_code: str |
1664 | 1673 | The code of the unit (i.e. 9807). |
1665 | 1674 | unit_category: str |
1666 | The category of the unit (“unknown”, “none”, “linear”, | |
1675 | The category of the unit (“unknown”, “none”, “linear”, | |
1667 | 1676 | “angular”, “scale”, “time” or “parametric”). |
1668 | 1677 | |
1669 | 1678 | """ |
1757 | 1766 | open_license: int |
1758 | 1767 | If 1, the grid is released with an open license. |
1759 | 1768 | available: int |
1760 | If 1, the grid is available at runtime. | |
1769 | If 1, the grid is available at runtime. | |
1761 | 1770 | |
1762 | 1771 | """ |
1763 | 1772 | def __cinit__(self): |
1851 | 1860 | The method code. |
1852 | 1861 | is_instantiable: int |
1853 | 1862 | If 1, a coordinate operation can be instantiated as a PROJ pipeline. |
1854 | This also checks that referenced grids are available. | |
1863 | This also checks that referenced grids are available. | |
1855 | 1864 | has_ballpark_transformation: int |
1856 | If 1, the coordinate operation has a “ballpark” transformation, | |
1857 | that is a very approximate one, due to lack of more accurate transformations. | |
1865 | If 1, the coordinate operation has a “ballpark” transformation, | |
1866 | that is a very approximate one, due to lack of more accurate transformations. | |
1858 | 1867 | accuracy: float |
1859 | The accuracy (in metre) of a coordinate operation. | |
1868 | The accuracy (in metre) of a coordinate operation. | |
1860 | 1869 | |
1861 | 1870 | """ |
1862 | 1871 | def __cinit__(self): |
2136 | 2145 | """ |
2137 | 2146 | Returns |
2138 | 2147 | ------- |
2139 | list[Param]: The coordinate operation parameters. | |
2148 | List[Param]: | |
2149 | The coordinate operation parameters. | |
2140 | 2150 | """ |
2141 | 2151 | if self._params is not None: |
2142 | 2152 | return self._params |
2162 | 2172 | """ |
2163 | 2173 | Returns |
2164 | 2174 | ------- |
2165 | list[Grid]: The coordinate operation grids. | |
2175 | List[Grid]: | |
2176 | The coordinate operation grids. | |
2166 | 2177 | """ |
2167 | 2178 | if self._grids is not None: |
2168 | 2179 | return self._grids |
2188 | 2199 | """ |
2189 | 2200 | Returns |
2190 | 2201 | ------- |
2191 | AreaOfUse: The area of use object with associated attributes. | |
2202 | AreaOfUse: | |
2203 | The area of use object with associated attributes. | |
2192 | 2204 | """ |
2193 | 2205 | if self._area_of_use is not None: |
2194 | 2206 | return self._area_of_use |
2202 | 2214 | Parameters |
2203 | 2215 | ---------- |
2204 | 2216 | version: pyproj.enums.ProjVersion |
2205 | The version of the PROJ string output. | |
2217 | The version of the PROJ string output. | |
2206 | 2218 | Default is :attr:`pyproj.enums.ProjVersion.PROJ_5`. |
2207 | 2219 | |
2208 | 2220 | Returns |
2209 | 2221 | ------- |
2210 | str: The PROJ string. | |
2222 | str: | |
2223 | The PROJ string. | |
2224 | ||
2211 | 2225 | """ |
2212 | 2226 | return _to_proj4(self.context, self.projobj, version) |
2213 | 2227 | |
2216 | 2230 | """ |
2217 | 2231 | Returns |
2218 | 2232 | ------- |
2219 | list(float): A list of 3 or 7 towgs84 values if they exist. | |
2220 | Otherwise an empty list. | |
2233 | List[float]: | |
2234 | A list of 3 or 7 towgs84 values if they exist. | |
2235 | ||
2221 | 2236 | """ |
2222 | 2237 | if self._towgs84 is not None: |
2223 | 2238 | return self._towgs84 |
2224 | 2239 | towgs84_dict = OrderedDict( |
2225 | 2240 | ( |
2226 | ('X-axis translation', None), | |
2241 | ('X-axis translation', None), | |
2227 | 2242 | ('Y-axis translation', None), |
2228 | 2243 | ('Z-axis translation', None), |
2229 | 2244 | ('X-axis rotation', None), |
2243 | 2258 | """ |
2244 | 2259 | .. versionadded:: 2.4.0 |
2245 | 2260 | |
2246 | tuple[CoordinateOperation]: The operations in a concatenated operation. | |
2261 | Returns | |
2262 | ------- | |
2263 | Tuple[CoordinateOperation]: | |
2264 | The operations in a concatenated operation. | |
2265 | ||
2247 | 2266 | """ |
2248 | 2267 | if self._operations is not None: |
2249 | 2268 | return self._operations |
2253 | 2272 | def __repr__(self): |
2254 | 2273 | return ( |
2255 | 2274 | "<Coordinate Operation: {type_name}>\n" |
2256 | "{name}\n" | |
2275 | "Name: {name}\n" | |
2276 | "Method: {method_name}\n" | |
2257 | 2277 | "Area of Use:\n{area_of_use}" |
2258 | 2278 | ).format( |
2259 | 2279 | type_name=self.type_name, |
2260 | 2280 | name=self.name, |
2281 | method_name=self.method_name, | |
2261 | 2282 | area_of_use=self.area_of_use or "- undefined", |
2262 | 2283 | ) |
2263 | 2284 | |
2324 | 2345 | @property |
2325 | 2346 | def axis_info(self): |
2326 | 2347 | """ |
2327 | Returns | |
2328 | ------- | |
2329 | list[Axis]: The list of axis information. | |
2330 | """ | |
2331 | return self.coordinate_system.axis_list if self.coordinate_system else [] | |
2348 | Retrieves all relevant axis information in the CRS. | |
2349 | If it is a Bound CRS, it gets the axis list from the Source CRS. | |
2350 | If it is a Compound CRS, it gets the axis list from the Sub CRS list. | |
2351 | ||
2352 | Returns | |
2353 | ------- | |
2354 | List[Axis]: | |
2355 | The list of axis information. | |
2356 | """ | |
2357 | axis_info_list = [] | |
2358 | if self.coordinate_system: | |
2359 | axis_info_list.extend(self.coordinate_system.axis_list) | |
2360 | elif self.is_bound and self.source_crs: | |
2361 | axis_info_list.extend(self.source_crs.axis_info) | |
2362 | else: | |
2363 | for sub_crs in self.sub_crs_list: | |
2364 | axis_info_list.extend(sub_crs.axis_info) | |
2365 | return axis_info_list | |
2332 | 2366 | |
2333 | 2367 | @property |
2334 | 2368 | def area_of_use(self): |
2335 | 2369 | """ |
2336 | 2370 | Returns |
2337 | 2371 | ------- |
2338 | AreaOfUse: The area of use object with associated attributes. | |
2372 | AreaOfUse: | |
2373 | The area of use object with associated attributes. | |
2339 | 2374 | """ |
2340 | 2375 | if self._area_of_use is not None: |
2341 | 2376 | return self._area_of_use |
2349 | 2384 | |
2350 | 2385 | Returns |
2351 | 2386 | ------- |
2352 | Ellipsoid: The ellipsoid object with associated attributes. | |
2387 | Ellipsoid: | |
2388 | The ellipsoid object with associated attributes. | |
2353 | 2389 | """ |
2354 | 2390 | if self._ellipsoid is not None: |
2355 | 2391 | return None if self._ellipsoid is False else self._ellipsoid |
2374 | 2410 | |
2375 | 2411 | Returns |
2376 | 2412 | ------- |
2377 | PrimeMeridian: The prime meridian object with associated attributes. | |
2413 | PrimeMeridian: | |
2414 | The prime meridian object with associated attributes. | |
2378 | 2415 | """ |
2379 | 2416 | if self._prime_meridian is not None: |
2380 | 2417 | return None if self._prime_meridian is True else self._prime_meridian |
2399 | 2436 | |
2400 | 2437 | Returns |
2401 | 2438 | ------- |
2402 | Datum: The datum. | |
2439 | Datum | |
2403 | 2440 | """ |
2404 | 2441 | if self._datum is not None: |
2405 | 2442 | return None if self._datum is False else self._datum |
2429 | 2466 | |
2430 | 2467 | Returns |
2431 | 2468 | ------- |
2432 | CoordinateSystem: The coordinate system. | |
2469 | CoordinateSystem | |
2433 | 2470 | """ |
2434 | 2471 | if self._coordinate_system is not None: |
2435 | 2472 | return None if self._coordinate_system is False else self._coordinate_system |
2458 | 2495 | |
2459 | 2496 | Returns |
2460 | 2497 | ------- |
2461 | CoordinateOperation: The coordinate operation. | |
2498 | CoordinateOperation | |
2462 | 2499 | """ |
2463 | 2500 | if self._coordinate_operation is not None: |
2464 | 2501 | return ( |
2465 | 2502 | None |
2466 | if self._coordinate_operation is False | |
2503 | if self._coordinate_operation is False | |
2467 | 2504 | else self._coordinate_operation |
2468 | 2505 | ) |
2469 | 2506 | cdef PJ_CONTEXT* context = proj_context_create() |
2486 | 2523 | @property |
2487 | 2524 | def source_crs(self): |
2488 | 2525 | """ |
2489 | Returns | |
2490 | ------- | |
2491 | _CRS: The the base CRS of a BoundCRS or a DerivedCRS/ProjectedCRS, | |
2492 | or the source CRS of a CoordinateOperation. | |
2526 | The the base CRS of a BoundCRS or a DerivedCRS/ProjectedCRS, | |
2527 | or the source CRS of a CoordinateOperation. | |
2528 | ||
2529 | Returns | |
2530 | ------- | |
2531 | _CRS | |
2493 | 2532 | """ |
2494 | 2533 | if self._source_crs is not None: |
2495 | 2534 | return None if self._source_crs is False else self._source_crs |
2511 | 2550 | |
2512 | 2551 | Returns |
2513 | 2552 | ------- |
2514 | _CRS: The hub CRS of a BoundCRS or the target CRS of a CoordinateOperation. | |
2553 | _CRS: | |
2554 | The hub CRS of a BoundCRS or the target CRS of a CoordinateOperation. | |
2515 | 2555 | """ |
2516 | 2556 | if self._target_crs is not None: |
2517 | 2557 | return None if self._target_crs is False else self._target_crs |
2533 | 2573 | |
2534 | 2574 | Returns |
2535 | 2575 | ------- |
2536 | list[_CRS] | |
2576 | List[_CRS] | |
2537 | 2577 | """ |
2538 | 2578 | if self._sub_crs_list is not None: |
2539 | 2579 | return self._sub_crs_list |
2563 | 2603 | """ |
2564 | 2604 | .. versionadded:: 2.2.0 |
2565 | 2605 | |
2566 | Returns | |
2567 | ------- | |
2568 | _CRS: The the geodeticCRS / geographicCRS from the CRS. | |
2606 | The the geodeticCRS / geographicCRS from the CRS. | |
2607 | ||
2608 | Returns | |
2609 | ------- | |
2610 | _CRS | |
2569 | 2611 | """ |
2570 | 2612 | if self._geodetic_crs is not None: |
2571 | 2613 | return self._geodetic_crs if self. _geodetic_crs is not False else None |
2591 | 2633 | Parameters |
2592 | 2634 | ---------- |
2593 | 2635 | version: pyproj.enums.ProjVersion |
2594 | The version of the PROJ string output. | |
2636 | The version of the PROJ string output. | |
2595 | 2637 | Default is :attr:`pyproj.enums.ProjVersion.PROJ_4`. |
2596 | 2638 | |
2597 | 2639 | Returns |
2598 | 2640 | ------- |
2599 | str: The PROJ string. | |
2641 | str | |
2600 | 2642 | """ |
2601 | 2643 | warnings.warn( |
2602 | 2644 | "You will likely lose important projection information when " |
2605 | 2647 | "coordinate-reference-systems" |
2606 | 2648 | ) |
2607 | 2649 | return _to_proj4(self.context, self.projobj, version) |
2608 | ||
2650 | ||
2609 | 2651 | def to_epsg(self, min_confidence=70): |
2610 | 2652 | """ |
2611 | 2653 | Return the EPSG code best matching the CRS |
2612 | 2654 | or None if it a match is not found. |
2613 | 2655 | |
2614 | Example: | |
2656 | Example: | |
2615 | 2657 | |
2616 | 2658 | >>> from pyproj import CRS |
2617 | 2659 | >>> ccs = CRS("epsg:4328") |
2638 | 2680 | |
2639 | 2681 | Returns |
2640 | 2682 | ------- |
2641 | int or None: The best matching EPSG code matching the confidence level. | |
2683 | Optional[int]: | |
2684 | The best matching EPSG code matching the confidence level. | |
2642 | 2685 | """ |
2643 | 2686 | auth_info = self.to_authority( |
2644 | 2687 | auth_name="EPSG", |
2655 | 2698 | Return the authority name and code best matching the CRS |
2656 | 2699 | or None if it a match is not found. |
2657 | 2700 | |
2658 | Example: | |
2701 | Example: | |
2659 | 2702 | |
2660 | 2703 | >>> from pyproj import CRS |
2661 | 2704 | >>> ccs = CRS("epsg:4328") |
2683 | 2726 | |
2684 | 2727 | Returns |
2685 | 2728 | ------- |
2686 | tuple(str, str) or None: The best matching (<auth_name>, <code>) | |
2687 | matching the confidence level. | |
2729 | tuple(str, str) or None: | |
2730 | The best matching (<auth_name>, <code>) for the confidence level. | |
2688 | 2731 | """ |
2689 | 2732 | # get list of possible matching projections |
2690 | 2733 | cdef PJ_OBJ_LIST *proj_list = NULL |
2767 | 2810 | |
2768 | 2811 | Returns |
2769 | 2812 | ------- |
2770 | bool: True if the CRS has this property. | |
2813 | bool: | |
2814 | True if the CRS has this property. | |
2771 | 2815 | """ |
2772 | 2816 | if self.sub_crs_list: |
2773 | 2817 | sub_crs = self.sub_crs_list[sub_crs_index] |
2786 | 2830 | """ |
2787 | 2831 | This checks if the CRS is geographic. |
2788 | 2832 | It will check if it has a geographic CRS |
2789 | in the sub CRS if it is a compount CRS and will check if | |
2833 | in the sub CRS if it is a compount CRS and will check if | |
2790 | 2834 | the source CRS is geographic if it is a bound CRS. |
2791 | 2835 | |
2792 | 2836 | Returns |
2793 | 2837 | ------- |
2794 | bool: True if the CRS is in geographic (lon/lat) coordinates. | |
2838 | bool: | |
2839 | True if the CRS is in geographic (lon/lat) coordinates. | |
2795 | 2840 | """ |
2796 | 2841 | return self._is_crs_property( |
2797 | "is_geographic", | |
2842 | "is_geographic", | |
2798 | 2843 | ( |
2799 | 2844 | PJ_TYPE_GEOGRAPHIC_CRS, |
2800 | 2845 | PJ_TYPE_GEOGRAPHIC_2D_CRS, |
2812 | 2857 | |
2813 | 2858 | Returns |
2814 | 2859 | ------- |
2815 | bool: True if CRS is projected. | |
2860 | bool: | |
2861 | True if CRS is projected. | |
2816 | 2862 | """ |
2817 | 2863 | return self._is_crs_property( |
2818 | "is_projected", | |
2864 | "is_projected", | |
2819 | 2865 | (PJ_TYPE_PROJECTED_CRS,) |
2820 | 2866 | ) |
2821 | 2867 | |
2826 | 2872 | |
2827 | 2873 | This checks if the CRS is vertical. |
2828 | 2874 | It will check if it has a vertical CRS |
2829 | in the sub CRS if it is a compount CRS and will check if | |
2875 | in the sub CRS if it is a compount CRS and will check if | |
2830 | 2876 | the source CRS is vertical if it is a bound CRS. |
2831 | 2877 | |
2832 | 2878 | Returns |
2833 | 2879 | ------- |
2834 | bool: True if CRS is vertical. | |
2880 | bool: | |
2881 | True if CRS is vertical. | |
2835 | 2882 | """ |
2836 | 2883 | return self._is_crs_property( |
2837 | "is_vertical", | |
2884 | "is_vertical", | |
2838 | 2885 | (PJ_TYPE_VERTICAL_CRS,), |
2839 | 2886 | sub_crs_index=1 |
2840 | 2887 | ) |
2844 | 2891 | """ |
2845 | 2892 | Returns |
2846 | 2893 | ------- |
2847 | bool: True if CRS is bound. | |
2894 | bool: | |
2895 | True if CRS is bound. | |
2848 | 2896 | """ |
2849 | 2897 | return self._type == PJ_TYPE_BOUND_CRS |
2850 | 2898 | |
2855 | 2903 | |
2856 | 2904 | Returns |
2857 | 2905 | ------- |
2858 | bool: True if CRS is local/engineering. | |
2906 | bool: | |
2907 | True if CRS is local/engineering. | |
2859 | 2908 | """ |
2860 | 2909 | return self._type == PJ_TYPE_ENGINEERING_CRS |
2861 | 2910 | |
2867 | 2916 | |
2868 | 2917 | Returns |
2869 | 2918 | ------- |
2870 | bool: True if CRS is in geocentric (x/y) coordinates. | |
2919 | bool: | |
2920 | True if CRS is in geocentric (x/y) coordinates. | |
2871 | 2921 | """ |
2872 | 2922 | if self.is_bound: |
2873 | 2923 | return self.source_crs.is_geocentric |
2 | 2 | cdef void pyproj_context_initialize(PJ_CONTEXT* context, bint free_context_on_error) except * |
3 | 3 | |
4 | 4 | cdef class ContextManager: |
5 | cdef PJ_CONTEXT *context⏎ | |
5 | cdef PJ_CONTEXT *context |
0 | def pyproj_global_context_initialize() -> None: ... |
27 | 27 | cdef class Geod: |
28 | 28 | cdef geod_geodesic _geod_geodesic |
29 | 29 | cdef readonly object initstring |
30 | cdef readonly object a | |
31 | cdef readonly object b | |
32 | cdef readonly object f | |
33 | cdef readonly object es | |
34 | cdef readonly object sphere | |
30 | cdef readonly double a | |
31 | cdef readonly double b | |
32 | cdef readonly double f | |
33 | cdef readonly double es | |
34 | cdef readonly bint sphere |
0 | from typing import Any, Tuple, Type | |
1 | ||
2 | geodesic_version_str: str | |
3 | ||
4 | class Geod: | |
5 | initstring: str | |
6 | a: float | |
7 | b: float | |
8 | f: float | |
9 | es: float | |
10 | sphere: bool | |
11 | def __init__( | |
12 | self, a: float, f: float, sphere: bool, b: float, es: float | |
13 | ) -> None: ... | |
14 | def __reduce__(self) -> Tuple[Type["Geod"], str]: ... | |
15 | def __repr__(self) -> str: ... | |
16 | def _fwd( | |
17 | self, lons: Any, lats: Any, az: Any, dist: Any, radians: bool = False | |
18 | ) -> None: ... | |
19 | def _inv( | |
20 | self, lons1: Any, lats1: Any, lons2: Any, lats2: Any, radians: bool = False | |
21 | ) -> None: ... | |
22 | def _npts( | |
23 | self, | |
24 | lon1: float, | |
25 | lat1: float, | |
26 | lon2: float, | |
27 | lat2: float, | |
28 | npts: int, | |
29 | radians: bool = False, | |
30 | ) -> Tuple[Tuple[float], Tuple[float]]: ... | |
31 | def _line_length(self, lons: Any, lats: Any, radians: bool = False) -> float: ... | |
32 | def _polygon_area_perimeter( | |
33 | self, lons: Any, lats: Any, radians: bool = False | |
34 | ) -> Tuple[float, float]: ... |
11 | 11 | ) |
12 | 12 | |
13 | 13 | cdef class Geod: |
14 | def __init__(self, a, f, sphere, b, es): | |
14 | def __init__(self, double a, double f, bint sphere, double b, double es): | |
15 | 15 | geod_init(&self._geod_geodesic, <double> a, <double> f) |
16 | 16 | self.a = a |
17 | 17 | self.f = f |
18 | if isinstance(a, float) and a.is_integer(): | |
19 | # convert 'a' only for initstring | |
20 | a = int(a) | |
21 | if f == 0.0: | |
22 | f = 0 | |
23 | self.initstring = pystrdecode(cstrencode("+a=%s +f=%s" % (a, f))) | |
18 | # convert 'a' only for initstring | |
19 | a_str = int(a) if a.is_integer() else a | |
20 | f_str = int(f) if f.is_integer() else f | |
21 | self.initstring = pystrdecode(cstrencode("+a=%s +f=%s" % (a_str, f_str))) | |
24 | 22 | self.sphere = sphere |
25 | 23 | self.b = b |
26 | 24 | self.es = es |
42 | 40 | cdef PyBuffWriteManager latbuff = PyBuffWriteManager(lats) |
43 | 41 | cdef PyBuffWriteManager azbuff = PyBuffWriteManager(az) |
44 | 42 | cdef PyBuffWriteManager distbuff = PyBuffWriteManager(dist) |
45 | ||
43 | ||
46 | 44 | # process data in buffer |
47 | 45 | if not lonbuff.len == latbuff.len == azbuff.len == distbuff.len: |
48 | 46 | raise GeodError("Array lengths are not the same.") |
188 | 186 | |
189 | 187 | Returns |
190 | 188 | ------- |
191 | float: The total distance. | |
192 | ||
189 | float: | |
190 | The total distance. | |
191 | ||
193 | 192 | """ |
194 | 193 | cdef PyBuffWriteManager lonbuff = PyBuffWriteManager(lons) |
195 | 194 | cdef PyBuffWriteManager latbuff = PyBuffWriteManager(lats) |
231 | 230 | def _polygon_area_perimeter(self, object lons, object lats, bint radians=False): |
232 | 231 | """ |
233 | 232 | A simple interface for computing the area of a geodesic polygon. |
234 | ||
233 | ||
235 | 234 | lats should be in the range [-90 deg, 90 deg]. |
236 | ||
235 | ||
237 | 236 | Only simple polygons (which are not self-intersecting) are allowed. |
238 | 237 | There's no need to "close" the polygon by repeating the first vertex. |
239 | 238 | The area returned is signed with counter-clockwise traversal being treated as |
250 | 249 | |
251 | 250 | Returns |
252 | 251 | ------- |
253 | (float, float): The area (meter^2) and permimeter (meters) of the polygon. | |
252 | (float, float): | |
253 | The area (meter^2) and permimeter (meters) of the polygon. | |
254 | 254 | |
255 | 255 | """ |
256 | 256 | cdef PyBuffWriteManager lonbuff = PyBuffWriteManager(lons) |
272 | 272 | |
273 | 273 | geod_polygonarea( |
274 | 274 | &self._geod_geodesic, |
275 | latbuff.data, lonbuff.data, lonbuff.len, | |
275 | latbuff.data, lonbuff.data, lonbuff.len, | |
276 | 276 | &polygon_area, &polygon_perimeter |
277 | 277 | ) |
278 | 278 | return (polygon_area, polygon_perimeter) |
0 | from typing import Dict, List, NamedTuple, Union | |
1 | ||
2 | from pyproj.enums import PJType | |
3 | ||
4 | def get_proj_operations_map() -> Dict[str, str]: ... | |
5 | def get_ellps_map() -> Dict[str, Dict[str, float]]: ... | |
6 | def get_prime_meridians_map() -> Dict[str, str]: ... | |
7 | ||
8 | class Unit(NamedTuple): | |
9 | id: str | |
10 | to_meter: str | |
11 | name: str | |
12 | factor: float | |
13 | ||
14 | def get_units_map() -> Dict[str, Unit]: ... | |
15 | def get_angular_units_map() -> Dict[str, Unit]: ... | |
16 | def get_authorities() -> List[str]: ... | |
17 | def get_codes( | |
18 | auth_name: str, pj_type: Union[PJType, str], allow_deprecated: bool = False | |
19 | ) -> List[str]: ... |
10 | 10 | """ |
11 | 11 | Returns |
12 | 12 | ------- |
13 | dict: operations supported by PROJ. | |
13 | dict: | |
14 | Operations supported by PROJ. | |
14 | 15 | """ |
15 | 16 | cdef PJ_OPERATIONS *proj_operations = proj_list_operations() |
16 | 17 | cdef int iii = 0 |
26 | 27 | """ |
27 | 28 | Returns |
28 | 29 | ------- |
29 | dict: ellipsoids supported by PROJ. | |
30 | dict: | |
31 | Ellipsoids supported by PROJ. | |
30 | 32 | """ |
31 | 33 | cdef PJ_ELLPS *proj_ellps = proj_list_ellps() |
32 | 34 | cdef int iii = 0 |
47 | 49 | """ |
48 | 50 | Returns |
49 | 51 | ------- |
50 | dict: prime meridians supported by PROJ. | |
52 | dict: | |
53 | Prime Meridians supported by PROJ. | |
51 | 54 | """ |
52 | 55 | cdef PJ_PRIME_MERIDIANS *prime_meridians = proj_list_prime_meridians() |
53 | 56 | cdef int iii = 0 |
66 | 69 | """ |
67 | 70 | Returns |
68 | 71 | ------- |
69 | dict: units supported by PROJ | |
72 | dict: | |
73 | Units supported by PROJ | |
70 | 74 | """ |
71 | 75 | cdef PJ_UNITS *proj_units = proj_list_units() |
72 | 76 | cdef int iii = 0 |
86 | 90 | """ |
87 | 91 | Returns |
88 | 92 | ------- |
89 | dict: angular units supported by PROJ | |
93 | dict: | |
94 | Angular units supported by PROJ | |
90 | 95 | """ |
91 | 96 | cdef PJ_UNITS *proj_units = proj_list_angular_units() |
92 | 97 | cdef int iii = 0 |
108 | 113 | |
109 | 114 | Returns |
110 | 115 | ------- |
111 | list[str]: Authorities in PROJ database. | |
116 | List[str]: | |
117 | Authorities in PROJ database. | |
112 | 118 | """ |
113 | 119 | cdef PJ_CONTEXT* context = proj_context_create() |
114 | 120 | pyproj_context_initialize(context, True) |
171 | 177 | |
172 | 178 | Returns |
173 | 179 | ------- |
174 | list[str]: Codes associated with authorities in PROJ database. | |
180 | List[str]: | |
181 | Codes associated with authorities in PROJ database. | |
175 | 182 | """ |
176 | 183 | cdef PJ_CONTEXT* context = NULL |
177 | 184 | cdef PJ_TYPE cpj_type = PJ_TYPE_MAP[PJType.create(pj_type)] |
0 | 0 | include "proj.pxi" |
1 | 1 | |
2 | cdef class Proj: | |
2 | cdef class _Proj: | |
3 | 3 | cdef PJ * projobj |
4 | 4 | cdef PJ_CONTEXT* context |
5 | 5 | cdef PJ_PROJ_INFO projobj_info |
0 | from typing import Any, NamedTuple | |
1 | ||
2 | proj_version_str: str | |
3 | ||
4 | class Factors(NamedTuple): | |
5 | meridional_scale: float | |
6 | parallel_scale: float | |
7 | areal_scale: float | |
8 | angular_distortion: float | |
9 | meridian_parallel_angle: float | |
10 | meridian_convergence: float | |
11 | tissot_semimajor: float | |
12 | tissot_semiminor: float | |
13 | dx_dlam: float | |
14 | dx_dphi: float | |
15 | dy_dlam: float | |
16 | dy_dphi: float | |
17 | ||
18 | class _Proj: | |
19 | srs: str | |
20 | def __init__(self, proj_string: str) -> None: ... | |
21 | @property | |
22 | def definition(self) -> str: ... | |
23 | @property | |
24 | def has_inverse(self) -> bool: ... | |
25 | def _fwd(self, lons: Any, lats: Any, errcheck: bool = False) -> None: ... | |
26 | def _inv(self, x: Any, y: Any, errcheck: bool = False) -> None: ... | |
27 | def _get_factors( | |
28 | self, longitude: Any, latitude: Any, radians: bool, errcheck: bool | |
29 | ) -> Factors: ... | |
30 | def __repr__(self) -> str: ... | |
31 | def _is_equivalent(self, other: "_Proj") -> bool: ... | |
32 | def is_exact_same(self, other: Any) -> bool: ... |
0 | 0 | include "base.pxi" |
1 | 1 | |
2 | import copy | |
2 | 3 | import warnings |
4 | from collections import namedtuple | |
3 | 5 | |
4 | 6 | cimport cython |
5 | 7 | |
7 | 9 | from pyproj.compat import cstrencode, pystrdecode |
8 | 10 | from pyproj.exceptions import ProjError |
9 | 11 | |
10 | # # version number string for PROJ | |
12 | # version number string for PROJ | |
11 | 13 | proj_version_str = "{0}.{1}.{2}".format( |
12 | 14 | PROJ_VERSION_MAJOR, |
13 | 15 | PROJ_VERSION_MINOR, |
14 | 16 | PROJ_VERSION_PATCH |
15 | 17 | ) |
16 | 18 | |
17 | cdef class Proj: | |
19 | ||
20 | Factors = namedtuple("Factors", | |
21 | [ | |
22 | "meridional_scale", | |
23 | "parallel_scale", | |
24 | "areal_scale", | |
25 | "angular_distortion", | |
26 | "meridian_parallel_angle", | |
27 | "meridian_convergence", | |
28 | "tissot_semimajor", | |
29 | "tissot_semiminor", | |
30 | "dx_dlam", | |
31 | "dx_dphi", | |
32 | "dy_dlam", | |
33 | "dy_dphi", | |
34 | ] | |
35 | ) | |
36 | Factors.__doc__ = """ | |
37 | .. versionadded:: 2.6.0 | |
38 | ||
39 | These are the scaling and angular distortion factors. | |
40 | ||
41 | See `PJ_FACTORS documentation <https://proj.org/development/reference/datatypes.html?highlight=pj_factors#c.PJ_FACTORS>`__ | |
42 | ||
43 | Parameters | |
44 | ---------- | |
45 | meridional_scale: List[float] | |
46 | Meridional scale at coordinate. | |
47 | parallel_scale: List[float] | |
48 | Parallel scale at coordinate. | |
49 | areal_scale: List[float] | |
50 | Areal scale factor at coordinate. | |
51 | angular_distortion: List[float] | |
52 | Angular distortion at coordinate. | |
53 | meridian_parallel_angle: List[float] | |
54 | Meridian/parallel angle at coordinate. | |
55 | meridian_convergence: List[float] | |
56 | Meridian convergence at coordinate. Sometimes also described as *grid declination*. | |
57 | tissot_semimajor: List[float] | |
58 | Maximum scale factor. | |
59 | tissot_semiminor: List[float] | |
60 | Minimum scale factor. | |
61 | dx_dlam: List[float] | |
62 | Partial derivative of coordinate. | |
63 | dx_dphi: List[float] | |
64 | Partial derivative of coordinate. | |
65 | dy_dlam: List[float] | |
66 | Partial derivative of coordinate. | |
67 | dy_dphi: List[float] | |
68 | Partial derivative of coordinate. | |
69 | """ | |
70 | ||
71 | ||
72 | cdef class _Proj: | |
18 | 73 | def __cinit__(self): |
19 | 74 | self.projobj = NULL |
20 | 75 | self.context = NULL |
186 | 241 | ybuff.data[iii] = projlonlatout.uv.v |
187 | 242 | ProjError.clear() |
188 | 243 | |
244 | @cython.boundscheck(False) | |
245 | @cython.wraparound(False) | |
246 | def _get_factors(self, longitude, latitude, bint radians, bint errcheck): | |
247 | """ | |
248 | Calculates the projection factors PJ_FACTORS | |
249 | ||
250 | Equivalent to `proj -S` command line. | |
251 | """ | |
252 | cdef PyBuffWriteManager lonbuff = PyBuffWriteManager(longitude) | |
253 | cdef PyBuffWriteManager latbuff = PyBuffWriteManager(longitude) | |
254 | ||
255 | if not lonbuff.len or not (lonbuff.len == latbuff.len): | |
256 | raise ProjError('longitude and latitude must be same size') | |
257 | ||
258 | # prepare the factors output | |
259 | meridional_scale = copy.copy(longitude) | |
260 | parallel_scale = copy.copy(longitude) | |
261 | areal_scale = copy.copy(longitude) | |
262 | angular_distortion = copy.copy(longitude) | |
263 | meridian_parallel_angle = copy.copy(longitude) | |
264 | meridian_convergence = copy.copy(longitude) | |
265 | tissot_semimajor = copy.copy(longitude) | |
266 | tissot_semiminor = copy.copy(longitude) | |
267 | dx_dlam = copy.copy(longitude) | |
268 | dx_dphi = copy.copy(longitude) | |
269 | dy_dlam = copy.copy(longitude) | |
270 | dy_dphi = copy.copy(longitude) | |
271 | cdef PyBuffWriteManager meridional_scale_buff = PyBuffWriteManager(meridional_scale) | |
272 | cdef PyBuffWriteManager parallel_scale_buff = PyBuffWriteManager(parallel_scale) | |
273 | cdef PyBuffWriteManager areal_scale_buff = PyBuffWriteManager(areal_scale) | |
274 | cdef PyBuffWriteManager angular_distortion_buff = PyBuffWriteManager(angular_distortion) | |
275 | cdef PyBuffWriteManager meridian_parallel_angle_buff = PyBuffWriteManager(meridian_parallel_angle) | |
276 | cdef PyBuffWriteManager meridian_convergence_buff = PyBuffWriteManager(meridian_convergence) | |
277 | cdef PyBuffWriteManager tissot_semimajor_buff = PyBuffWriteManager(tissot_semimajor) | |
278 | cdef PyBuffWriteManager tissot_semiminor_buff = PyBuffWriteManager(tissot_semiminor) | |
279 | cdef PyBuffWriteManager dx_dlam_buff = PyBuffWriteManager(dx_dlam) | |
280 | cdef PyBuffWriteManager dx_dphi_buff = PyBuffWriteManager(dx_dphi) | |
281 | cdef PyBuffWriteManager dy_dlam_buff = PyBuffWriteManager(dy_dlam) | |
282 | cdef PyBuffWriteManager dy_dphi_buff = PyBuffWriteManager(dy_dphi) | |
283 | ||
284 | # calculate the factors | |
285 | cdef PJ_COORD pj_coord = proj_coord(0, 0, 0, HUGE_VAL) | |
286 | cdef PJ_FACTORS pj_factors | |
287 | cdef int errno = 0 | |
288 | cdef bint invalid_coord = 0 | |
289 | cdef Py_ssize_t iii | |
290 | with nogil: | |
291 | for iii in range(lonbuff.len): | |
292 | pj_coord.uv.u = lonbuff.data[iii] | |
293 | pj_coord.uv.v = latbuff.data[iii] | |
294 | if not radians: | |
295 | pj_coord.uv.u *= _DG2RAD | |
296 | pj_coord.uv.v *= _DG2RAD | |
297 | ||
298 | # set both to HUGE_VAL if inf or nan | |
299 | proj_errno_reset(self.projobj) | |
300 | if pj_coord.uv.v == HUGE_VAL \ | |
301 | or pj_coord.uv.v != pj_coord.uv.v \ | |
302 | or pj_coord.uv.u == HUGE_VAL \ | |
303 | or pj_coord.uv.u != pj_coord.uv.u: | |
304 | invalid_coord = True | |
305 | else: | |
306 | invalid_coord = False | |
307 | pj_factors = proj_factors(self.projobj, pj_coord) | |
308 | ||
309 | errno = proj_errno(self.projobj) | |
310 | if errcheck and errno: | |
311 | with gil: | |
312 | raise ProjError("proj error: {}".format( | |
313 | pystrdecode(proj_errno_string(errno)))) | |
314 | ||
315 | if errno or invalid_coord: | |
316 | meridional_scale_buff.data[iii] = HUGE_VAL | |
317 | parallel_scale_buff.data[iii] = HUGE_VAL | |
318 | areal_scale_buff.data[iii] = HUGE_VAL | |
319 | angular_distortion_buff.data[iii] = HUGE_VAL | |
320 | meridian_parallel_angle_buff.data[iii] = HUGE_VAL | |
321 | meridian_convergence_buff.data[iii] = HUGE_VAL | |
322 | tissot_semimajor_buff.data[iii] = HUGE_VAL | |
323 | tissot_semiminor_buff.data[iii] = HUGE_VAL | |
324 | dx_dlam_buff.data[iii] = HUGE_VAL | |
325 | dx_dphi_buff.data[iii] = HUGE_VAL | |
326 | dy_dlam_buff.data[iii] = HUGE_VAL | |
327 | dy_dphi_buff.data[iii] = HUGE_VAL | |
328 | else: | |
329 | meridional_scale_buff.data[iii] = pj_factors.meridional_scale | |
330 | parallel_scale_buff.data[iii] = pj_factors.parallel_scale | |
331 | areal_scale_buff.data[iii] = pj_factors.areal_scale | |
332 | angular_distortion_buff.data[iii] = pj_factors.angular_distortion * _RAD2DG | |
333 | meridian_parallel_angle_buff.data[iii] = pj_factors.meridian_parallel_angle * _RAD2DG | |
334 | meridian_convergence_buff.data[iii] = pj_factors.meridian_convergence * _RAD2DG | |
335 | tissot_semimajor_buff.data[iii] = pj_factors.tissot_semimajor | |
336 | tissot_semiminor_buff.data[iii] = pj_factors.tissot_semiminor | |
337 | dx_dlam_buff.data[iii] = pj_factors.dx_dlam | |
338 | dx_dphi_buff.data[iii] = pj_factors.dx_dphi | |
339 | dy_dlam_buff.data[iii] = pj_factors.dy_dlam | |
340 | dy_dphi_buff.data[iii] = pj_factors.dy_dphi | |
341 | ||
342 | ProjError.clear() | |
343 | ||
344 | return Factors( | |
345 | meridional_scale=meridional_scale, | |
346 | parallel_scale=parallel_scale, | |
347 | areal_scale=areal_scale, | |
348 | angular_distortion=angular_distortion, | |
349 | meridian_parallel_angle=meridian_parallel_angle, | |
350 | meridian_convergence=meridian_convergence, | |
351 | tissot_semimajor=tissot_semimajor, | |
352 | tissot_semiminor=tissot_semiminor, | |
353 | dx_dlam=dx_dlam, | |
354 | dx_dphi=dx_dphi, | |
355 | dy_dlam=dy_dlam, | |
356 | dy_dphi=dy_dphi, | |
357 | ) | |
358 | ||
189 | 359 | def __repr__(self): |
190 | 360 | return "Proj('{srs}', preserve_units=True)".format(srs=self.srs) |
191 | 361 | |
192 | def _is_exact_same(self, Proj other): | |
362 | def _is_exact_same(self, _Proj other): | |
193 | 363 | return proj_is_equivalent_to( |
194 | 364 | self.projobj, other.projobj, PJ_COMP_STRICT) == 1 |
195 | 365 | |
196 | def _is_equivalent(self, Proj other): | |
366 | def _is_equivalent(self, _Proj other): | |
197 | 367 | return proj_is_equivalent_to( |
198 | 368 | self.projobj, other.projobj, PJ_COMP_EQUIVALENT) == 1 |
199 | 369 | |
200 | 370 | def is_exact_same(self, other): |
201 | 371 | """Compares Proj objects to see if they are exactly the same.""" |
202 | if not isinstance(other, Proj): | |
372 | if not isinstance(other, _Proj): | |
203 | 373 | return False |
204 | 374 | return self._is_exact_same(other) |
18 | 18 | cdef readonly skip_equivalent |
19 | 19 | cdef readonly projections_equivalent |
20 | 20 | cdef readonly projections_exact_same |
21 | cdef readonly type_name | |
21 | cdef readonly type_name | |
22 | 22 | cdef readonly object _operations |
23 | 23 | |
24 | 24 | @staticmethod |
29 | 29 | _CRS crs_to, |
30 | 30 | skip_equivalent, |
31 | 31 | always_xy, |
32 | )⏎ | |
32 | ) |
0 | from typing import Any, Iterable, List, NamedTuple, Optional, Tuple, Union | |
1 | ||
2 | from pyproj._crs import _CRS, AreaOfUse, Base, CoordinateOperation | |
3 | from pyproj.enums import TransformDirection | |
4 | ||
5 | class AreaOfInterest(NamedTuple): | |
6 | west_lon_degree: float | |
7 | south_lat_degree: float | |
8 | east_lon_degree: float | |
9 | north_lat_degree: float | |
10 | ||
11 | class _TransformerGroup: | |
12 | _transformers: Any | |
13 | _unavailable_operations: List[CoordinateOperation] | |
14 | _best_available: bool | |
15 | def __init__( | |
16 | self, | |
17 | crs_from: _CRS, | |
18 | crs_to: _CRS, | |
19 | skip_equivalent: bool = False, | |
20 | always_xy: bool = False, | |
21 | area_of_interest: Optional[AreaOfInterest] = None, | |
22 | ) -> None: ... | |
23 | ||
24 | class _Transformer(Base): | |
25 | input_geographic: bool | |
26 | output_geographic: bool | |
27 | is_pipeline: bool | |
28 | skip_equivalent: bool | |
29 | projections_equivalent: bool | |
30 | projections_exact_same: bool | |
31 | type_name: str | |
32 | @property | |
33 | def id(self) -> str: ... | |
34 | @property | |
35 | def description(self) -> str: ... | |
36 | @property | |
37 | def definition(self) -> str: ... | |
38 | @property | |
39 | def has_inverse(self) -> bool: ... | |
40 | @property | |
41 | def accuracy(self) -> float: ... | |
42 | @property | |
43 | def area_of_use(self) -> AreaOfUse: ... | |
44 | @property | |
45 | def operations(self) -> Union[Tuple[CoordinateOperation], None]: ... | |
46 | @staticmethod | |
47 | def from_crs( | |
48 | crs_from: _CRS, | |
49 | crs_to: _CRS, | |
50 | skip_equivalent: bool = False, | |
51 | always_xy: bool = False, | |
52 | area_of_interest: Optional[AreaOfInterest] = None, | |
53 | ) -> "_Transformer": ... | |
54 | @staticmethod | |
55 | def from_pipeline(proj_pipeline: str) -> "_Transformer": ... | |
56 | def _transform( | |
57 | self, | |
58 | inx: Any, | |
59 | iny: Any, | |
60 | inz: Any, | |
61 | intime: Any, | |
62 | direction: Union[TransformDirection, str], | |
63 | radians: bool, | |
64 | errcheck: bool, | |
65 | ) -> None: ... | |
66 | def _transform_sequence( | |
67 | self, | |
68 | stride: int, | |
69 | inseq: Iterable[Iterable[float]], | |
70 | switch: bool, | |
71 | direction: Union[TransformDirection, str], | |
72 | time_3rd: bool, | |
73 | radians: bool, | |
74 | errcheck: bool, | |
75 | ) -> None: ... |
171 | 171 | if pj_operations != NULL: |
172 | 172 | proj_list_destroy(pj_operations) |
173 | 173 | ProjError.clear() |
174 | ||
174 | ||
175 | 175 | |
176 | 176 | cdef _CRS get_transform_crs(_CRS in_crs): |
177 | 177 | for sub_crs in in_crs.sub_crs_list: |
237 | 237 | @property |
238 | 238 | def accuracy(self): |
239 | 239 | return self.proj_info.accuracy |
240 | ||
240 | ||
241 | 241 | @property |
242 | 242 | def area_of_use(self): |
243 | 243 | """ |
244 | 244 | Returns |
245 | 245 | ------- |
246 | AreaOfUse: The area of use object with associated attributes. | |
246 | AreaOfUse: | |
247 | The area of use object with associated attributes. | |
247 | 248 | """ |
248 | 249 | if self._area_of_use is not None: |
249 | 250 | return self._area_of_use |
255 | 256 | """ |
256 | 257 | .. versionadded:: 2.4.0 |
257 | 258 | |
258 | tuple[CoordinateOperation]: The operations in a concatenated operation. | |
259 | Tuple[CoordinateOperation]: | |
260 | The operations in a concatenated operation. | |
259 | 261 | """ |
260 | 262 | if self._operations is not None: |
261 | 263 | return self._operations |
398 | 400 | |
399 | 401 | @cython.boundscheck(False) |
400 | 402 | @cython.wraparound(False) |
401 | def _transform(self, inx, iny, inz, intime, direction, radians, errcheck): | |
403 | def _transform( | |
404 | self, | |
405 | object inx, | |
406 | object iny, | |
407 | object inz, | |
408 | object intime, | |
409 | object direction, | |
410 | bint radians, | |
411 | bint errcheck, | |
412 | ): | |
402 | 413 | if self.projections_exact_same or (self.projections_equivalent and self.skip_equivalent): |
403 | 414 | return |
415 | if radians and self.is_pipeline: | |
416 | warnings.warn( | |
417 | "radian input with pipelines is not supported and may result " | |
418 | "in unexpected transformations." | |
419 | ) | |
420 | ||
404 | 421 | tmp_pj_direction = _PJ_DIRECTION_MAP[TransformDirection.create(direction)] |
405 | 422 | cdef PJ_DIRECTION pj_direction = <PJ_DIRECTION>tmp_pj_direction |
406 | 423 | cdef PyBuffWriteManager xbuff = PyBuffWriteManager(inx) |
433 | 450 | |
434 | 451 | cdef Py_ssize_t iii |
435 | 452 | # degrees to radians |
436 | if not self.is_pipeline and not radians\ | |
437 | and self._input_radians[pj_direction]: | |
453 | if not radians and self._input_radians[pj_direction]: | |
438 | 454 | with nogil: |
439 | 455 | for iii in range(xbuff.len): |
440 | 456 | xbuff.data[iii] = xbuff.data[iii]*_DG2RAD |
441 | 457 | ybuff.data[iii] = ybuff.data[iii]*_DG2RAD |
442 | 458 | # radians to degrees |
443 | elif not self.is_pipeline and radians\ | |
444 | and not self._input_radians[pj_direction]\ | |
445 | and self.input_geographic: | |
459 | elif self.input_geographic and radians\ | |
460 | and not self._input_radians[pj_direction]: | |
446 | 461 | with nogil: |
447 | 462 | for iii in range(xbuff.len): |
448 | 463 | xbuff.data[iii] = xbuff.data[iii]*_RAD2DG |
465 | 480 | raise ProjError("transform error") |
466 | 481 | |
467 | 482 | # radians to degrees |
468 | if not self.is_pipeline and not radians\ | |
469 | and self._output_radians[pj_direction]: | |
483 | if not radians and self._output_radians[pj_direction]: | |
470 | 484 | with nogil: |
471 | 485 | for iii in range(xbuff.len): |
472 | 486 | xbuff.data[iii] = xbuff.data[iii]*_RAD2DG |
473 | 487 | ybuff.data[iii] = ybuff.data[iii]*_RAD2DG |
474 | 488 | # degrees to radians |
475 | elif not self.is_pipeline and radians\ | |
476 | and not self._output_radians[pj_direction]\ | |
477 | and self.output_geographic: | |
489 | elif self.output_geographic and radians\ | |
490 | and not self._output_radians[pj_direction]: | |
478 | 491 | with nogil: |
479 | 492 | for iii in range(xbuff.len): |
480 | 493 | xbuff.data[iii] = xbuff.data[iii]*_DG2RAD |
484 | 497 | @cython.boundscheck(False) |
485 | 498 | @cython.wraparound(False) |
486 | 499 | def _transform_sequence( |
487 | self, Py_ssize_t stride, object inseq, bint switch, | |
488 | direction, time_3rd, radians, errcheck | |
500 | self, | |
501 | Py_ssize_t stride, | |
502 | object inseq, | |
503 | bint switch, | |
504 | object direction, | |
505 | bint time_3rd, | |
506 | bint radians, | |
507 | bint errcheck, | |
489 | 508 | ): |
490 | 509 | if self.projections_exact_same or (self.projections_equivalent and self.skip_equivalent): |
491 | 510 | return |
499 | 518 | |
500 | 519 | if stride < 2: |
501 | 520 | raise ProjError("coordinates must contain at least 2 values") |
502 | ||
521 | ||
503 | 522 | cdef PyBuffWriteManager coordbuff = PyBuffWriteManager(inseq) |
504 | 523 | cdef Py_ssize_t npts, iii, jjj |
505 | 524 | npts = coordbuff.len // stride |
506 | 525 | # degrees to radians |
507 | if not self.is_pipeline and not radians\ | |
508 | and self._input_radians[pj_direction]: | |
526 | if not radians and self._input_radians[pj_direction]: | |
509 | 527 | with nogil: |
510 | 528 | for iii in range(npts): |
511 | 529 | jjj = stride * iii |
512 | 530 | coordbuff.data[jjj] *= _DG2RAD |
513 | 531 | coordbuff.data[jjj + 1] *= _DG2RAD |
514 | 532 | # radians to degrees |
515 | elif not self.is_pipeline and radians\ | |
516 | and not self._input_radians[pj_direction]\ | |
517 | and self.input_geographic: | |
533 | elif self.input_geographic and radians\ | |
534 | and not self._input_radians[pj_direction]: | |
518 | 535 | with nogil: |
519 | 536 | for iii in range(npts): |
520 | 537 | jjj = stride * iii |
560 | 577 | |
561 | 578 | |
562 | 579 | # radians to degrees |
563 | if not self.is_pipeline and not radians\ | |
564 | and self._output_radians[pj_direction]: | |
580 | if not radians and self._output_radians[pj_direction]: | |
565 | 581 | with nogil: |
566 | 582 | for iii in range(npts): |
567 | 583 | jjj = stride * iii |
568 | 584 | coordbuff.data[jjj] *= _RAD2DG |
569 | 585 | coordbuff.data[jjj + 1] *= _RAD2DG |
570 | 586 | # degrees to radians |
571 | elif not self.is_pipeline and radians\ | |
572 | and not self._output_radians[pj_direction]\ | |
573 | and self.output_geographic: | |
587 | elif self.output_geographic and radians\ | |
588 | and not self._output_radians[pj_direction]: | |
574 | 589 | with nogil: |
575 | 590 | for iii in range(npts): |
576 | 591 | jjj = stride * iii |
30 | 30 | |
31 | 31 | def __dealloc__(self): |
32 | 32 | PyBuffer_Release(&self.buffer) |
33 | self.data = NULL | |
33 | self.data = NULL |
0 | 0 | import warnings |
1 | 1 | from distutils.version import LooseVersion |
2 | from typing import Any | |
2 | 3 | |
3 | 4 | from pyproj._crs import CoordinateOperation |
4 | 5 | from pyproj._proj import proj_version_str |
16 | 17 | |
17 | 18 | def __new__( |
18 | 19 | cls, |
19 | latitude_first_parallel, | |
20 | latitude_second_parallel, | |
21 | latitude_false_origin=0.0, | |
22 | longitude_false_origin=0.0, | |
23 | easting_false_origin=0.0, | |
24 | northing_false_origin=0.0, | |
20 | latitude_first_parallel: float, | |
21 | latitude_second_parallel: float, | |
22 | latitude_false_origin: float = 0.0, | |
23 | longitude_false_origin: float = 0.0, | |
24 | easting_false_origin: float = 0.0, | |
25 | northing_false_origin: float = 0.0, | |
25 | 26 | ): |
26 | 27 | """ |
27 | 28 | Parameters |
108 | 109 | |
109 | 110 | def __new__( |
110 | 111 | cls, |
111 | latitude_natural_origin=0.0, | |
112 | longitude_natural_origin=0.0, | |
113 | false_easting=0.0, | |
114 | false_northing=0.0, | |
112 | latitude_natural_origin: float = 0.0, | |
113 | longitude_natural_origin: float = 0.0, | |
114 | false_easting: float = 0.0, | |
115 | false_northing: float = 0.0, | |
115 | 116 | ): |
116 | 117 | """ |
117 | 118 | Parameters |
175 | 176 | |
176 | 177 | def __new__( |
177 | 178 | cls, |
178 | sweep_angle_axis, | |
179 | satellite_height, | |
180 | latitude_natural_origin=0.0, | |
181 | longitude_natural_origin=0.0, | |
182 | false_easting=0.0, | |
183 | false_northing=0.0, | |
179 | sweep_angle_axis: str, | |
180 | satellite_height: float, | |
181 | latitude_natural_origin: float = 0.0, | |
182 | longitude_natural_origin: float = 0.0, | |
183 | false_easting: float = 0.0, | |
184 | false_northing: float = 0.0, | |
184 | 185 | ): |
185 | 186 | """ |
186 | 187 | Parameters |
264 | 265 | |
265 | 266 | def __new__( |
266 | 267 | cls, |
267 | latitude_natural_origin=0.0, | |
268 | longitude_natural_origin=0.0, | |
269 | false_easting=0.0, | |
270 | false_northing=0.0, | |
268 | latitude_natural_origin: float = 0.0, | |
269 | longitude_natural_origin: float = 0.0, | |
270 | false_easting: float = 0.0, | |
271 | false_northing: float = 0.0, | |
271 | 272 | ): |
272 | 273 | """ |
273 | 274 | Parameters |
331 | 332 | |
332 | 333 | def __new__( |
333 | 334 | cls, |
334 | latitude_first_parallel, | |
335 | latitude_second_parallel, | |
336 | latitude_false_origin=0.0, | |
337 | longitude_false_origin=0.0, | |
338 | easting_false_origin=0.0, | |
339 | northing_false_origin=0.0, | |
335 | latitude_first_parallel: float, | |
336 | latitude_second_parallel: float, | |
337 | latitude_false_origin: float = 0.0, | |
338 | longitude_false_origin: float = 0.0, | |
339 | easting_false_origin: float = 0.0, | |
340 | northing_false_origin: float = 0.0, | |
340 | 341 | ): |
341 | 342 | """ |
342 | 343 | Parameters |
416 | 417 | |
417 | 418 | def __new__( |
418 | 419 | cls, |
419 | latitude_natural_origin=0.0, | |
420 | longitude_natural_origin=0.0, | |
421 | false_easting=0.0, | |
422 | false_northing=0.0, | |
423 | scale_factor_natural_origin=1.0, | |
420 | latitude_natural_origin: float = 0.0, | |
421 | longitude_natural_origin: float = 0.0, | |
422 | false_easting: float = 0.0, | |
423 | false_northing: float = 0.0, | |
424 | scale_factor_natural_origin: float = 1.0, | |
424 | 425 | ): |
425 | 426 | """ |
426 | 427 | Parameters |
492 | 493 | |
493 | 494 | def __new__( |
494 | 495 | cls, |
495 | latitude_first_parallel=0.0, | |
496 | longitude_natural_origin=0.0, | |
497 | false_easting=0.0, | |
498 | false_northing=0.0, | |
496 | latitude_first_parallel: float = 0.0, | |
497 | longitude_natural_origin: float = 0.0, | |
498 | false_easting: float = 0.0, | |
499 | false_northing: float = 0.0, | |
499 | 500 | ): |
500 | 501 | """ |
501 | 502 | Parameters |
565 | 566 | |
566 | 567 | def __new__( |
567 | 568 | cls, |
568 | longitude_natural_origin=0.0, | |
569 | false_easting=0.0, | |
570 | false_northing=0.0, | |
571 | scale_factor_natural_origin=1.0, | |
569 | longitude_natural_origin: float = 0.0, | |
570 | false_easting: float = 0.0, | |
571 | false_northing: float = 0.0, | |
572 | scale_factor_natural_origin: float = 1.0, | |
572 | 573 | ): |
573 | 574 | """ |
574 | 575 | Parameters |
600 | 601 | ) |
601 | 602 | ) |
602 | 603 | if LooseVersion(proj_version_str) >= LooseVersion("6.3.1"): |
603 | return cls.from_json(CRS(proj_string).coordinate_operation.to_json()) | |
604 | return cls.from_json( | |
605 | CRS(proj_string).coordinate_operation.to_json() # type: ignore | |
606 | ) | |
604 | 607 | return cls.from_string(proj_string) |
605 | 608 | |
606 | 609 | |
615 | 618 | |
616 | 619 | def __new__( |
617 | 620 | cls, |
618 | latitude_natural_origin=0.0, | |
619 | longitude_natural_origin=0.0, | |
620 | false_easting=0.0, | |
621 | false_northing=0.0, | |
622 | scale_factor_natural_origin=1.0, | |
621 | latitude_natural_origin: float = 0.0, | |
622 | longitude_natural_origin: float = 0.0, | |
623 | false_easting: float = 0.0, | |
624 | false_northing: float = 0.0, | |
625 | scale_factor_natural_origin: float = 1.0, | |
623 | 626 | ): |
624 | 627 | """ |
625 | 628 | Parameters |
691 | 694 | |
692 | 695 | def __new__( |
693 | 696 | cls, |
694 | latitude_first_parallel=0.0, | |
695 | longitude_natural_origin=0.0, | |
696 | false_easting=0.0, | |
697 | false_northing=0.0, | |
697 | latitude_first_parallel: float = 0.0, | |
698 | longitude_natural_origin: float = 0.0, | |
699 | false_easting: float = 0.0, | |
700 | false_northing: float = 0.0, | |
698 | 701 | ): |
699 | 702 | """ |
700 | 703 | Parameters |
758 | 761 | |
759 | 762 | def __new__( |
760 | 763 | cls, |
761 | latitude_projection_centre, | |
762 | longitude_projection_centre, | |
763 | azimuth_initial_line, | |
764 | angle_from_rectified_to_skew_grid, | |
765 | scale_factor_on_initial_line=1.0, | |
766 | easting_projection_centre=0.0, | |
767 | northing_projection_centre=0.0, | |
764 | latitude_projection_centre: float, | |
765 | longitude_projection_centre: float, | |
766 | azimuth_initial_line: float, | |
767 | angle_from_rectified_to_skew_grid: float, | |
768 | scale_factor_on_initial_line: float = 1.0, | |
769 | easting_projection_centre: float = 0.0, | |
770 | northing_projection_centre: float = 0.0, | |
768 | 771 | ): |
769 | 772 | """ |
770 | 773 | Parameters |
851 | 854 | |
852 | 855 | def __new__( |
853 | 856 | cls, |
854 | latitude_natural_origin=0.0, | |
855 | longitude_natural_origin=0.0, | |
856 | false_easting=0.0, | |
857 | false_northing=0.0, | |
857 | latitude_natural_origin: float = 0.0, | |
858 | longitude_natural_origin: float = 0.0, | |
859 | false_easting: float = 0.0, | |
860 | false_northing: float = 0.0, | |
858 | 861 | ): |
859 | 862 | """ |
860 | 863 | Parameters |
918 | 921 | |
919 | 922 | def __new__( |
920 | 923 | cls, |
921 | latitude_natural_origin, | |
922 | longitude_natural_origin=0.0, | |
923 | false_easting=0.0, | |
924 | false_northing=0.0, | |
925 | scale_factor_natural_origin=1.0, | |
924 | latitude_natural_origin: float, | |
925 | longitude_natural_origin: float = 0.0, | |
926 | false_easting: float = 0.0, | |
927 | false_northing: float = 0.0, | |
928 | scale_factor_natural_origin: float = 1.0, | |
926 | 929 | ): |
927 | 930 | """ |
928 | 931 | Parameters |
995 | 998 | |
996 | 999 | def __new__( |
997 | 1000 | cls, |
998 | latitude_standard_parallel=0.0, | |
999 | longitude_origin=0.0, | |
1000 | false_easting=0.0, | |
1001 | false_northing=0.0, | |
1001 | latitude_standard_parallel: float = 0.0, | |
1002 | longitude_origin: float = 0.0, | |
1003 | false_easting: float = 0.0, | |
1004 | false_northing: float = 0.0, | |
1002 | 1005 | ): |
1003 | 1006 | """ |
1004 | 1007 | Parameters |
1061 | 1064 | """ |
1062 | 1065 | |
1063 | 1066 | def __new__( |
1064 | cls, longitude_natural_origin=0.0, false_easting=0.0, false_northing=0.0 | |
1067 | cls, | |
1068 | longitude_natural_origin: float = 0.0, | |
1069 | false_easting: float = 0.0, | |
1070 | false_northing: float = 0.0, | |
1065 | 1071 | ): |
1066 | 1072 | """ |
1067 | 1073 | Parameters |
1114 | 1120 | |
1115 | 1121 | def __new__( |
1116 | 1122 | cls, |
1117 | latitude_natural_origin=0.0, | |
1118 | longitude_natural_origin=0.0, | |
1119 | false_easting=0.0, | |
1120 | false_northing=0.0, | |
1121 | scale_factor_natural_origin=1.0, | |
1123 | latitude_natural_origin: float = 0.0, | |
1124 | longitude_natural_origin: float = 0.0, | |
1125 | false_easting: float = 0.0, | |
1126 | false_northing: float = 0.0, | |
1127 | scale_factor_natural_origin: float = 1.0, | |
1122 | 1128 | ): |
1123 | 1129 | """ |
1124 | 1130 | Parameters |
1186 | 1192 | https://proj.org/operations/projections/utm.html |
1187 | 1193 | """ |
1188 | 1194 | |
1189 | def __new__(cls, zone, hemisphere="N"): | |
1195 | def __new__(cls, zone: str, hemisphere: str = "N"): | |
1190 | 1196 | """ |
1191 | 1197 | Parameters |
1192 | 1198 | ---------- |
1211 | 1217 | |
1212 | 1218 | def __new__( |
1213 | 1219 | cls, |
1214 | latitude_natural_origin=0.0, | |
1215 | longitude_natural_origin=0.0, | |
1216 | false_easting=0.0, | |
1217 | false_northing=0.0, | |
1218 | scale_factor_natural_origin=1.0, | |
1220 | latitude_natural_origin: float = 0.0, | |
1221 | longitude_natural_origin: float = 0.0, | |
1222 | false_easting: float = 0.0, | |
1223 | false_northing: float = 0.0, | |
1224 | scale_factor_natural_origin: float = 1.0, | |
1219 | 1225 | ): |
1220 | 1226 | """ |
1221 | 1227 | Parameters |
1287 | 1293 | |
1288 | 1294 | def __new__( |
1289 | 1295 | cls, |
1290 | viewpoint_height, | |
1291 | latitude_topocentric_origin=0.0, | |
1292 | longitude_topocentric_origin=0.0, | |
1293 | ellipsoidal_height_topocentric_origin=0.0, | |
1294 | false_easting=0.0, | |
1295 | false_northing=0.0, | |
1296 | viewpoint_height: float, | |
1297 | latitude_topocentric_origin: float = 0.0, | |
1298 | longitude_topocentric_origin: float = 0.0, | |
1299 | ellipsoidal_height_topocentric_origin: float = 0.0, | |
1300 | false_easting: float = 0.0, | |
1301 | false_northing: float = 0.0, | |
1296 | 1302 | ): |
1297 | 1303 | """ |
1298 | 1304 | Parameters |
1370 | 1376 | https://proj.org/operations/projections/ob_tran.html |
1371 | 1377 | """ |
1372 | 1378 | |
1373 | def __new__(cls, o_lat_p, o_lon_p, lon_0=0.0): | |
1379 | def __new__(cls, o_lat_p: float, o_lon_p: float, lon_0: float = 0.0): | |
1374 | 1380 | """ |
1375 | 1381 | Parameters |
1376 | 1382 | ---------- |
1377 | 1383 | o_lat_p: float |
1378 | 1384 | Latitude of the North pole of the unrotated source CRS, |
1379 | 1385 | expressed in the rotated geographic CRS. |
1380 | o_lon_p: | |
1386 | o_lon_p: float | |
1381 | 1387 | Longitude of the North pole of the unrotated source CRS, |
1382 | 1388 | expressed in the rotated geographic CRS. |
1383 | 1389 | lon_0: float, optional |
1409 | 1415 | |
1410 | 1416 | def __new__( |
1411 | 1417 | cls, |
1412 | latitude_first_parallel=0.0, | |
1413 | latitude_natural_origin=0.0, | |
1414 | longitude_natural_origin=0.0, | |
1415 | false_easting=0.0, | |
1416 | false_northing=0.0, | |
1418 | latitude_first_parallel: float = 0.0, | |
1419 | latitude_natural_origin: float = 0.0, | |
1420 | longitude_natural_origin: float = 0.0, | |
1421 | false_easting: float = 0.0, | |
1422 | false_northing: float = 0.0, | |
1417 | 1423 | ): |
1418 | 1424 | """ |
1419 | 1425 | Parameters |
1486 | 1492 | |
1487 | 1493 | def __new__( |
1488 | 1494 | cls, |
1489 | source_crs, | |
1490 | x_axis_translation=0, | |
1491 | y_axis_translation=0, | |
1492 | z_axis_translation=0, | |
1493 | x_axis_rotation=0, | |
1494 | y_axis_rotation=0, | |
1495 | z_axis_rotation=0, | |
1496 | scale_difference=0, | |
1497 | ): | |
1498 | """ | |
1499 | Parameters | |
1500 | ---------- | |
1495 | source_crs: Any, | |
1496 | x_axis_translation: float = 0, | |
1497 | y_axis_translation: float = 0, | |
1498 | z_axis_translation: float = 0, | |
1499 | x_axis_rotation: float = 0, | |
1500 | y_axis_rotation: float = 0, | |
1501 | z_axis_rotation: float = 0, | |
1502 | scale_difference: float = 0, | |
1503 | ): | |
1504 | """ | |
1505 | Parameters | |
1506 | ---------- | |
1507 | source_crs: Any | |
1508 | Input to create the Source CRS. | |
1501 | 1509 | x_axis_translation: float, optional |
1502 | 1510 | X-axis translation. Defaults to 0.0. |
1503 | 1511 | y_axis_translation: float, optional |
0 | from typing import Union | |
1 | ||
0 | 2 | from pyproj._crs import CoordinateSystem |
1 | 3 | from pyproj.crs.enums import ( |
2 | 4 | Cartesian2DCSAxis, |
54 | 56 | This generates an Ellipsoidal 2D Coordinate System |
55 | 57 | """ |
56 | 58 | |
57 | def __new__(cls, axis=Ellipsoidal2DCSAxis.LONGITUDE_LATITUDE): | |
59 | def __new__( | |
60 | cls, | |
61 | axis: Union[Ellipsoidal2DCSAxis, str] = Ellipsoidal2DCSAxis.LONGITUDE_LATITUDE, | |
62 | ): | |
58 | 63 | """ |
59 | 64 | Parameters |
60 | 65 | ---------- |
121 | 126 | This generates an Ellipsoidal 3D Coordinate System |
122 | 127 | """ |
123 | 128 | |
124 | def __new__(cls, axis=Ellipsoidal3DCSAxis.LONGITUDE_LATITUDE_HEIGHT): | |
129 | def __new__( | |
130 | cls, | |
131 | axis: Union[ | |
132 | Ellipsoidal3DCSAxis, str | |
133 | ] = Ellipsoidal3DCSAxis.LONGITUDE_LATITUDE_HEIGHT, | |
134 | ): | |
125 | 135 | """ |
126 | 136 | Parameters |
127 | 137 | ---------- |
264 | 274 | This generates an Cartesian 2D Coordinate System |
265 | 275 | """ |
266 | 276 | |
267 | def __new__(cls, axis=Cartesian2DCSAxis.EASTING_NORTHING): | |
277 | def __new__( | |
278 | cls, axis: Union[Cartesian2DCSAxis, str] = Cartesian2DCSAxis.EASTING_NORTHING | |
279 | ): | |
268 | 280 | """ |
269 | 281 | Parameters |
270 | 282 | ---------- |
345 | 357 | This generates an Vertical Coordinate System |
346 | 358 | """ |
347 | 359 | |
348 | def __new__(cls, axis=VerticalCSAxis.GRAVITY_HEIGHT): | |
360 | def __new__(cls, axis: Union[VerticalCSAxis, str] = VerticalCSAxis.GRAVITY_HEIGHT): | |
349 | 361 | """ |
350 | 362 | Parameters |
351 | 363 | ---------- |
3 | 3 | to the coordinate reference system (CRS) information. |
4 | 4 | |
5 | 5 | Original Author: Alan D. Snow [github.com/snowman2] (2019) |
6 | ||
6 | 7 | """ |
7 | 8 | import json |
8 | 9 | import re |
9 | 10 | import warnings |
11 | from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union | |
10 | 12 | |
11 | 13 | from pyproj._crs import ( # noqa |
12 | 14 | _CRS, |
34 | 36 | from pyproj.geod import Geod |
35 | 37 | |
36 | 38 | |
37 | def _prepare_from_dict(projparams): | |
39 | def _prepare_from_dict(projparams: dict, allow_json: bool = True) -> str: | |
38 | 40 | # check if it is a PROJ JSON dict |
39 | if "proj" not in projparams and "init" not in projparams: | |
41 | if "proj" not in projparams and "init" not in projparams and allow_json: | |
40 | 42 | return json.dumps(projparams) |
41 | 43 | # convert a dict to a proj string. |
42 | 44 | pjargs = [] |
47 | 49 | # issue 183 (+ no_rot) |
48 | 50 | if value is None or value is True: |
49 | 51 | pjargs.append("+{key}".format(key=key)) |
50 | elif value is False: | |
52 | elif str(value) == str(False): | |
51 | 53 | pass |
52 | 54 | else: |
53 | 55 | pjargs.append("+{key}={value}".format(key=key, value=value)) |
54 | 56 | return _prepare_from_string(" ".join(pjargs)) |
55 | 57 | |
56 | 58 | |
57 | def _prepare_from_string(in_crs_string): | |
59 | def _prepare_from_string(in_crs_string: str) -> str: | |
58 | 60 | if not in_crs_string: |
59 | 61 | raise CRSError("CRS is empty or invalid: {!r}".format(in_crs_string)) |
60 | 62 | elif "{" in in_crs_string: |
72 | 74 | # make sure the projection starts with +proj or +init |
73 | 75 | starting_params = ("+init", "+proj", "init", "proj") |
74 | 76 | if not in_crs_string.startswith(starting_params): |
75 | kvpairs = [] | |
77 | kvpairs = [] # type: List[str] | |
76 | 78 | first_item_inserted = False |
77 | 79 | for kvpair in in_crs_string.split(): |
78 | 80 | if not first_item_inserted and (kvpair.startswith(starting_params)): |
105 | 107 | return in_crs_string |
106 | 108 | |
107 | 109 | |
108 | def _prepare_from_authority(auth_name, auth_code): | |
110 | def _prepare_from_authority(auth_name: str, auth_code: Union[str, int]): | |
109 | 111 | return "{}:{}".format(auth_name, auth_code) |
110 | 112 | |
111 | 113 | |
112 | def _prepare_from_epsg(auth_code): | |
114 | def _prepare_from_epsg(auth_code: Union[str, int]): | |
113 | 115 | return _prepare_from_authority("epsg", auth_code) |
114 | 116 | |
115 | 117 | |
136 | 138 | |
137 | 139 | """ |
138 | 140 | |
139 | def __init__(self, projparams=None, **kwargs): | |
141 | def __init__(self, projparams: Any = None, **kwargs) -> None: | |
140 | 142 | """ |
141 | 143 | Initialize a CRS class instance with: |
142 | 144 | - PROJ string |
274 | 276 | >>> crs.is_geographic |
275 | 277 | False |
276 | 278 | """ |
277 | if isinstance(projparams, str): | |
278 | projstring = _prepare_from_string(projparams) | |
279 | elif isinstance(projparams, dict): | |
280 | projstring = _prepare_from_dict(projparams) | |
281 | elif kwargs: | |
282 | projstring = _prepare_from_dict(kwargs) | |
283 | elif isinstance(projparams, int): | |
284 | projstring = _prepare_from_epsg(projparams) | |
285 | elif isinstance(projparams, (list, tuple)) and len(projparams) == 2: | |
286 | projstring = _prepare_from_authority(*projparams) | |
287 | elif hasattr(projparams, "to_wkt"): | |
288 | projstring = projparams.to_wkt() | |
289 | else: | |
290 | raise CRSError("Invalid CRS input: {!r}".format(projparams)) | |
279 | projstring = "" | |
280 | ||
281 | if projparams: | |
282 | if isinstance(projparams, str): | |
283 | projstring = _prepare_from_string(projparams) | |
284 | elif isinstance(projparams, dict): | |
285 | projstring = _prepare_from_dict(projparams) | |
286 | elif isinstance(projparams, int): | |
287 | projstring = _prepare_from_epsg(projparams) | |
288 | elif isinstance(projparams, (list, tuple)) and len(projparams) == 2: | |
289 | projstring = _prepare_from_authority(*projparams) | |
290 | elif hasattr(projparams, "to_wkt"): | |
291 | projstring = projparams.to_wkt() # type: ignore | |
292 | else: | |
293 | raise CRSError("Invalid CRS input: {!r}".format(projparams)) | |
294 | ||
295 | if kwargs: | |
296 | projkwargs = _prepare_from_dict(kwargs, allow_json=False) | |
297 | projstring = _prepare_from_string(" ".join((projstring, projkwargs))) | |
291 | 298 | |
292 | 299 | super().__init__(projstring) |
293 | 300 | |
294 | 301 | @staticmethod |
295 | def from_authority(auth_name, code): | |
302 | def from_authority(auth_name: str, code: Union[str, int]) -> "CRS": | |
296 | 303 | """ |
297 | 304 | .. versionadded:: 2.2.0 |
298 | 305 | |
312 | 319 | return CRS(_prepare_from_authority(auth_name, code)) |
313 | 320 | |
314 | 321 | @staticmethod |
315 | def from_epsg(code): | |
322 | def from_epsg(code: Union[str, int]) -> "CRS": | |
316 | 323 | """Make a CRS from an EPSG code |
317 | 324 | |
318 | 325 | Parameters |
327 | 334 | return CRS(_prepare_from_epsg(code)) |
328 | 335 | |
329 | 336 | @staticmethod |
330 | def from_proj4(in_proj_string): | |
337 | def from_proj4(in_proj_string: str) -> "CRS": | |
331 | 338 | """ |
332 | 339 | .. versionadded:: 2.2.0 |
333 | 340 | |
347 | 354 | return CRS(_prepare_from_string(in_proj_string)) |
348 | 355 | |
349 | 356 | @staticmethod |
350 | def from_wkt(in_wkt_string): | |
357 | def from_wkt(in_wkt_string: str) -> "CRS": | |
351 | 358 | """ |
352 | 359 | .. versionadded:: 2.2.0 |
353 | 360 | |
367 | 374 | return CRS(_prepare_from_string(in_wkt_string)) |
368 | 375 | |
369 | 376 | @staticmethod |
370 | def from_string(in_crs_string): | |
377 | def from_string(in_crs_string: str) -> "CRS": | |
371 | 378 | """ |
372 | 379 | Make a CRS from: |
373 | 380 | |
388 | 395 | """ |
389 | 396 | return CRS(_prepare_from_string(in_crs_string)) |
390 | 397 | |
391 | def to_string(self): | |
398 | def to_string(self) -> str: | |
392 | 399 | """ |
393 | 400 | .. versionadded:: 2.2.0 |
394 | 401 | |
400 | 407 | |
401 | 408 | Returns |
402 | 409 | ------- |
403 | str: String representation of the CRS. | |
410 | str | |
404 | 411 | """ |
405 | 412 | auth_info = self.to_authority(min_confidence=100) |
406 | 413 | if auth_info: |
408 | 415 | return self.srs |
409 | 416 | |
410 | 417 | @staticmethod |
411 | def from_user_input(value): | |
418 | def from_user_input(value: Any, **kwargs) -> "CRS": | |
412 | 419 | """ |
413 | 420 | Initialize a CRS class instance with: |
414 | 421 | - PROJ string |
433 | 440 | """ |
434 | 441 | if isinstance(value, CRS): |
435 | 442 | return value |
436 | return CRS(value) | |
437 | ||
438 | def get_geod(self): | |
439 | """ | |
440 | Returns | |
441 | ------- | |
442 | pyproj.geod.Geod: Geod object based on the ellipsoid. | |
443 | return CRS(value, **kwargs) | |
444 | ||
445 | def get_geod(self) -> Optional[Geod]: | |
446 | """ | |
447 | Returns | |
448 | ------- | |
449 | pyproj.geod.Geod: | |
450 | Geod object based on the ellipsoid. | |
443 | 451 | """ |
444 | 452 | if self.ellipsoid is None: |
445 | 453 | return None |
446 | in_kwargs = { | |
447 | "a": self.ellipsoid.semi_major_metre, | |
448 | "rf": self.ellipsoid.inverse_flattening, | |
449 | "b": self.ellipsoid.semi_minor_metre, | |
450 | } | |
451 | return Geod(**in_kwargs) | |
454 | return Geod( | |
455 | a=self.ellipsoid.semi_major_metre, | |
456 | rf=self.ellipsoid.inverse_flattening, | |
457 | b=self.ellipsoid.semi_minor_metre, | |
458 | ) | |
452 | 459 | |
453 | 460 | @staticmethod |
454 | def from_dict(proj_dict): | |
461 | def from_dict(proj_dict: dict) -> "CRS": | |
455 | 462 | """ |
456 | 463 | .. versionadded:: 2.2.0 |
457 | 464 | |
469 | 476 | return CRS(_prepare_from_dict(proj_dict)) |
470 | 477 | |
471 | 478 | @staticmethod |
472 | def from_json(crs_json): | |
479 | def from_json(crs_json: str) -> "CRS": | |
473 | 480 | """ |
474 | 481 | .. versionadded:: 2.4.0 |
475 | 482 | |
487 | 494 | return CRS.from_json_dict(_load_proj_json(crs_json)) |
488 | 495 | |
489 | 496 | @staticmethod |
490 | def from_json_dict(crs_dict): | |
497 | def from_json_dict(crs_dict: dict) -> "CRS": | |
491 | 498 | """ |
492 | 499 | .. versionadded:: 2.4.0 |
493 | 500 | |
504 | 511 | """ |
505 | 512 | return CRS(json.dumps(crs_dict)) |
506 | 513 | |
507 | def to_dict(self): | |
514 | def to_dict(self) -> dict: | |
508 | 515 | """ |
509 | 516 | .. versionadded:: 2.2.0 |
510 | 517 | |
516 | 523 | |
517 | 524 | Returns |
518 | 525 | ------- |
519 | dict: PROJ params in dict format. | |
526 | dict: | |
527 | PROJ params in dict format. | |
520 | 528 | |
521 | 529 | """ |
522 | 530 | |
546 | 554 | |
547 | 555 | return {key: value for key, value in items if value is not False} |
548 | 556 | |
549 | def to_cf(self, wkt_version=WktVersion.WKT2_2019, errcheck=False): | |
557 | def to_cf( | |
558 | self, | |
559 | wkt_version: Union[WktVersion, str] = WktVersion.WKT2_2019, | |
560 | errcheck: bool = False, | |
561 | ) -> dict: | |
550 | 562 | """ |
551 | 563 | .. versionadded:: 2.2.0 |
552 | 564 | |
567 | 579 | |
568 | 580 | Returns |
569 | 581 | ------- |
570 | dict: CF-1.8 version of the projection. | |
582 | dict: | |
583 | CF-1.8 version of the projection. | |
571 | 584 | |
572 | 585 | """ |
573 | 586 | unknown_names = ("unknown", "undefined") |
574 | cf_dict = {"crs_wkt": self.to_wkt(wkt_version)} | |
587 | cf_dict = {"crs_wkt": self.to_wkt(wkt_version)} # type: Dict[str, Any] | |
575 | 588 | |
576 | 589 | # handle bound CRS |
577 | if self.is_bound and self.coordinate_operation.towgs84: | |
578 | sub_cf = self.source_crs.to_cf(errcheck=errcheck) | |
590 | if ( | |
591 | self.is_bound | |
592 | and self.coordinate_operation | |
593 | and self.coordinate_operation.towgs84 | |
594 | ): | |
595 | sub_cf = self.source_crs.to_cf(errcheck=errcheck) # type: ignore | |
579 | 596 | sub_cf.pop("crs_wkt") |
580 | 597 | cf_dict.update(sub_cf) |
581 | 598 | cf_dict["towgs84"] = self.coordinate_operation.towgs84 |
594 | 611 | vert_json = self.to_json_dict() |
595 | 612 | if "geoid_model" in vert_json: |
596 | 613 | cf_dict["geoid_name"] = vert_json["geoid_model"]["name"] |
597 | if self.datum.name not in unknown_names: | |
614 | if self.datum and self.datum.name not in unknown_names: | |
598 | 615 | cf_dict["geopotential_datum_name"] = self.datum.name |
599 | 616 | return cf_dict |
600 | 617 | |
623 | 640 | self.coordinate_operation.method_name.lower() |
624 | 641 | ](self.coordinate_operation) |
625 | 642 | ) |
626 | if self.datum.name not in unknown_names: | |
643 | if self.datum and self.datum.name not in unknown_names: | |
627 | 644 | cf_dict["horizontal_datum_name"] = self.datum.name |
628 | 645 | else: |
629 | 646 | cf_dict["grid_mapping_name"] = "latitude_longitude" |
630 | 647 | return cf_dict |
631 | 648 | |
632 | 649 | # handle projected CRS |
633 | if self.is_projected and self.datum.name not in unknown_names: | |
650 | if self.is_projected and self.datum and self.datum.name not in unknown_names: | |
634 | 651 | cf_dict["horizontal_datum_name"] = self.datum.name |
635 | 652 | coordinate_operation = None |
636 | 653 | if not self.is_bound and self.is_projected: |
663 | 680 | return cf_dict |
664 | 681 | |
665 | 682 | @staticmethod |
666 | def from_cf(in_cf, errcheck=False): | |
683 | def from_cf(in_cf: dict, errcheck=False) -> "CRS": | |
667 | 684 | """ |
668 | 685 | .. versionadded:: 2.2.0 |
669 | 686 | |
702 | 719 | try: |
703 | 720 | geographic_conversion_method = _GEOGRAPHIC_GRID_MAPPING_NAME_MAP[ |
704 | 721 | grid_mapping_name |
705 | ] | |
722 | ] # type: Optional[Callable] | |
706 | 723 | except KeyError: |
707 | 724 | geographic_conversion_method = None |
708 | 725 | |
710 | 727 | if datum: |
711 | 728 | geographic_crs = GeographicCRS( |
712 | 729 | name=geographic_crs_name or "undefined", datum=datum, |
713 | ) | |
730 | ) # type: CRS | |
714 | 731 | elif geographic_crs_name: |
715 | 732 | geographic_crs = CRS(geographic_crs_name) |
716 | 733 | else: |
760 | 777 | name="undefined", components=[bound_crs or projected_crs, vertical_crs] |
761 | 778 | ) |
762 | 779 | |
763 | def is_exact_same(self, other, ignore_axis_order=False): | |
780 | def is_exact_same(self, other: Any, ignore_axis_order: bool = False) -> bool: | |
764 | 781 | """ |
765 | 782 | Check if the CRS objects are the exact same. |
766 | 783 | |
781 | 798 | return False |
782 | 799 | return super().is_exact_same(other) |
783 | 800 | |
784 | def equals(self, other, ignore_axis_order=False): | |
801 | def equals(self, other: Any, ignore_axis_order: bool = False) -> bool: | |
785 | 802 | """ |
786 | 803 | |
787 | 804 | .. versionadded:: 2.5.0 |
809 | 826 | return super().equals(other, ignore_axis_order=ignore_axis_order) |
810 | 827 | |
811 | 828 | @property |
812 | def geodetic_crs(self): | |
829 | def geodetic_crs(self) -> Optional["CRS"]: | |
813 | 830 | """ |
814 | 831 | .. versionadded:: 2.2.0 |
815 | 832 | |
816 | 833 | Returns |
817 | 834 | ------- |
818 | CRS: The the geodeticCRS / geographicCRS from the CRS. | |
819 | """ | |
820 | if super().geodetic_crs is None: | |
835 | CRS: | |
836 | The the geodeticCRS / geographicCRS from the CRS. | |
837 | ||
838 | """ | |
839 | geodetic_crs = super().geodetic_crs | |
840 | if geodetic_crs is None: | |
821 | 841 | return None |
822 | return CRS(super().geodetic_crs.srs) | |
842 | return CRS(geodetic_crs.srs) | |
823 | 843 | |
824 | 844 | @property |
825 | def source_crs(self): | |
826 | """ | |
827 | Returns | |
828 | ------- | |
829 | CRS: The the base CRS of a BoundCRS or a DerivedCRS/ProjectedCRS, | |
830 | or the source CRS of a CoordinateOperation. | |
831 | """ | |
832 | if super().source_crs is None: | |
845 | def source_crs(self) -> Optional["CRS"]: | |
846 | """ | |
847 | The the base CRS of a BoundCRS or a DerivedCRS/ProjectedCRS, | |
848 | or the source CRS of a CoordinateOperation. | |
849 | ||
850 | Returns | |
851 | ------- | |
852 | CRS | |
853 | """ | |
854 | source_crs = super().source_crs | |
855 | if source_crs is None: | |
833 | 856 | return None |
834 | return CRS(super().source_crs.srs) | |
857 | return CRS(source_crs.srs) | |
835 | 858 | |
836 | 859 | @property |
837 | def target_crs(self): | |
860 | def target_crs(self) -> Optional["CRS"]: | |
838 | 861 | """ |
839 | 862 | .. versionadded:: 2.2.0 |
840 | 863 | |
841 | 864 | Returns |
842 | 865 | ------- |
843 | CRS: The hub CRS of a BoundCRS or the target CRS of a CoordinateOperation. | |
844 | """ | |
845 | if super().target_crs is None: | |
866 | CRS: | |
867 | The hub CRS of a BoundCRS or the target CRS of a CoordinateOperation. | |
868 | ||
869 | """ | |
870 | target_crs = super().target_crs | |
871 | if target_crs is None: | |
846 | 872 | return None |
847 | return CRS(super().target_crs.srs) | |
873 | return CRS(target_crs.srs) | |
848 | 874 | |
849 | 875 | @property |
850 | def sub_crs_list(self): | |
876 | def sub_crs_list(self) -> List["CRS"]: | |
851 | 877 | """ |
852 | 878 | If the CRS is a compound CRS, it will return a list of sub CRS objects. |
853 | 879 | |
854 | 880 | Returns |
855 | 881 | ------- |
856 | list[CRS] | |
882 | List[CRS] | |
857 | 883 | """ |
858 | 884 | return [CRS(sub_crs.srs) for sub_crs in super().sub_crs_list] |
859 | 885 | |
860 | def __eq__(self, other): | |
886 | @property | |
887 | def utm_zone(self) -> Optional[str]: | |
888 | """ | |
889 | .. versionadded:: 2.6.0 | |
890 | ||
891 | Finds the UTM zone in a Projected CRS, Bound CRS, or Compound CRS | |
892 | ||
893 | Returns | |
894 | ------- | |
895 | Optional[str]: | |
896 | The UTM zone number and letter if applicable. | |
897 | """ | |
898 | if self.is_bound and self.source_crs: | |
899 | return self.source_crs.utm_zone | |
900 | elif self.sub_crs_list: | |
901 | for sub_crs in self.sub_crs_list: | |
902 | if sub_crs.utm_zone: | |
903 | return sub_crs.utm_zone | |
904 | elif ( | |
905 | self.coordinate_operation | |
906 | and "UTM ZONE" in self.coordinate_operation.name.upper() | |
907 | ): | |
908 | return self.coordinate_operation.name.upper().split("UTM ZONE ")[-1] | |
909 | return None | |
910 | ||
911 | def __eq__(self, other: Any) -> bool: | |
861 | 912 | return self.equals(other) |
862 | 913 | |
863 | def __reduce__(self): | |
914 | def __reduce__(self) -> Tuple[Type["CRS"], Tuple[str]]: | |
864 | 915 | """special method that allows CRS instance to be pickled""" |
865 | 916 | return self.__class__, (self.srs,) |
866 | 917 | |
867 | def __hash__(self): | |
918 | def __hash__(self) -> int: | |
868 | 919 | return hash(self.to_wkt()) |
869 | 920 | |
870 | def __str__(self): | |
921 | def __str__(self) -> str: | |
871 | 922 | return self.srs |
872 | 923 | |
873 | def __repr__(self): | |
874 | # get axis/coordinate system information | |
875 | axis_info_list = [] | |
876 | ||
877 | def extent_axis(axis_list): | |
878 | for axis_info in axis_list: | |
879 | axis_info_list.extend(["- ", str(axis_info), "\n"]) | |
880 | ||
924 | def __repr__(self) -> str: | |
925 | # get axis information | |
926 | axis_info_list = [] # type: List[str] | |
927 | for axis in self.axis_info: | |
928 | axis_info_list.extend(["- ", str(axis), "\n"]) | |
929 | axis_info_str = "".join(axis_info_list) | |
930 | ||
931 | # get coordinate system & sub CRS info | |
881 | 932 | source_crs_repr = "" |
882 | 933 | sub_crs_repr = "" |
883 | if self.axis_info: | |
884 | extent_axis(self.axis_info) | |
934 | if self.coordinate_system and self.coordinate_system.axis_list: | |
885 | 935 | coordinate_system_name = str(self.coordinate_system) |
886 | elif self.is_bound: | |
887 | extent_axis(self.source_crs.axis_info) | |
936 | elif self.is_bound and self.source_crs: | |
888 | 937 | coordinate_system_name = str(self.source_crs.coordinate_system) |
889 | 938 | source_crs_repr = "Source CRS: {}\n".format(self.source_crs.name) |
890 | 939 | else: |
891 | 940 | coordinate_system_names = [] |
892 | 941 | sub_crs_repr_list = ["Sub CRS:\n"] |
893 | 942 | for sub_crs in self.sub_crs_list: |
894 | extent_axis(sub_crs.axis_info) | |
895 | 943 | coordinate_system_names.append(str(sub_crs.coordinate_system)) |
896 | 944 | sub_crs_repr_list.extend(["- ", sub_crs.name, "\n"]) |
897 | 945 | coordinate_system_name = "|".join(coordinate_system_names) |
898 | 946 | sub_crs_repr = "".join(sub_crs_repr_list) |
899 | axis_info_str = "".join(axis_info_list) | |
900 | 947 | |
901 | 948 | # get coordinate operation repr |
902 | 949 | coordinate_operation = "" |
954 | 1001 | |
955 | 1002 | def __init__( |
956 | 1003 | self, |
957 | name="undefined", | |
958 | datum="urn:ogc:def:datum:EPSG::6326", | |
959 | ellipsoidal_cs=Ellipsoidal2DCS(), | |
960 | ): | |
1004 | name: str = "undefined", | |
1005 | datum: Any = "urn:ogc:def:datum:EPSG::6326", | |
1006 | ellipsoidal_cs: Any = None, | |
1007 | ) -> None: | |
961 | 1008 | """ |
962 | 1009 | Parameters |
963 | 1010 | ---------- |
977 | 1024 | "name": name, |
978 | 1025 | "datum": Datum.from_user_input(datum).to_json_dict(), |
979 | 1026 | "coordinate_system": CoordinateSystem.from_user_input( |
980 | ellipsoidal_cs | |
1027 | ellipsoidal_cs or Ellipsoidal2DCS() | |
981 | 1028 | ).to_json_dict(), |
982 | 1029 | } |
983 | 1030 | super().__init__(geographic_crs_json) |
991 | 1038 | """ |
992 | 1039 | |
993 | 1040 | def __init__( |
994 | self, base_crs, conversion, ellipsoidal_cs=Ellipsoidal2DCS(), name="undefined", | |
995 | ): | |
1041 | self, | |
1042 | base_crs: Any, | |
1043 | conversion: Any, | |
1044 | ellipsoidal_cs: Any = None, | |
1045 | name: str = "undefined", | |
1046 | ) -> None: | |
996 | 1047 | """ |
997 | 1048 | Parameters |
998 | 1049 | ---------- |
1018 | 1069 | conversion |
1019 | 1070 | ).to_json_dict(), |
1020 | 1071 | "coordinate_system": CoordinateSystem.from_user_input( |
1021 | ellipsoidal_cs | |
1072 | ellipsoidal_cs or Ellipsoidal2DCS() | |
1022 | 1073 | ).to_json_dict(), |
1023 | 1074 | } |
1024 | 1075 | super().__init__(derived_geographic_crs_json) |
1033 | 1084 | |
1034 | 1085 | def __init__( |
1035 | 1086 | self, |
1036 | conversion, | |
1037 | name="undefined", | |
1038 | cartesian_cs=Cartesian2DCS(), | |
1039 | geodetic_crs=GeographicCRS(), | |
1040 | ): | |
1087 | conversion: Any, | |
1088 | name: str = "undefined", | |
1089 | cartesian_cs: Any = None, | |
1090 | geodetic_crs: Any = None, | |
1091 | ) -> None: | |
1041 | 1092 | """ |
1042 | 1093 | Parameters |
1043 | 1094 | ---------- |
1058 | 1109 | "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", |
1059 | 1110 | "type": "ProjectedCRS", |
1060 | 1111 | "name": name, |
1061 | "base_crs": CRS.from_user_input(geodetic_crs).to_json_dict(), | |
1112 | "base_crs": CRS.from_user_input( | |
1113 | geodetic_crs or GeographicCRS() | |
1114 | ).to_json_dict(), | |
1062 | 1115 | "conversion": CoordinateOperation.from_user_input( |
1063 | 1116 | conversion |
1064 | 1117 | ).to_json_dict(), |
1065 | 1118 | "coordinate_system": CoordinateSystem.from_user_input( |
1066 | cartesian_cs | |
1119 | cartesian_cs or Cartesian2DCS() | |
1067 | 1120 | ).to_json_dict(), |
1068 | 1121 | } |
1069 | 1122 | super().__init__(proj_crs_json) |
1079 | 1132 | |
1080 | 1133 | """ |
1081 | 1134 | |
1082 | def __init__(self, name, datum, vertical_cs=VerticalCS(), geoid_model=None): | |
1135 | def __init__( | |
1136 | self, | |
1137 | name: str, | |
1138 | datum: Any, | |
1139 | vertical_cs: Any = None, | |
1140 | geoid_model: Optional[str] = None, | |
1141 | ) -> None: | |
1083 | 1142 | """ |
1084 | 1143 | Parameters |
1085 | 1144 | ---------- |
1100 | 1159 | "name": name, |
1101 | 1160 | "datum": Datum.from_user_input(datum).to_json_dict(), |
1102 | 1161 | "coordinate_system": CoordinateSystem.from_user_input( |
1103 | vertical_cs | |
1162 | vertical_cs or VerticalCS() | |
1104 | 1163 | ).to_json_dict(), |
1105 | 1164 | } |
1106 | 1165 | if geoid_model is not None: |
1116 | 1175 | This class is for building a Compound CRS. |
1117 | 1176 | """ |
1118 | 1177 | |
1119 | def __init__(self, name, components): | |
1178 | def __init__(self, name: str, components: List[Any]) -> None: | |
1120 | 1179 | """ |
1121 | 1180 | Parameters |
1122 | 1181 | ---------- |
1146 | 1205 | This class is for building a Bound CRS. |
1147 | 1206 | """ |
1148 | 1207 | |
1149 | def __init__(self, source_crs, target_crs, transformation): | |
1208 | def __init__(self, source_crs: Any, target_crs: Any, transformation: Any) -> None: | |
1150 | 1209 | """ |
1151 | 1210 | Parameters |
1152 | 1211 | ---------- |
0 | from typing import Any, Dict, Optional, Union | |
1 | ||
0 | 2 | from pyproj._crs import Datum, Ellipsoid, PrimeMeridian |
1 | 3 | |
2 | 4 | |
7 | 9 | Class to build a datum based on an ellipsoid and prime meridian. |
8 | 10 | """ |
9 | 11 | |
10 | def __new__(cls, name="undefined", ellipsoid="WGS 84", prime_meridian="Greenwich"): | |
12 | def __new__( | |
13 | cls, | |
14 | name: str = "undefined", | |
15 | ellipsoid: Any = "WGS 84", | |
16 | prime_meridian: Any = "Greenwich", | |
17 | ): | |
11 | 18 | """ |
12 | 19 | Parameters |
13 | 20 | ---------- |
40 | 47 | |
41 | 48 | def __new__( |
42 | 49 | cls, |
43 | name="undefined", | |
44 | semi_major_axis=None, | |
45 | inverse_flattening=None, | |
46 | semi_minor_axis=None, | |
47 | radius=None, | |
50 | name: str = "undefined", | |
51 | semi_major_axis: Optional[float] = None, | |
52 | inverse_flattening: Optional[float] = None, | |
53 | semi_minor_axis: Optional[float] = None, | |
54 | radius: Optional[float] = None, | |
48 | 55 | ): |
49 | 56 | """ |
50 | 57 | Parameters |
67 | 74 | "$schema": "https://proj.org/schemas/v0.2/projjson.schema.json", |
68 | 75 | "type": "Ellipsoid", |
69 | 76 | "name": name, |
70 | } | |
77 | } # type: Dict[str, Union[float, str]] | |
71 | 78 | if semi_major_axis is not None: |
72 | 79 | ellipsoid_json["semi_major_axis"] = semi_major_axis |
73 | 80 | if inverse_flattening is not None: |
86 | 93 | Class to build a prime meridian based on a longitude. |
87 | 94 | """ |
88 | 95 | |
89 | def __new__(cls, longitude, name="undefined"): | |
96 | def __new__(cls, longitude: float, name: str = "undefined"): | |
90 | 97 | """ |
91 | 98 | Parameters |
92 | 99 | ---------- |
10 | 10 | _VALIDATED_PROJ_DATA = None |
11 | 11 | |
12 | 12 | |
13 | def set_data_dir(proj_data_dir): | |
13 | def set_data_dir(proj_data_dir: str) -> None: | |
14 | 14 | """ |
15 | 15 | Set the data directory for PROJ to use. |
16 | 16 | |
32 | 32 | pyproj_global_context_initialize() |
33 | 33 | |
34 | 34 | |
35 | def append_data_dir(proj_data_dir): | |
35 | def append_data_dir(proj_data_dir: str) -> None: | |
36 | 36 | """ |
37 | 37 | Add an additional data directory for PROJ to use. |
38 | 38 | |
44 | 44 | set_data_dir(os.pathsep.join([get_data_dir(), proj_data_dir])) |
45 | 45 | |
46 | 46 | |
47 | def get_data_dir(): | |
47 | def get_data_dir() -> str: | |
48 | 48 | """ |
49 | 49 | The order of preference for the data directory is: |
50 | 50 | |
56 | 56 | |
57 | 57 | Returns |
58 | 58 | ------- |
59 | str: The valid data directory. | |
59 | str: | |
60 | The valid data directory. | |
60 | 61 | |
61 | 62 | """ |
62 | 63 | # to avoid re-validating |
83 | 84 | for proj_data_dir in potential_data_dirs.split(os.pathsep): |
84 | 85 | if valid_data_dir(proj_data_dir): |
85 | 86 | return True |
86 | break | |
87 | 87 | return None |
88 | 88 | |
89 | 89 | if valid_data_dirs(_USER_PROJ_DATA): |
8 | 8 | |
9 | 9 | internal_proj_error = None |
10 | 10 | |
11 | def __init__(self, error_message): | |
11 | def __init__(self, error_message: str) -> None: | |
12 | 12 | if self.internal_proj_error is not None: |
13 | 13 | error_message = ( |
14 | 14 | "{error_message}: (Internal Proj Error: {internal_proj_error})" |
20 | 20 | super().__init__(error_message) |
21 | 21 | |
22 | 22 | @staticmethod |
23 | def clear(): | |
23 | def clear() -> None: | |
24 | 24 | """ |
25 | 25 | This will clear the internal PROJ erro message. |
26 | 26 | """ |
31 | 31 | __all__ = ["Geod", "pj_ellps", "geodesic_version_str"] |
32 | 32 | |
33 | 33 | import math |
34 | from typing import Any, Dict, List, Optional, Tuple, Union | |
34 | 35 | |
35 | 36 | from pyproj._geod import Geod as _Geod |
36 | 37 | from pyproj._geod import geodesic_version_str |
44 | 45 | class Geod(_Geod): |
45 | 46 | """ |
46 | 47 | performs forward and inverse geodetic, or Great Circle, |
47 | computations. The forward computation (using the 'fwd' method) | |
48 | involves determining latitude, longitude and back azimuth of a | |
49 | 48 | computations. The forward computation (using the 'fwd' method) |
50 | 49 | involves determining latitude, longitude and back azimuth of a |
51 | 50 | terminus point given the latitude and longitude of an initial |
71 | 70 | |
72 | 71 | """ |
73 | 72 | |
74 | def __init__(self, initstring=None, **kwargs): | |
73 | def __init__(self, initstring: Optional[str] = None, **kwargs) -> None: | |
75 | 74 | """ |
76 | 75 | initialize a Geod class instance. |
77 | 76 | |
128 | 127 | """ |
129 | 128 | # if initparams is a proj-type init string, |
130 | 129 | # convert to dict. |
131 | ellpsd = {} | |
130 | ellpsd = {} # type: Dict[str, Union[str, float]] | |
132 | 131 | if initstring is not None: |
133 | 132 | for kvpair in initstring.split(): |
134 | 133 | # Actually only +a and +b are needed |
138 | 137 | k, v = kvpair.split("=") |
139 | 138 | k = k.lstrip("+") |
140 | 139 | if k in ["a", "b", "rf", "f", "es", "e"]: |
141 | v = float(v) | |
142 | ellpsd[k] = v | |
140 | ellpsd[k] = float(v) | |
141 | else: | |
142 | ellpsd[k] = v | |
143 | 143 | # merge this dict with kwargs dict. |
144 | 144 | kwargs = dict(list(kwargs.items()) + list(ellpsd.items())) |
145 | 145 | sphere = False |
146 | 146 | if "ellps" in kwargs: |
147 | 147 | # ellipse name given, look up in pj_ellps dict |
148 | 148 | ellps_dict = pj_ellps[kwargs["ellps"]] |
149 | a = ellps_dict["a"] | |
149 | a = ellps_dict["a"] # type: float | |
150 | 150 | if ellps_dict["description"] == "Normal Sphere": |
151 | 151 | sphere = True |
152 | 152 | if "b" in ellps_dict: |
153 | b = ellps_dict["b"] | |
154 | es = 1.0 - (b * b) / (a * a) | |
155 | f = (a - b) / a | |
153 | b = ellps_dict["b"] # type: float | |
154 | es = 1.0 - (b * b) / (a * a) # type: float | |
155 | f = (a - b) / a # type: float | |
156 | 156 | elif "rf" in ellps_dict: |
157 | 157 | f = 1.0 / ellps_dict["rf"] |
158 | 158 | b = a * (1.0 - f) |
196 | 196 | |
197 | 197 | super().__init__(a, f, sphere, b, es) |
198 | 198 | |
199 | def fwd(self, lons, lats, az, dist, radians=False): | |
200 | """ | |
201 | forward transformation - Returns longitudes, latitudes and back | |
202 | azimuths of terminus points given longitudes (lons) and | |
203 | latitudes (lats) of initial points, plus forward azimuths (az) | |
204 | and distances (dist). | |
205 | latitudes (lats) of initial points, plus forward azimuths (az) | |
206 | and distances (dist). | |
207 | ||
208 | Works with numpy and regular python array objects, python | |
209 | sequences and scalars. | |
210 | ||
211 | if radians=True, lons/lats and azimuths are radians instead of | |
212 | degrees. Distances are in meters. | |
199 | def fwd( | |
200 | self, lons: Any, lats: Any, az: Any, dist: Any, radians=False | |
201 | ) -> Tuple[Any, Any, Any]: | |
202 | """ | |
203 | Forward transformation | |
204 | ||
205 | Determine longitudes, latitudes and back azimuths of terminus | |
206 | points given longitudes and latitudes of initial points, | |
207 | plus forward azimuths and distances. | |
208 | ||
209 | Parameters | |
210 | ---------- | |
211 | lons: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
212 | Longitude(s) of initial point(s) | |
213 | lats: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
214 | Latitude(s) of initial point(s) | |
215 | az: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
216 | Forward azimuth(s) | |
217 | dist: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
218 | Distance(s) between initial and terminus point(s) | |
219 | in meters | |
220 | radians: bool, optional | |
221 | If True, the input data is assumed to be in radians. | |
222 | ||
223 | Returns | |
224 | ------- | |
225 | array, :class:`numpy.ndarray`, list, tuple, or scalar: | |
226 | Longitude(s) of terminus point(s) | |
227 | array, :class:`numpy.ndarray`, list, tuple, or scalar: | |
228 | Latitude(s) of terminus point(s) | |
229 | array, :class:`numpy.ndarray`, list, tuple, or scalar: | |
230 | Back azimuth(s) | |
213 | 231 | """ |
214 | 232 | # process inputs, making copies that support buffer API. |
215 | 233 | inx, xisfloat, xislist, xistuple = _copytobuffer(lons) |
223 | 241 | outz = _convertback(zisfloat, zislist, zistuple, inz) |
224 | 242 | return outx, outy, outz |
225 | 243 | |
226 | def inv(self, lons1, lats1, lons2, lats2, radians=False): | |
227 | """ | |
228 | inverse transformation - Returns forward and back azimuths, plus | |
229 | distances between initial points (specified by lons1, lats1) and | |
230 | terminus points (specified by lons2, lats2). | |
231 | ||
232 | Works with numpy and regular python array objects, python | |
233 | sequences and scalars. | |
234 | ||
235 | if radians=True, lons/lats and azimuths are radians instead of | |
236 | degrees. Distances are in meters. | |
244 | def inv( | |
245 | self, lons1: Any, lats1: Any, lons2: Any, lats2: Any, radians=False | |
246 | ) -> Tuple[Any, Any, Any]: | |
247 | """ | |
248 | Inverse transformation | |
249 | ||
250 | Determine forward and back azimuths, plus distances | |
251 | between initial points and terminus points. | |
252 | ||
253 | Parameters | |
254 | ---------- | |
255 | lons1: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
256 | Longitude(s) of initial point(s) | |
257 | lats1: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
258 | Latitude(s) of initial point(s) | |
259 | lons2: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
260 | Longitude(s) of terminus point(s) | |
261 | lats2: array, :class:`numpy.ndarray`, list, tuple, or scalar | |
262 | Latitude(s) of terminus point(s) | |
263 | radians: bool, optional | |
264 | If True, the input data is assumed to be in radians. | |
265 | ||
266 | Returns | |
267 | ------- | |
268 | array, :class:`numpy.ndarray`, list, tuple, or scalar: | |
269 | Forward azimuth(s) | |
270 | array, :class:`numpy.ndarray`, list, tuple, or scalar: | |
271 | Back azimuth(s) | |
272 | array, :class:`numpy.ndarray`, list, tuple, or scalar: | |
273 | Distance(s) between initial and terminus point(s) | |
274 | in meters | |
237 | 275 | """ |
238 | 276 | # process inputs, making copies that support buffer API. |
239 | 277 | inx, xisfloat, xislist, xistuple = _copytobuffer(lons1) |
247 | 285 | outz = _convertback(zisfloat, zislist, zistuple, inz) |
248 | 286 | return outx, outy, outz |
249 | 287 | |
250 | def npts(self, lon1, lat1, lon2, lat2, npts, radians=False): | |
251 | """ | |
252 | Given a single initial point and terminus point (specified by | |
253 | python floats lon1,lat1 and lon2,lat2), returns a list of | |
254 | longitude/latitude pairs describing npts equally spaced | |
255 | intermediate points along the geodesic between the initial and | |
256 | terminus points. | |
257 | ||
258 | if radians=True, lons/lats are radians instead of degrees. | |
288 | def npts( | |
289 | self, | |
290 | lon1: float, | |
291 | lat1: float, | |
292 | lon2: float, | |
293 | lat2: float, | |
294 | npts: int, | |
295 | radians: bool = False, | |
296 | ) -> List: | |
297 | """ | |
298 | Given a single initial point and terminus point, returns | |
299 | a list of longitude/latitude pairs describing npts equally | |
300 | spaced intermediate points along the geodesic between the | |
301 | initial and terminus points. | |
259 | 302 | |
260 | 303 | Example usage: |
261 | 304 | |
300 | 343 | '47.136 -109.100' |
301 | 344 | '46.805 -114.051' |
302 | 345 | '46.262 -118.924' |
346 | ||
347 | Parameters | |
348 | ---------- | |
349 | lon1: float | |
350 | Longitude of the initial point | |
351 | lat1: float | |
352 | Latitude of the initial point | |
353 | lon2: float | |
354 | Longitude of the terminus point | |
355 | lat2: float | |
356 | Latitude of the terminus point | |
357 | npts: int | |
358 | Number of points to be returned | |
359 | radians: bool, optional | |
360 | If True, the input data is assumed to be in radians. | |
361 | ||
362 | Returns | |
363 | ------- | |
364 | list of tuples: | |
365 | list of (lon, lat) points along the geodesic | |
366 | between the initial and terminus points. | |
303 | 367 | """ |
304 | 368 | lons, lats = super()._npts(lon1, lat1, lon2, lat2, npts, radians=radians) |
305 | 369 | return list(zip(lons, lats)) |
306 | 370 | |
307 | def line_length(self, lons, lats, radians=False): | |
371 | def line_length(self, lons: Any, lats: Any, radians: bool = False) -> float: | |
308 | 372 | """ |
309 | 373 | .. versionadded:: 2.3.0 |
310 | 374 | |
332 | 396 | |
333 | 397 | Returns |
334 | 398 | ------- |
335 | float: The total length of the line. | |
399 | float: | |
400 | The total length of the line. | |
336 | 401 | """ |
337 | 402 | # process inputs, making copies that support buffer API. |
338 | 403 | inx, xisfloat, xislist, xistuple = _copytobuffer(lons) |
339 | 404 | iny, yisfloat, yislist, yistuple = _copytobuffer(lats) |
340 | 405 | return self._line_length(inx, iny, radians=radians) |
341 | 406 | |
342 | def line_lengths(self, lons, lats, radians=False): | |
407 | def line_lengths(self, lons: Any, lats: Any, radians: bool = False) -> Any: | |
343 | 408 | """ |
344 | 409 | .. versionadded:: 2.3.0 |
345 | 410 | |
375 | 440 | line_lengths = _convertback(xisfloat, xislist, xistuple, inx) |
376 | 441 | return line_lengths if xisfloat else line_lengths[:-1] |
377 | 442 | |
378 | def polygon_area_perimeter(self, lons, lats, radians=False): | |
443 | def polygon_area_perimeter( | |
444 | self, lons: Any, lats: Any, radians: bool = False | |
445 | ) -> Tuple[float, float]: | |
379 | 446 | """ |
380 | 447 | .. versionadded:: 2.3.0 |
381 | 448 | |
421 | 488 | _copytobuffer(lons)[0], _copytobuffer(lats)[0], radians=radians |
422 | 489 | ) |
423 | 490 | |
424 | def geometry_length(self, geometry, radians=False): | |
491 | def geometry_length(self, geometry, radians: bool = False) -> float: | |
425 | 492 | """ |
426 | 493 | .. versionadded:: 2.3.0 |
427 | 494 | |
450 | 517 | |
451 | 518 | Returns |
452 | 519 | ------- |
453 | float: The total geodesic length of the geometry (meters). | |
454 | ||
520 | float: | |
521 | The total geodesic length of the geometry (meters). | |
455 | 522 | """ |
456 | 523 | try: |
457 | return self.line_length(*geometry.xy, radians=radians) | |
524 | return self.line_length(*geometry.xy, radians=radians) # type: ignore | |
458 | 525 | except (AttributeError, NotImplementedError): |
459 | 526 | pass |
460 | 527 | if hasattr(geometry, "exterior"): |
466 | 533 | return total_length |
467 | 534 | raise GeodError("Invalid geometry provided.") |
468 | 535 | |
469 | def geometry_area_perimeter(self, geometry, radians=False): | |
536 | def geometry_area_perimeter( | |
537 | self, geometry, radians: bool = False | |
538 | ) -> Tuple[float, float]: | |
470 | 539 | """ |
471 | 540 | .. versionadded:: 2.3.0 |
472 | 541 | |
511 | 580 | radians: bool, optional |
512 | 581 | If True, the input data is assumed to be in radians. |
513 | 582 | |
514 | Returns | |
583 | Returns | |
515 | 584 | ------- |
516 | 585 | (float, float): |
517 | 586 | The geodesic area (meters^2) and permimeter (meters) of the polygon. |
518 | 587 | """ |
519 | 588 | try: |
520 | return self.polygon_area_perimeter(*geometry.xy, radians=radians) | |
589 | return self.polygon_area_perimeter( # type: ignore | |
590 | *geometry.xy, radians=radians, | |
591 | ) | |
521 | 592 | except (AttributeError, NotImplementedError): |
522 | 593 | pass |
523 | 594 | # polygon |
541 | 612 | return total_area, total_perimeter |
542 | 613 | raise GeodError("Invalid geometry provided.") |
543 | 614 | |
544 | def __repr__(self): | |
615 | def __repr__(self) -> str: | |
545 | 616 | # search for ellipse name |
546 | 617 | for (ellps, vals) in pj_ellps.items(): |
547 | 618 | if self.a == vals["a"]: |
557 | 628 | # no ellipse name found, call super class |
558 | 629 | return super().__repr__() |
559 | 630 | |
560 | def __eq__(self, other): | |
631 | def __eq__(self, other: Any) -> bool: | |
561 | 632 | """ |
562 | 633 | equality operator == for Geod objects |
563 | 634 |
433 | 433 | PROJ_GRID_AVAILABILITY_USED_FOR_SORTING |
434 | 434 | PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID |
435 | 435 | PROJ_GRID_AVAILABILITY_IGNORED |
436 | ||
437 | ctypedef struct PJ_FACTORS: | |
438 | double meridional_scale | |
439 | double parallel_scale | |
440 | double areal_scale | |
441 | double angular_distortion | |
442 | double meridian_parallel_angle | |
443 | double meridian_convergence | |
444 | double tissot_semimajor | |
445 | double tissot_semiminor | |
446 | double dx_dlam | |
447 | double dx_dphi | |
448 | double dy_dlam | |
449 | double dy_dphi | |
450 | ||
451 | PJ_FACTORS proj_factors(PJ *P, PJ_COORD lp) nogil |
35 | 35 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ |
36 | 36 | import re |
37 | 37 | import warnings |
38 | ||
39 | from pyproj import _proj | |
38 | from typing import Any, Optional, Tuple, Type | |
39 | ||
40 | 40 | from pyproj._list import get_proj_operations_map |
41 | from pyproj._proj import Factors, _Proj, proj_version_str # noqa: F401 | |
41 | 42 | from pyproj.compat import cstrencode, pystrdecode |
42 | 43 | from pyproj.crs import CRS |
43 | 44 | from pyproj.utils import _convertback, _copytobuffer |
44 | 45 | |
45 | # import numpy as np | |
46 | proj_version_str = _proj.proj_version_str | |
47 | ||
48 | 46 | pj_list = get_proj_operations_map() |
49 | 47 | |
50 | 48 | |
51 | class Proj(_proj.Proj): | |
49 | class Proj(_Proj): | |
52 | 50 | """ |
53 | 51 | Performs cartographic transformations (converts from |
54 | 52 | longitude,latitude to native map projection x,y coordinates and |
84 | 82 | |
85 | 83 | """ |
86 | 84 | |
87 | def __init__(self, projparams=None, preserve_units=True, **kwargs): | |
85 | def __init__( | |
86 | self, projparams: Any = None, preserve_units: bool = True, **kwargs | |
87 | ) -> None: | |
88 | 88 | """ |
89 | 89 | initialize a Proj class instance. |
90 | 90 | |
94 | 94 | Parameters |
95 | 95 | ---------- |
96 | 96 | projparams: int, str, dict, pyproj.CRS |
97 | A PROJ or WKT string, PROJ dict, EPSG integer, or a pyproj.CRS instnace. | |
97 | A PROJ or WKT string, PROJ dict, EPSG integer, or a pyproj.CRS instance. | |
98 | 98 | preserve_units: bool |
99 | 99 | If false, will ensure +units=m. |
100 | 100 | **kwargs: |
142 | 142 | >>> '{:.3f} {:.3f}'.format(x2, y2) |
143 | 143 | '116.366 39.867' |
144 | 144 | """ |
145 | self.crs = CRS.from_user_input(projparams if projparams is not None else kwargs) | |
145 | self.crs = CRS.from_user_input(projparams, **kwargs) | |
146 | 146 | # make sure units are meters if preserve_units is False. |
147 | 147 | if not preserve_units and "foot" in self.crs.axis_info[0].unit_name: |
148 | 148 | # ignore export to PROJ string deprecation warning |
169 | 169 | projstring = re.sub(r"\s\+?type=crs", "", projstring) |
170 | 170 | super().__init__(cstrencode(projstring.strip())) |
171 | 171 | |
172 | def __call__(self, *args, **kw): | |
172 | def __call__(self, *args, **kw) -> Tuple[Any, Any]: | |
173 | 173 | # ,lon,lat,inverse=False,errcheck=False): |
174 | 174 | """ |
175 | 175 | Calling a Proj class instance with the arguments lon, lat will |
203 | 203 | outy = _convertback(yisfloat, yislist, xistuple, iny) |
204 | 204 | return outx, outy |
205 | 205 | |
206 | def definition_string(self): | |
206 | def get_factors( | |
207 | self, | |
208 | longitude: Any, | |
209 | latitude: Any, | |
210 | radians: bool = False, | |
211 | errcheck: bool = False, | |
212 | ) -> Factors: | |
213 | """ | |
214 | .. versionadded:: 2.6.0 | |
215 | ||
216 | Calculate various cartographic properties, such as scale factors, angular | |
217 | distortion and meridian convergence. Depending on the underlying projection | |
218 | values will be calculated either numerically (default) or analytically. | |
219 | ||
220 | The function also calculates the partial derivatives of the given | |
221 | coordinate. | |
222 | ||
223 | Parameters | |
224 | ---------- | |
225 | longitude: scalar or array (numpy or python) | |
226 | Input longitude coordinate(s). | |
227 | latitude: scalar or array (numpy or python) | |
228 | Input latitude coordinate(s). | |
229 | radians: boolean, optional | |
230 | If True, will expect input data to be in radians. | |
231 | Default is False (degrees). | |
232 | errcheck: boolean, optional (default False) | |
233 | If True an exception is raised if the errors are found in the process. | |
234 | By default errcheck=False and ``inf`` is returned. | |
235 | ||
236 | Returns | |
237 | ------- | |
238 | Factors | |
239 | """ | |
240 | # process inputs, making copies that support buffer API. | |
241 | inx, xisfloat, xislist, xistuple = _copytobuffer(longitude) | |
242 | iny, yisfloat, yislist, yistuple = _copytobuffer(latitude) | |
243 | ||
244 | # calculate the factors | |
245 | factors = self._get_factors(inx, iny, radians=radians, errcheck=errcheck) | |
246 | ||
247 | # if inputs were lists, tuples or floats, convert back. | |
248 | return Factors( | |
249 | meridional_scale=_convertback( | |
250 | xisfloat, xislist, xistuple, factors.meridional_scale | |
251 | ), | |
252 | parallel_scale=_convertback( | |
253 | xisfloat, xislist, xistuple, factors.parallel_scale | |
254 | ), | |
255 | areal_scale=_convertback(xisfloat, xislist, xistuple, factors.areal_scale), | |
256 | angular_distortion=_convertback( | |
257 | xisfloat, xislist, xistuple, factors.angular_distortion | |
258 | ), | |
259 | meridian_parallel_angle=_convertback( | |
260 | xisfloat, xislist, xistuple, factors.meridian_parallel_angle | |
261 | ), | |
262 | meridian_convergence=_convertback( | |
263 | xisfloat, xislist, xistuple, factors.meridian_convergence | |
264 | ), | |
265 | tissot_semimajor=_convertback( | |
266 | xisfloat, xislist, xistuple, factors.tissot_semimajor | |
267 | ), | |
268 | tissot_semiminor=_convertback( | |
269 | xisfloat, xislist, xistuple, factors.tissot_semiminor | |
270 | ), | |
271 | dx_dlam=_convertback(xisfloat, xislist, xistuple, factors.dx_dlam), | |
272 | dx_dphi=_convertback(xisfloat, xislist, xistuple, factors.dx_dphi), | |
273 | dy_dlam=_convertback(xisfloat, xislist, xistuple, factors.dy_dlam), | |
274 | dy_dphi=_convertback(xisfloat, xislist, xistuple, factors.dy_dphi), | |
275 | ) | |
276 | ||
277 | def definition_string(self) -> str: | |
207 | 278 | """Returns formal definition string for projection |
208 | 279 | |
209 | 280 | >>> Proj("epsg:4326").definition_string() |
210 | 281 | 'proj=longlat datum=WGS84 no_defs ellps=WGS84 towgs84=0,0,0' |
211 | >>> | |
212 | 282 | """ |
213 | 283 | return pystrdecode(self.definition) |
214 | 284 | |
215 | def to_latlong_def(self): | |
285 | def to_latlong_def(self) -> Optional[str]: | |
216 | 286 | """return the definition string of the geographic (lat/lon) |
217 | 287 | coordinate version of the current projection""" |
218 | return self.crs.geodetic_crs.to_proj4(4) | |
219 | ||
220 | def to_latlong(self): | |
288 | return self.crs.geodetic_crs.to_proj4(4) if self.crs.geodetic_crs else None | |
289 | ||
290 | def to_latlong(self) -> "Proj": | |
221 | 291 | """return a new Proj instance which is the geographic (lat/lon) |
222 | 292 | coordinate version of the current projection""" |
223 | 293 | return Proj(self.crs.geodetic_crs) |
224 | 294 | |
225 | def __reduce__(self): | |
295 | def __reduce__(self) -> Tuple[Type["Proj"], Tuple[str]]: | |
226 | 296 | """special method that allows pyproj.Proj instance to be pickled""" |
227 | 297 | return self.__class__, (self.crs.srs,) |
228 | 298 | |
229 | def __repr__(self): | |
299 | def __repr__(self) -> str: | |
230 | 300 | return "Proj('{srs}', preserve_units=True)".format(srs=self.srs) |
231 | 301 | |
232 | def __eq__(self, other): | |
302 | def __eq__(self, other: Any) -> bool: | |
233 | 303 | if not isinstance(other, Proj): |
234 | 304 | return False |
235 | 305 | return self._is_equivalent(other) |
23 | 23 | "TransformerGroup", |
24 | 24 | "AreaOfInterest", |
25 | 25 | ] |
26 | ||
27 | 26 | from array import array |
28 | 27 | from itertools import chain, islice |
28 | from typing import Any, Iterable, Iterator, List, Optional, Tuple, Union | |
29 | 29 | |
30 | 30 | from pyproj import CRS, Proj |
31 | from pyproj._crs import AreaOfUse, CoordinateOperation | |
31 | 32 | from pyproj._transformer import AreaOfInterest, _Transformer, _TransformerGroup # noqa |
32 | 33 | from pyproj.compat import cstrencode |
33 | 34 | from pyproj.enums import TransformDirection, WktVersion |
53 | 54 | |
54 | 55 | def __init__( |
55 | 56 | self, |
56 | crs_from, | |
57 | crs_to, | |
58 | skip_equivalent=False, | |
59 | always_xy=False, | |
60 | area_of_interest=None, | |
61 | ): | |
57 | crs_from: Any, | |
58 | crs_to: Any, | |
59 | skip_equivalent: bool = False, | |
60 | always_xy: bool = False, | |
61 | area_of_interest: Optional[AreaOfInterest] = None, | |
62 | ) -> None: | |
62 | 63 | """Get all possible transformations from a :obj:`pyproj.crs.CRS` |
63 | 64 | or input used to create one. |
64 | 65 | |
103 | 104 | self._transformers[iii] = Transformer(transformer) |
104 | 105 | |
105 | 106 | @property |
106 | def transformers(self): | |
107 | def transformers(self) -> List["Transformer"]: | |
107 | 108 | """ |
108 | 109 | list[:obj:`Transformer`]: |
109 | 110 | List of available :obj:`Transformer` |
112 | 113 | return self._transformers |
113 | 114 | |
114 | 115 | @property |
115 | def unavailable_operations(self): | |
116 | def unavailable_operations(self) -> List[CoordinateOperation]: | |
116 | 117 | """ |
117 | 118 | list[:obj:`pyproj.crs.CoordinateOperation`]: |
118 | 119 | List of :obj:`pyproj.crs.CoordinateOperation` that are not |
121 | 122 | return self._unavailable_operations |
122 | 123 | |
123 | 124 | @property |
124 | def best_available(self): | |
125 | def best_available(self) -> bool: | |
125 | 126 | """ |
126 | 127 | bool: If True, the best possible transformer is available. |
127 | 128 | """ |
128 | 129 | return self._best_available |
129 | 130 | |
130 | def __repr__(self): | |
131 | def __repr__(self) -> str: | |
131 | 132 | return ( |
132 | 133 | "<TransformerGroup: best_available={best_available}>\n" |
133 | 134 | "- transformers: {transformers}\n" |
151 | 152 | |
152 | 153 | """ |
153 | 154 | |
154 | def __init__(self, base_transformer=None): | |
155 | def __init__(self, base_transformer: Optional[_Transformer] = None) -> None: | |
155 | 156 | if not isinstance(base_transformer, _Transformer): |
156 | 157 | ProjError.clear() |
157 | 158 | raise ProjError( |
161 | 162 | self._transformer = base_transformer |
162 | 163 | |
163 | 164 | @property |
164 | def name(self): | |
165 | def name(self) -> str: | |
165 | 166 | """ |
166 | 167 | str: Name of the projection. |
167 | 168 | """ |
168 | 169 | return self._transformer.id |
169 | 170 | |
170 | 171 | @property |
171 | def description(self): | |
172 | def description(self) -> str: | |
172 | 173 | """ |
173 | 174 | str: Description of the projection. |
174 | 175 | """ |
175 | 176 | return self._transformer.description |
176 | 177 | |
177 | 178 | @property |
178 | def definition(self): | |
179 | def definition(self) -> str: | |
179 | 180 | """ |
180 | 181 | str: Definition of the projection. |
181 | 182 | """ |
182 | 183 | return self._transformer.definition |
183 | 184 | |
184 | 185 | @property |
185 | def has_inverse(self): | |
186 | def has_inverse(self) -> bool: | |
186 | 187 | """ |
187 | 188 | bool: True if an inverse mapping exists. |
188 | 189 | """ |
189 | 190 | return self._transformer.has_inverse |
190 | 191 | |
191 | 192 | @property |
192 | def accuracy(self): | |
193 | def accuracy(self) -> float: | |
193 | 194 | """ |
194 | 195 | float: Expected accuracy of the transformation. -1 if unknown. |
195 | 196 | """ |
196 | 197 | return self._transformer.accuracy |
197 | 198 | |
198 | 199 | @property |
199 | def area_of_use(self): | |
200 | def area_of_use(self) -> AreaOfUse: | |
200 | 201 | """ |
201 | 202 | .. versionadded:: 2.3.0 |
202 | 203 | |
203 | 204 | Returns |
204 | 205 | ------- |
205 | AreaOfUse: The area of use object with associated attributes. | |
206 | AreaOfUse: | |
207 | The area of use object with associated attributes. | |
206 | 208 | """ |
207 | 209 | return self._transformer.area_of_use |
208 | 210 | |
209 | 211 | @property |
210 | def remarks(self): | |
212 | def remarks(self) -> str: | |
211 | 213 | """ |
212 | 214 | .. versionadded:: 2.4.0 |
213 | 215 | |
214 | str: Remarks about object. | |
216 | Returns | |
217 | ------- | |
218 | str: | |
219 | Remarks about object. | |
215 | 220 | """ |
216 | 221 | return self._transformer.remarks |
217 | 222 | |
218 | 223 | @property |
219 | def scope(self): | |
224 | def scope(self) -> str: | |
220 | 225 | """ |
221 | 226 | .. versionadded:: 2.4.0 |
222 | 227 | |
223 | str: Scope of object. | |
228 | Returns | |
229 | ------- | |
230 | str: | |
231 | Scope of object. | |
224 | 232 | """ |
225 | 233 | return self._transformer.scope |
226 | 234 | |
227 | 235 | @property |
228 | def operations(self): | |
236 | def operations(self) -> Optional[Tuple[CoordinateOperation]]: | |
229 | 237 | """ |
230 | 238 | .. versionadded:: 2.4.0 |
231 | 239 | |
232 | tuple[CoordinateOperation]: The operations in a concatenated operation. | |
240 | Returns | |
241 | ------- | |
242 | Tuple[CoordinateOperation]: | |
243 | The operations in a concatenated operation. | |
233 | 244 | """ |
234 | 245 | return self._transformer.operations |
235 | 246 | |
236 | 247 | @staticmethod |
237 | 248 | def from_proj( |
238 | proj_from, | |
239 | proj_to, | |
240 | skip_equivalent=False, | |
241 | always_xy=False, | |
242 | area_of_interest=None, | |
243 | ): | |
249 | proj_from: Any, | |
250 | proj_to: Any, | |
251 | skip_equivalent: bool = False, | |
252 | always_xy: bool = False, | |
253 | area_of_interest: Optional[AreaOfInterest] = None, | |
254 | ) -> "Transformer": | |
244 | 255 | """Make a Transformer from a :obj:`pyproj.proj.Proj` or input used to create one. |
245 | 256 | |
246 | 257 | .. versionadded:: 2.1.2 skip_equivalent |
266 | 277 | |
267 | 278 | Returns |
268 | 279 | ------- |
269 | :obj:`Transformer` | |
280 | Transformer | |
270 | 281 | |
271 | 282 | """ |
272 | 283 | if not isinstance(proj_from, Proj): |
284 | 295 | |
285 | 296 | @staticmethod |
286 | 297 | def from_crs( |
287 | crs_from, crs_to, skip_equivalent=False, always_xy=False, area_of_interest=None | |
288 | ): | |
298 | crs_from: Any, | |
299 | crs_to: Any, | |
300 | skip_equivalent: bool = False, | |
301 | always_xy: bool = False, | |
302 | area_of_interest: Optional[AreaOfInterest] = None, | |
303 | ) -> "Transformer": | |
289 | 304 | """Make a Transformer from a :obj:`pyproj.crs.CRS` or input used to create one. |
290 | 305 | |
291 | 306 | .. versionadded:: 2.1.2 skip_equivalent |
311 | 326 | |
312 | 327 | Returns |
313 | 328 | ------- |
314 | :obj:`Transformer` | |
329 | Transformer | |
315 | 330 | |
316 | 331 | """ |
317 | 332 | return Transformer( |
325 | 340 | ) |
326 | 341 | |
327 | 342 | @staticmethod |
328 | def from_pipeline(proj_pipeline): | |
343 | def from_pipeline(proj_pipeline: str) -> "Transformer": | |
329 | 344 | """Make a Transformer from a PROJ pipeline string. |
330 | 345 | |
331 | 346 | https://proj.org/operations/pipeline.html |
344 | 359 | |
345 | 360 | def transform( |
346 | 361 | self, |
347 | xx, | |
348 | yy, | |
349 | zz=None, | |
350 | tt=None, | |
351 | radians=False, | |
352 | errcheck=False, | |
353 | direction=TransformDirection.FORWARD, | |
354 | ): | |
362 | xx: Any, | |
363 | yy: Any, | |
364 | zz: Any = None, | |
365 | tt: Any = None, | |
366 | radians: bool = False, | |
367 | errcheck: bool = False, | |
368 | direction: Union[TransformDirection, str] = TransformDirection.FORWARD, | |
369 | ) -> Any: | |
355 | 370 | """ |
356 | 371 | Transform points between two coordinate systems. |
357 | 372 | |
395 | 410 | >>> pipe_trans = Transformer.from_pipeline(pipeline_str) |
396 | 411 | >>> xt, yt = pipe_trans.transform(2.1, 0.001) |
397 | 412 | >>> "%.3f %.3f" % (xt, yt) |
398 | '120.321 0.057' | |
413 | '2.100 0.001' | |
399 | 414 | >>> transproj = Transformer.from_crs( |
400 | 415 | ... {"proj":'geocent', "ellps":'WGS84', "datum":'WGS84'}, |
401 | 416 | ... "EPSG:4326", |
449 | 464 | outy = _convertback(yisfloat, yislist, xistuple, iny) |
450 | 465 | return_data = (outx, outy) |
451 | 466 | if inz is not None: |
452 | return_data += (_convertback(zisfloat, zislist, zistuple, inz),) | |
467 | return_data += ( # type: ignore | |
468 | _convertback(zisfloat, zislist, zistuple, inz), | |
469 | ) | |
453 | 470 | if intime is not None: |
454 | return_data += (_convertback(tisfloat, tislist, tistuple, intime),) | |
471 | return_data += ( # type: ignore | |
472 | _convertback(tisfloat, tislist, tistuple, intime), | |
473 | ) | |
455 | 474 | return return_data |
456 | 475 | |
457 | 476 | def itransform( |
458 | 477 | self, |
459 | points, | |
460 | switch=False, | |
461 | time_3rd=False, | |
462 | radians=False, | |
463 | errcheck=False, | |
464 | direction=TransformDirection.FORWARD, | |
465 | ): | |
478 | points: Any, | |
479 | switch: bool = False, | |
480 | time_3rd: bool = False, | |
481 | radians: bool = False, | |
482 | errcheck: bool = False, | |
483 | direction: Union[TransformDirection, str] = TransformDirection.FORWARD, | |
484 | ) -> Iterator[Iterable]: | |
466 | 485 | """ |
467 | 486 | Iterator/generator version of the function pyproj.Transformer.transform. |
468 | 487 | |
507 | 526 | >>> pipe_trans = Transformer.from_pipeline(pipeline_str) |
508 | 527 | >>> for pt in pipe_trans.itransform([(2.1, 0.001)]): |
509 | 528 | ... '{:.3f} {:.3f}'.format(*pt) |
510 | '120.321 0.057' | |
529 | '2.100 0.001' | |
511 | 530 | >>> transproj = Transformer.from_crs( |
512 | 531 | ... {"proj":'geocent', "ellps":'WGS84', "datum":'WGS84'}, |
513 | 532 | ... "EPSG:4326", |
579 | 598 | for pt in zip(*([iter(buff)] * stride)): |
580 | 599 | yield pt |
581 | 600 | |
582 | def to_wkt(self, version=WktVersion.WKT2_2019, pretty=False): | |
601 | def to_wkt( | |
602 | self, | |
603 | version: Union[WktVersion, str] = WktVersion.WKT2_2019, | |
604 | pretty: bool = False, | |
605 | ): | |
583 | 606 | """ |
584 | 607 | Convert the projection to a WKT string. |
585 | 608 | |
602 | 625 | |
603 | 626 | Returns |
604 | 627 | ------- |
605 | str: The WKT string. | |
628 | str: | |
629 | The WKT string. | |
606 | 630 | """ |
607 | 631 | return self._transformer.to_wkt(version=version, pretty=pretty) |
608 | 632 | |
609 | def to_json(self, pretty=False, indentation=2): | |
633 | def to_json(self, pretty: bool = False, indentation: int = 2) -> str: | |
610 | 634 | """ |
611 | 635 | Convert the projection to a JSON string. |
612 | 636 | |
621 | 645 | |
622 | 646 | Returns |
623 | 647 | ------- |
624 | str: The JSON string. | |
648 | str: | |
649 | The JSON string. | |
625 | 650 | """ |
626 | 651 | return self._transformer.to_json(pretty=pretty, indentation=indentation) |
627 | 652 | |
628 | def to_json_dict(self): | |
653 | def to_json_dict(self) -> dict: | |
629 | 654 | """ |
630 | 655 | Convert the projection to a JSON dictionary. |
631 | 656 | |
633 | 658 | |
634 | 659 | Returns |
635 | 660 | ------- |
636 | dict: The JSON dictionary. | |
661 | dict: | |
662 | The JSON dictionary. | |
637 | 663 | """ |
638 | 664 | return self._transformer.to_json_dict() |
639 | 665 | |
640 | def __str__(self): | |
666 | def __str__(self) -> str: | |
641 | 667 | return self.definition |
642 | 668 | |
643 | def __repr__(self): | |
669 | def __repr__(self) -> str: | |
644 | 670 | return ( |
645 | 671 | "<{type_name}: {name}>\nDescription: {description}\n" |
646 | 672 | "Area of Use:\n{area_of_use}" |
651 | 677 | area_of_use=self.area_of_use or "- undefined", |
652 | 678 | ) |
653 | 679 | |
680 | def __eq__(self, other: Any) -> bool: | |
681 | if not isinstance(other, Transformer): | |
682 | return False | |
683 | return self._transformer.__eq__(other._transformer) | |
684 | ||
654 | 685 | |
655 | 686 | def transform( |
656 | p1, | |
657 | p2, | |
658 | x, | |
659 | y, | |
660 | z=None, | |
661 | tt=None, | |
662 | radians=False, | |
663 | errcheck=False, | |
664 | skip_equivalent=False, | |
665 | always_xy=False, | |
687 | p1: Any, | |
688 | p2: Any, | |
689 | x: Any, | |
690 | y: Any, | |
691 | z: Any = None, | |
692 | tt: Any = None, | |
693 | radians: bool = False, | |
694 | errcheck: bool = False, | |
695 | skip_equivalent: bool = False, | |
696 | always_xy: bool = False, | |
666 | 697 | ): |
667 | 698 | """ |
668 | 699 | .. versionadded:: 2.1.2 skip_equivalent |
743 | 774 | |
744 | 775 | |
745 | 776 | def itransform( |
746 | p1, | |
747 | p2, | |
748 | points, | |
749 | switch=False, | |
750 | time_3rd=False, | |
751 | radians=False, | |
752 | errcheck=False, | |
753 | skip_equivalent=False, | |
754 | always_xy=False, | |
777 | p1: Any, | |
778 | p2: Any, | |
779 | points: Iterable[Iterable], | |
780 | switch: bool = False, | |
781 | time_3rd: bool = False, | |
782 | radians: bool = False, | |
783 | errcheck: bool = False, | |
784 | skip_equivalent: bool = False, | |
785 | always_xy: bool = False, | |
755 | 786 | ): |
756 | 787 | """ |
757 | 788 | .. versionadded:: 2.1.2 skip_equivalent |
0 | 0 | from array import array |
1 | from typing import Any, Tuple | |
1 | 2 | |
2 | 3 | |
3 | def _copytobuffer_return_scalar(x): | |
4 | def _copytobuffer_return_scalar(xx: Any) -> Tuple[array, bool, bool, bool]: | |
5 | """ | |
6 | Parameters | |
7 | ----------- | |
8 | xx: float or 0-d numpy array | |
9 | """ | |
4 | 10 | try: |
5 | 11 | # inx,isfloat,islist,istuple |
6 | return array("d", (float(x),)), True, False, False | |
12 | return array("d", (float(xx),)), True, False, False | |
7 | 13 | except Exception: |
8 | raise TypeError("input must be an array, list, tuple or scalar") | |
14 | raise TypeError("input must be a scalar") | |
9 | 15 | |
10 | 16 | |
11 | def _copytobuffer(x): | |
17 | def _copytobuffer(xx: Any) -> Tuple[Any, bool, bool, bool]: | |
12 | 18 | """ |
13 | return a copy of x as an object that supports the python Buffer | |
19 | return a copy of xx as an object that supports the python Buffer | |
14 | 20 | API (python array if input is float, list or tuple, numpy array |
15 | 21 | if input is a numpy array). returns copyofx, isfloat, islist, |
16 | 22 | istuple (islist is True if input is a list, istuple is true if |
22 | 28 | istuple = False |
23 | 29 | # first, if it's a numpy array scalar convert to float |
24 | 30 | # (array scalars don't support buffer API) |
25 | if hasattr(x, "shape"): | |
26 | if x.shape == (): | |
27 | return _copytobuffer_return_scalar(x) | |
31 | if hasattr(xx, "shape"): | |
32 | if xx.shape == (): | |
33 | return _copytobuffer_return_scalar(xx) | |
28 | 34 | else: |
29 | 35 | try: |
30 | 36 | # typecast numpy arrays to double. |
31 | 37 | # (this makes a copy - which is crucial |
32 | 38 | # since buffer is modified in place) |
33 | x.dtype.char | |
39 | xx.dtype.char | |
34 | 40 | # Basemap issue |
35 | 41 | # https://github.com/matplotlib/basemap/pull/223/files |
36 | 42 | # (deal with input array in fortran order) |
37 | inx = x.copy(order="C").astype("d") | |
43 | inx = xx.copy(order="C").astype("d") | |
38 | 44 | # inx,isfloat,islist,istuple |
39 | 45 | return inx, False, False, False |
40 | 46 | except Exception: |
41 | 47 | try: # perhaps they are Numeric/numarrays? |
42 | 48 | # sorry, not tested yet. |
43 | 49 | # i don't know Numeric/numarrays has `shape'. |
44 | x.typecode() | |
45 | inx = x.astype("d") | |
50 | xx.typecode() | |
51 | inx = xx.astype("d") | |
46 | 52 | # inx,isfloat,islist,istuple |
47 | 53 | return inx, False, False, False |
48 | 54 | except Exception: |
49 | 55 | raise TypeError("input must be an array, list, tuple or scalar") |
50 | 56 | else: |
51 | 57 | # perhaps they are regular python arrays? |
52 | if hasattr(x, "typecode"): | |
53 | # x.typecode | |
54 | inx = array("d", x) | |
58 | if hasattr(xx, "typecode"): | |
59 | # xx.typecode | |
60 | inx = array("d", xx) | |
55 | 61 | # try to convert to python array |
56 | 62 | # a list. |
57 | elif type(x) == list: | |
58 | inx = array("d", x) | |
63 | elif type(xx) == list: | |
64 | inx = array("d", xx) | |
59 | 65 | islist = True |
60 | 66 | # a tuple. |
61 | elif type(x) == tuple: | |
62 | inx = array("d", x) | |
67 | elif type(xx) == tuple: | |
68 | inx = array("d", xx) | |
63 | 69 | istuple = True |
64 | 70 | # a scalar? |
65 | 71 | else: |
66 | return _copytobuffer_return_scalar(x) | |
72 | return _copytobuffer_return_scalar(xx) | |
67 | 73 | return inx, isfloat, islist, istuple |
68 | 74 | |
69 | 75 | |
70 | def _convertback(isfloat, islist, istuple, inx): | |
76 | def _convertback(isfloat: bool, islist: bool, istuple: bool, inx: Any) -> Any: | |
71 | 77 | # if inputs were lists, tuples or floats, convert back to original type. |
72 | 78 | if isfloat: |
73 | 79 | return inx[0] |
0 | 0 | [build-system] |
1 | 1 | # Minimum requirements for the build system to execute. |
2 | requires = ["setuptools", "wheel", "cython>=0.28.4"]⏎ | |
2 | requires = ["setuptools", "wheel", "cython>=0.28.4"] |
1 | 1 | black; python_version >= '3.6' |
2 | 2 | flake8 |
3 | 3 | mock |
4 | mypy | |
4 | 5 | numpy |
5 | 6 | pylint |
6 | 7 | pytest>3.6 |
7 | 8 | pytest-cov |
8 | shapely; sys_platform != 'win32' # shapely wheels not on Windows ⏎ | |
9 | shapely; sys_platform != 'win32' # shapely wheels not on Windows | |
10 | pre-commit |
74 | 74 | epsg_init_crs.to_proj4() |
75 | 75 | == "+proj=utm +zone=11 +datum=NAD83 +units=m +no_defs +type=crs" |
76 | 76 | ) |
77 | ||
78 | ||
79 | def test_initialize_projparams_with_kwargs(): | |
80 | crs_mixed_args = CRS("+proj=utm +zone=10", ellps="WGS84") | |
81 | crs_positional = CRS("+proj=utm +zone=10 +ellps=WGS84") | |
82 | assert crs_mixed_args.is_exact_same(crs_positional) | |
77 | 83 | |
78 | 84 | |
79 | 85 | def test_bare_parameters(): |
276 | 282 | ) |
277 | 283 | |
278 | 284 | |
285 | def test_axis_info_compound(): | |
286 | assert [axis.direction for axis in CRS.from_epsg(3901).axis_info] == [ | |
287 | "north", | |
288 | "east", | |
289 | "up", | |
290 | ] | |
291 | ||
292 | ||
279 | 293 | def test_dunder_str(): |
280 | 294 | with pytest.warns(FutureWarning): |
281 | 295 | assert str(CRS({"init": "EPSG:4326"})) == CRS({"init": "EPSG:4326"}).srs |
489 | 503 | crs = CRS.from_epsg(26915) |
490 | 504 | assert repr(crs.coordinate_operation) == ( |
491 | 505 | "<Coordinate Operation: Conversion>\n" |
492 | "UTM zone 15N\n" | |
506 | "Name: UTM zone 15N\n" | |
507 | "Method: Transverse Mercator\n" | |
493 | 508 | "Area of Use:\n" |
494 | 509 | "- name: World - N hemisphere - 96°W to 90°W\n" |
495 | 510 | "- bounds: (-96.0, 0.0, -90.0, 84.0)" |
792 | 807 | ] |
793 | 808 | |
794 | 809 | |
810 | def test_axis_info_bound(): | |
811 | crs = CRS( | |
812 | "+proj=tmerc +lat_0=0 +lon_0=15 +k=0.9996 +x_0=2520000 +y_0=0 " | |
813 | "+ellps=intl +towgs84=-122.74,-34.27,-22.83,-1.884,-3.400,-3.030,-15.62" | |
814 | ) | |
815 | assert [axis.direction for axis in crs.axis_info] == ["east", "north"] | |
816 | ||
817 | ||
795 | 818 | def test_coordinate_operation_towgs84_missing(): |
796 | 819 | crs = CRS("epsg:3004") |
797 | 820 | assert crs.coordinate_operation.towgs84 == [] |
1238 | 1261 | def test_crs_equals__ignore_axis_order(): |
1239 | 1262 | with pytest.warns(FutureWarning): |
1240 | 1263 | assert CRS("epsg:4326").equals("+init=epsg:4326", ignore_axis_order=True) |
1264 | ||
1265 | ||
1266 | @pytest.mark.parametrize( | |
1267 | "crs_input", | |
1268 | [ | |
1269 | "+proj=utm +zone=15", | |
1270 | 26915, | |
1271 | "+proj=utm +zone=15 +towgs84=0,0,0", | |
1272 | "EPSG:26915+5717", | |
1273 | ], | |
1274 | ) | |
1275 | def test_utm_zone(crs_input): | |
1276 | assert CRS(crs_input).utm_zone == "15N" | |
1277 | ||
1278 | ||
1279 | @pytest.mark.parametrize("crs_input", ["+proj=tmerc", "epsg:4326"]) | |
1280 | def test_utm_zone__none(crs_input): | |
1281 | assert CRS(crs_input).utm_zone is None |
2 | 2 | import sys |
3 | 3 | import unittest |
4 | 4 | |
5 | import numpy as np | |
5 | 6 | import pytest |
7 | from numpy.testing import assert_almost_equal | |
6 | 8 | |
7 | 9 | from pyproj import Geod, Proj, pj_ellps, pj_list, transform |
8 | from pyproj.crs import CRSError | |
10 | from pyproj.exceptions import CRSError, ProjError | |
9 | 11 | |
10 | 12 | |
11 | 13 | class BasicTest(unittest.TestCase): |
395 | 397 | assert proj.crs.srs == "proj=lonlat type=crs" |
396 | 398 | |
397 | 399 | |
400 | def test_initialize_projparams_with_kwargs(): | |
401 | proj_mixed_args = Proj("+proj=utm +zone=10", ellps="WGS84") | |
402 | proj_positional = Proj("+proj=utm +zone=10 +ellps=WGS84") | |
403 | assert proj_mixed_args.is_exact_same(proj_positional) | |
404 | ||
405 | ||
398 | 406 | def test_equals_different_type(): |
399 | 407 | assert Proj("epsg:4326") != "" |
400 | 408 | |
411 | 419 | assert proj(0, 0, inverse=True, errcheck=True) == (0.0, -90.0) |
412 | 420 | |
413 | 421 | |
414 | if __name__ == "__main__": | |
415 | unittest.main() | |
422 | @pytest.mark.parametrize("radians", [False, True]) | |
423 | def test_get_factors__2d_input(radians): | |
424 | transformer = Proj(3857) | |
425 | longitude = np.array([[0, 1], [2, 3]]) | |
426 | latitude = np.array([[1, 2], [3, 4]]) | |
427 | if radians: | |
428 | longitude = np.radians(longitude) | |
429 | latitude = np.radians(latitude) | |
430 | factors = transformer.get_factors( | |
431 | longitude=longitude, latitude=latitude, radians=radians | |
432 | ) | |
433 | assert_almost_equal( | |
434 | factors.meridional_scale, [[1.0, 1.00015233], [1.00060954, 1.00137235]], | |
435 | ) | |
436 | assert_almost_equal( | |
437 | factors.parallel_scale, [[1.0, 1.00015233], [1.00060954, 1.00137235]], | |
438 | ) | |
439 | assert_almost_equal( | |
440 | factors.areal_scale, [[1.0, 1.00030468], [1.00121946, 1.00274658]], | |
441 | ) | |
442 | assert_almost_equal(factors.angular_distortion, [[0, 0], [0, 0]], decimal=5) | |
443 | assert_almost_equal( | |
444 | factors.meridian_parallel_angle, [[90, 90], [90, 90]], | |
445 | ) | |
446 | assert_almost_equal(factors.meridian_convergence, [[0, 0], [0, 0]]) | |
447 | assert_almost_equal( | |
448 | factors.tissot_semimajor, [[1.0, 1.00015233], [1.00060955, 1.00137235]], | |
449 | ) | |
450 | assert_almost_equal( | |
451 | factors.tissot_semiminor, [[1.0, 1.00015233], [1.00060953, 1.00137235]], | |
452 | ) | |
453 | assert_almost_equal( | |
454 | factors.dx_dlam, [[1, 1], [1, 1]], | |
455 | ) | |
456 | assert_almost_equal(factors.dx_dphi, [[0, 0], [0, 0]]) | |
457 | assert_almost_equal(factors.dy_dlam, [[0, 0], [0, 0]]) | |
458 | assert_almost_equal( | |
459 | factors.dy_dphi, [[1.0, 1.00015233], [1.00060954, 1.00137235]], | |
460 | ) | |
461 | ||
462 | ||
463 | def test_get_factors__nan_inf(): | |
464 | transformer = Proj(3857) | |
465 | factors = transformer.get_factors( | |
466 | longitude=[0, np.nan, np.inf, 0], latitude=[np.nan, 2, 2, np.inf] | |
467 | ) | |
468 | assert_almost_equal(factors.meridional_scale, [1, np.inf, np.inf, 1]) | |
469 | assert_almost_equal(factors.parallel_scale, [1, np.inf, np.inf, 1]) | |
470 | assert_almost_equal(factors.areal_scale, [1, np.inf, np.inf, 1]) | |
471 | assert_almost_equal(factors.angular_distortion, [0, np.inf, np.inf, 0]) | |
472 | assert_almost_equal(factors.meridian_parallel_angle, [90, np.inf, np.inf, 90]) | |
473 | assert_almost_equal(factors.meridian_convergence, [0.0, np.inf, np.inf, 0.0]) | |
474 | assert_almost_equal(factors.tissot_semimajor, [1, np.inf, np.inf, 1]) | |
475 | assert_almost_equal(factors.tissot_semiminor, [1, np.inf, np.inf, 1]) | |
476 | assert_almost_equal(factors.dx_dlam, [1, np.inf, np.inf, 1]) | |
477 | assert_almost_equal(factors.dx_dphi, [0.0, np.inf, np.inf, 0.0]) | |
478 | assert_almost_equal(factors.dy_dlam, [0.0, np.inf, np.inf, 0.0]) | |
479 | assert_almost_equal(factors.dy_dphi, [1, np.inf, np.inf, 1]) | |
480 | ||
481 | ||
482 | def test_get_factors__errcheck(): | |
483 | transformer = Proj(3857) | |
484 | with pytest.raises(ProjError): | |
485 | transformer.get_factors(longitude=40, latitude=70, errcheck=True, radians=True) | |
486 | ||
487 | ||
488 | def test_numpy_bool_kwarg(): | |
489 | # Issue 546 | |
490 | south = np.array(50) < 0 | |
491 | proj = Proj( | |
492 | proj="utm", zone=32, ellipsis="WGS84", datum="WGS84", units="m", south=south | |
493 | ) | |
494 | assert "south" not in proj.srs |
584 | 584 | def test_transformer_group__area_of_interest__invalid(aoi_data_directory): |
585 | 585 | with pytest.raises(ProjError): |
586 | 586 | TransformerGroup(4326, 2964, area_of_interest=(-136.46, 49.0, -60.72, 83.17)) |
587 | ||
588 | ||
589 | def test_transformer_equals(): | |
590 | assert Transformer.from_crs(28356, 7856) == Transformer.from_crs(28356, 7856) | |
591 | ||
592 | ||
593 | @pytest.mark.parametrize( | |
594 | "comparison", | |
595 | [Transformer.from_pipeline("+proj=pipeline +ellps=GRS80 +step +proj=cart"), 22], | |
596 | ) | |
597 | def test_transformer_not_equals(comparison): | |
598 | assert Transformer.from_crs(28356, 7856) != comparison | |
599 | ||
600 | ||
601 | @pytest.mark.parametrize( | |
602 | "pipeline_str", | |
603 | [ | |
604 | "+proj=pipeline +ellps=GRS80 +step +proj=cart", | |
605 | "+proj=pipeline +step +proj=unitconvert +xy_in=deg " | |
606 | "+xy_out=rad +ellps=GRS80 +step +proj=cart", | |
607 | ], | |
608 | ) | |
609 | def test_pipeline_transform(pipeline_str): | |
610 | trans = Transformer.from_pipeline(pipeline_str) | |
611 | assert_almost_equal( | |
612 | trans.transform(50, 25, 0), | |
613 | (3717892.6072086394, 4430811.87152035, 2679074.4628772778), | |
614 | ) | |
615 | ||
616 | ||
617 | @pytest.mark.parametrize( | |
618 | "pipeline_str", | |
619 | [ | |
620 | "+proj=pipeline +ellps=GRS80 +step +proj=cart", | |
621 | "+proj=pipeline +step +proj=unitconvert +xy_in=deg " | |
622 | "+xy_out=rad +ellps=GRS80 +step +proj=cart", | |
623 | ], | |
624 | ) | |
625 | def test_pipeline_itransform(pipeline_str): | |
626 | trans = Transformer.from_pipeline(pipeline_str) | |
627 | assert_almost_equal( | |
628 | list(trans.itransform([(50, 25, 0)])), | |
629 | [(3717892.6072086394, 4430811.87152035, 2679074.4628772778)], | |
630 | ) | |
631 | ||
632 | ||
633 | def test_pipeline_radian_transform_warning(): | |
634 | trans = Transformer.from_pipeline("+proj=pipeline +ellps=GRS80 +step +proj=cart") | |
635 | with pytest.warns(UserWarning): | |
636 | trans.transform(0.1, 0.1, 0, radians=True) |
0 | from array import array | |
1 | ||
2 | import numpy | |
3 | import pytest | |
4 | ||
5 | from pyproj.utils import _copytobuffer, _copytobuffer_return_scalar | |
6 | ||
7 | ||
8 | @pytest.mark.parametrize("in_data", [numpy.array(1), 1]) | |
9 | def test__copytobuffer_return_scalar(in_data): | |
10 | assert _copytobuffer_return_scalar(in_data) == (array("d", [1]), True, False, False) | |
11 | ||
12 | ||
13 | def test__copytobuffer_return_scalar__invalid(): | |
14 | with pytest.raises(TypeError): | |
15 | _copytobuffer_return_scalar("invalid") | |
16 | ||
17 | ||
18 | @pytest.mark.parametrize( | |
19 | "in_data, is_float, is_list, is_tuple", | |
20 | [ | |
21 | (numpy.array(1), True, False, False), | |
22 | (1, True, False, False), | |
23 | ([1], False, True, False), | |
24 | ((1,), False, False, True), | |
25 | ], | |
26 | ) | |
27 | def test__copytobuffer(in_data, is_float, is_list, is_tuple): | |
28 | assert _copytobuffer(in_data) == (array("d", [1]), is_float, is_list, is_tuple) | |
29 | ||
30 | ||
31 | def test__copytobuffer__numpy_array(): | |
32 | in_arr = numpy.array([1]) | |
33 | assert _copytobuffer(in_arr) == (in_arr.astype("d"), False, False, False) | |
34 | ||
35 | ||
36 | def test__copytobuffer__invalid(): | |
37 | with pytest.raises(TypeError): | |
38 | _copytobuffer("invalid") |