SciTools / cartopy

Cartopy - a cartographic python library with matplotlib support
https://scitools.org.uk/cartopy/docs/latest
BSD 3-Clause "New" or "Revised" License
1.44k stars 367 forks source link

`GeoAxes.set_boundary` failed in smaller extent #2175

Open ZhaJiMan opened 1 year ago

ZhaJiMan commented 1 year ago

Description

I want to use a circle bondary in a Plate Carrée map, and I found that in big extent (like set_global) it worked, but in smaller extent it failed. The same problem also occurred in a Lambert comformal map.

Code to reproduce

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import cartopy.crs as ccrs
from cartopy.feature import LAND, OCEAN

crs = ccrs.PlateCarree()
fig = plt.figure()
ax = fig.add_subplot(projection=crs)
ax.set_global()
ax.stock_img()

r = 0.5
t = np.linspace(0, 2 * np.pi, 100)
x = r * np.cos(t) + 0.5
y = r * np.sin(t) + 0.5
verts = np.column_stack([x, y])
path = Path(verts)

ax.set_boundary(path, ax.transAxes)
plt.show()

image

But the boundary would not show in [60, 130, 0, 60] range.

ax.set_extent([60, 130, 0, 60], crs=crs)

image

Full environment definition ### Operating system Windows 11 ### Cartopy version 0.21.0 ### conda list ``` # Name Version Build Channel _ipython_minor_entry_point 8.7.0 h8cf3c4a_0 conda-forge _py-xgboost-mutex 2.0 cpu_0 conda-forge ansicon 1.89.0 py39hcbf5309_6 conda-forge anyio 3.5.0 py39haa95532_0 defaults appdirs 1.4.4 pyh9f0ad1d_0 conda-forge argon2-cffi 21.3.0 pyhd3eb1b0_0 defaults argon2-cffi-bindings 21.2.0 py39h2bbff1b_0 defaults asttokens 2.2.1 pyhd8ed1ab_0 conda-forge attrs 22.1.0 pyh71513ae_1 conda-forge backcall 0.2.0 pyh9f0ad1d_0 conda-forge backports 1.0 pyhd8ed1ab_3 conda-forge backports.functools_lru_cache 1.6.4 pyhd8ed1ab_0 conda-forge bcrypt 3.2.2 py39ha55989b_1 conda-forge beautifulsoup4 4.11.1 py39haa95532_0 defaults blas 1.0 mkl defaults bleach 4.1.0 pyhd3eb1b0_0 defaults blessed 1.19.1 pyh95a074a_2 conda-forge blosc 1.21.1 h74325e0_3 conda-forge bokeh 2.4.3 pyhd8ed1ab_3 conda-forge boost-cpp 1.78.0 h9f4b32c_1 conda-forge bottleneck 1.3.5 py39hc266a54_1 conda-forge branca 0.6.0 pyhd8ed1ab_0 conda-forge brotli 1.0.9 hcfcfb64_8 conda-forge brotli-bin 1.0.9 hcfcfb64_8 conda-forge brotlipy 0.7.0 py39h2bbff1b_1003 https://repo.anaconda.com/pkgs/main bzip2 1.0.8 h8ffe710_4 conda-forge ca-certificates 2022.12.7 h5b45459_0 conda-forge cached-property 1.5.2 hd8ed1ab_1 conda-forge cached_property 1.5.2 pyha770c72_1 conda-forge cairo 1.16.0 hd694305_1014 conda-forge cartopy 0.21.0 py39h25ee47b_3 conda-forge certifi 2022.12.7 pyhd8ed1ab_0 conda-forge cffi 1.15.0 py39h2bbff1b_1 https://repo.anaconda.com/pkgs/main cfgrib 0.9.10.3 pyhd8ed1ab_0 conda-forge cfitsio 4.2.0 h9ebe7e4_0 conda-forge cftime 1.6.2 py39hc266a54_1 conda-forge charset-normalizer 2.0.4 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main click 8.1.3 win_pyhd8ed1ab_2 conda-forge click-plugins 1.1.1 py_0 conda-forge cligj 0.7.2 pyhd8ed1ab_1 conda-forge cloudpickle 2.2.0 pyhd8ed1ab_0 conda-forge cmarkgfm 0.8.0 py39ha55989b_2 conda-forge colorama 0.4.4 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main commonmark 0.9.1 py_0 conda-forge conda 4.12.0 py39haa95532_0 https://repo.anaconda.com/pkgs/main conda-content-trust 0.1.1 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main conda-package-handling 1.8.1 py39h8cc25b3_0 https://repo.anaconda.com/pkgs/main console_shortcut 0.1.1 4 https://repo.anaconda.com/pkgs/main contourpy 1.0.6 py39h1f6ef14_0 conda-forge cryptography 36.0.0 py39h21b164f_0 https://repo.anaconda.com/pkgs/main cuda 11.6.2 0 nvidia cuda-cccl 11.6.55 0 nvidia cuda-command-line-tools 11.6.2 0 nvidia cuda-compiler 11.6.2 0 nvidia cuda-cudart 11.6.55 0 nvidia cuda-cudart-dev 11.6.55 0 nvidia cuda-cuobjdump 11.6.124 0 nvidia cuda-cupti 11.6.124 0 nvidia cuda-cuxxfilt 11.6.124 0 nvidia cuda-libraries 11.6.2 0 nvidia cuda-libraries-dev 11.6.2 0 nvidia cuda-memcheck 11.8.86 0 nvidia cuda-nsight-compute 11.8.0 0 nvidia cuda-nvcc 11.6.124 0 nvidia cuda-nvdisasm 11.8.86 0 nvidia cuda-nvml-dev 11.6.55 0 nvidia cuda-nvprof 11.8.87 0 nvidia cuda-nvprune 11.6.124 0 nvidia cuda-nvrtc 11.6.124 0 nvidia cuda-nvrtc-dev 11.6.124 0 nvidia cuda-nvtx 11.6.124 0 nvidia cuda-nvvp 11.8.87 0 nvidia cuda-runtime 11.6.2 0 nvidia cuda-sanitizer-api 11.8.86 0 nvidia cuda-toolkit 11.6.2 0 nvidia cuda-tools 11.6.2 0 nvidia cuda-visual-tools 11.6.2 0 nvidia curl 7.86.0 heaf79c2_1 conda-forge cycler 0.11.0 pyhd8ed1ab_0 conda-forge cytoolz 0.12.0 py39ha55989b_1 conda-forge dask 2022.12.0 pyhd8ed1ab_0 conda-forge dask-core 2022.12.0 pyhd8ed1ab_0 conda-forge dataclasses 0.8 pyhc8e2a94_3 conda-forge debugpy 1.5.1 py39hd77b12b_0 defaults decorator 5.1.1 pyhd8ed1ab_0 conda-forge defusedxml 0.7.1 pyhd3eb1b0_0 defaults dill 0.3.6 pyhd8ed1ab_1 conda-forge distributed 2022.12.0 pyhd8ed1ab_0 conda-forge docutils 0.19 py39hcbf5309_1 conda-forge eccodes 2.27.1 hf38be0f_0 conda-forge entrypoints 0.4 py39haa95532_0 defaults et_xmlfile 1.0.1 py_1001 conda-forge executing 1.2.0 pyhd8ed1ab_0 conda-forge expat 2.5.0 h1537add_0 conda-forge fftw 3.3.9 h2bbff1b_1 defaults findlibs 0.0.2 pyhd8ed1ab_0 conda-forge fiona 1.8.22 py39h9e0966e_2 conda-forge flit-core 3.6.0 pyhd3eb1b0_0 defaults folium 0.13.0 pyhd8ed1ab_0 conda-forge font-ttf-dejavu-sans-mono 2.37 hab24e00_0 conda-forge font-ttf-inconsolata 3.000 h77eed37_0 conda-forge font-ttf-source-code-pro 2.038 h77eed37_0 conda-forge font-ttf-ubuntu 0.83 hab24e00_0 conda-forge fontconfig 2.14.1 hbde0cde_0 conda-forge fonts-conda-ecosystem 1 0 conda-forge fonts-conda-forge 1 0 conda-forge fonttools 4.38.0 py39ha55989b_1 conda-forge freeglut 3.2.2 h0e60522_1 conda-forge freetype 2.12.1 h546665d_1 conda-forge freexl 1.0.6 h67ca5e6_1 conda-forge fsspec 2022.11.0 pyhd8ed1ab_0 conda-forge future 0.18.2 pyhd8ed1ab_6 conda-forge gdal 3.5.3 py39h34c8707_8 conda-forge geopandas 0.12.1 pyhd8ed1ab_1 conda-forge geopandas-base 0.12.1 pyha770c72_1 conda-forge geos 3.11.1 h1537add_0 conda-forge geotiff 1.7.1 h4ffd875_4 conda-forge gettext 0.21.1 h5728263_0 conda-forge gpustat 1.0.0 pyhd8ed1ab_0 conda-forge h5py 3.7.0 nompi_py39hbc6f334_102 conda-forge hdf4 4.2.15 h1b1b6ef_5 conda-forge hdf5 1.12.2 nompi_h2a0e4a3_100 conda-forge heapdict 1.0.1 py_0 conda-forge icc_rt 2022.1.0 h6049295_2 defaults icu 70.1 h0e60522_0 conda-forge idna 3.3 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main importlib-metadata 5.1.0 pyha770c72_0 conda-forge importlib_metadata 5.1.0 hd8ed1ab_0 conda-forge importlib_resources 5.10.0 pyhd8ed1ab_0 conda-forge intel-openmp 2021.4.0 haa95532_3556 defaults ipdb 0.13.9 pyhd8ed1ab_0 conda-forge ipykernel 6.15.2 py39haa95532_0 defaults ipympl 0.8.7 pyhd3eb1b0_0 defaults ipython 8.7.0 pyh08f2357_0 conda-forge ipython_genutils 0.2.0 pyhd3eb1b0_1 defaults ipywidgets 7.6.5 pyhd3eb1b0_1 defaults jaraco.classes 3.2.3 pyhd8ed1ab_0 conda-forge jasper 2.0.33 h77af90b_0 conda-forge jedi 0.18.2 pyhd8ed1ab_0 conda-forge jinja2 3.1.2 pyhd8ed1ab_1 conda-forge jinxed 1.2.0 pyh95a074a_0 conda-forge joblib 1.2.0 pyhd8ed1ab_0 conda-forge jpeg 9e h8ffe710_2 conda-forge jplephem 2.18 pyh78acc04_0 conda-forge jsonschema 4.16.0 py39haa95532_0 defaults jupyter_client 7.4.7 py39haa95532_0 defaults jupyter_core 4.11.2 py39haa95532_0 defaults jupyter_server 1.18.1 py39haa95532_0 defaults jupyterlab_pygments 0.1.2 py_0 defaults jupyterlab_widgets 1.0.0 pyhd3eb1b0_1 defaults kealib 1.5.0 h61be68b_0 conda-forge keyring 23.11.0 py39hcbf5309_0 conda-forge kiwisolver 1.4.4 py39h1f6ef14_1 conda-forge krb5 1.19.3 h1176d77_0 conda-forge lcms2 2.14 h90d422f_0 conda-forge lerc 4.0.0 h63175ca_0 conda-forge libaec 1.0.6 h39d44d4_0 conda-forge libbrotlicommon 1.0.9 hcfcfb64_8 conda-forge libbrotlidec 1.0.9 hcfcfb64_8 conda-forge libbrotlienc 1.0.9 hcfcfb64_8 conda-forge libcublas 11.11.3.6 0 nvidia libcublas-dev 11.11.3.6 0 nvidia libcufft 10.9.0.58 0 nvidia libcufft-dev 10.9.0.58 0 nvidia libcurand 10.3.0.86 0 nvidia libcurand-dev 10.3.0.86 0 nvidia libcurl 7.86.0 heaf79c2_1 conda-forge libcusolver 11.4.1.48 0 nvidia libcusolver-dev 11.4.1.48 0 nvidia libcusparse 11.7.5.86 0 nvidia libcusparse-dev 11.7.5.86 0 nvidia libdeflate 1.14 hcfcfb64_0 conda-forge libffi 3.4.2 h8ffe710_5 conda-forge libgdal 3.5.3 h74b97fb_8 conda-forge libglib 2.74.1 he8f3873_1 conda-forge libiconv 1.17 h8ffe710_0 conda-forge libkml 1.3.0 hf2ab4e4_1015 conda-forge libnetcdf 4.8.1 nompi_h8c042bf_106 conda-forge libnpp 11.8.0.86 0 nvidia libnpp-dev 11.8.0.86 0 nvidia libnvjpeg 11.9.0.86 0 nvidia libnvjpeg-dev 11.9.0.86 0 nvidia libpng 1.6.39 h19919ed_0 conda-forge libpq 15.1 h04fd8be_1 conda-forge librttopo 1.1.0 he22b5cd_12 conda-forge libsodium 1.0.18 h62dcd97_0 defaults libspatialindex 1.9.3 h39d44d4_4 conda-forge libspatialite 5.0.1 h07bf483_22 conda-forge libsqlite 3.40.0 hcfcfb64_0 conda-forge libssh2 1.10.0 h680486a_3 conda-forge libtiff 4.4.0 h8e97e67_4 conda-forge libuv 1.40.0 he774522_0 defaults libwebp-base 1.2.4 h8ffe710_0 conda-forge libxcb 1.13 hcd874cb_1004 conda-forge libxgboost 1.7.1 cpu_h20390bd_0 conda-forge libxml2 2.10.3 hc3477c8_0 conda-forge libzip 1.9.2 hfed4ece_1 conda-forge libzlib 1.2.13 hcfcfb64_4 conda-forge lightgbm 3.3.3 py39h99910a6_1 conda-forge line_profiler 4.0.1 py39h748ffb7_0 conda-forge locket 1.0.0 pyhd8ed1ab_0 conda-forge lz4 4.0.2 py39hf617134_0 conda-forge lz4-c 1.9.3 h8ffe710_1 conda-forge m2w64-gcc-libgfortran 5.3.0 6 conda-forge m2w64-gcc-libs 5.3.0 7 conda-forge m2w64-gcc-libs-core 5.3.0 7 conda-forge m2w64-gmp 6.1.0 2 conda-forge m2w64-libwinpthread-git 5.0.0.4634.697f757 2 conda-forge mapclassify 2.4.3 pyhd8ed1ab_0 conda-forge mapie 0.5.0 pyhd8ed1ab_0 conda-forge markupsafe 2.1.1 py39ha55989b_2 conda-forge matplotlib-base 3.6.2 py39haf65ace_0 conda-forge matplotlib-inline 0.1.6 pyhd8ed1ab_0 conda-forge memory_profiler 0.61.0 pyhd8ed1ab_0 conda-forge menuinst 1.4.18 py39h59b6b97_0 https://repo.anaconda.com/pkgs/main metpy 1.3.1 pyhd8ed1ab_0 conda-forge missingno 0.4.2 py_1 conda-forge mistune 0.8.4 py39h2bbff1b_1000 defaults mkl 2021.4.0 haa95532_640 defaults mkl-service 2.4.0 py39h2bbff1b_0 defaults mkl_fft 1.3.1 py39h277e83a_0 defaults mkl_random 1.2.2 py39hf11a4ad_0 defaults more-itertools 9.0.0 pyhd8ed1ab_0 conda-forge msgpack-python 1.0.4 py39h1f6ef14_1 conda-forge msys2-conda-epoch 20160418 1 conda-forge munch 2.5.0 py_0 conda-forge munkres 1.1.4 pyh9f0ad1d_0 conda-forge nbclassic 0.4.8 py39haa95532_0 defaults nbclient 0.5.13 py39haa95532_0 defaults nbconvert 6.4.4 py39haa95532_0 defaults nbformat 5.5.0 py39haa95532_0 defaults nest-asyncio 1.5.5 py39haa95532_0 defaults netcdf4 1.6.2 nompi_py39h34fa13a_100 conda-forge networkx 2.8.8 pyhd8ed1ab_0 conda-forge notebook 6.5.2 py39haa95532_0 defaults notebook-shim 0.2.2 py39haa95532_0 defaults nsight-compute 2022.3.0.22 0 nvidia numexpr 2.8.4 py39h5b0cc5e_0 defaults numpy 1.23.4 py39h3b20f71_0 defaults numpy-base 1.23.4 py39h4da318b_0 defaults nvidia-ml-py 11.495.46 pyhd8ed1ab_0 conda-forge opencc 1.1.1 pypi_0 pypi openjpeg 2.5.0 hc9384bd_1 conda-forge openpyxl 3.0.10 py39ha55989b_2 conda-forge openssl 1.1.1t hcfcfb64_0 conda-forge packaging 21.3 pyhd3eb1b0_0 defaults pandas 1.5.1 py39hf11a4ad_0 defaults pandocfilters 1.5.0 pyhd3eb1b0_0 defaults paramiko 3.0.0 pyhd8ed1ab_0 conda-forge parso 0.8.3 pyhd8ed1ab_0 conda-forge partd 1.3.0 pyhd8ed1ab_0 conda-forge patsy 0.5.3 pyhd8ed1ab_0 conda-forge pcre2 10.40 h17e33f8_0 conda-forge pickleshare 0.7.5 py_1003 conda-forge pillow 9.2.0 py39h595c93f_3 conda-forge pint 0.20.1 pyhd8ed1ab_0 conda-forge pip 21.2.4 py39haa95532_0 https://repo.anaconda.com/pkgs/main pixman 0.40.0 h8ffe710_0 conda-forge pkginfo 1.9.2 pyhd8ed1ab_0 conda-forge pooch 1.6.0 pyhd8ed1ab_0 conda-forge poppler 22.11.0 ha6c1112_0 conda-forge poppler-data 0.4.11 hd8ed1ab_0 conda-forge portalocker 2.3.0 py39haa95532_0 defaults postgresql 15.1 h392df6f_1 conda-forge powershell_shortcut 0.0.1 3 https://repo.anaconda.com/pkgs/main prcoords 1.0.2 pypi_0 pypi proj 9.1.0 h3863b3b_0 conda-forge prometheus_client 0.14.1 py39haa95532_0 defaults prompt-toolkit 3.0.33 pyha770c72_0 conda-forge psutil 5.9.0 py39h2bbff1b_0 defaults pthread-stubs 0.4 hcd874cb_1001 conda-forge pure_eval 0.2.2 pyhd8ed1ab_0 conda-forge py-xgboost 1.7.1 cpu_py39ha538f94_0 conda-forge pycosat 0.6.3 py39h2bbff1b_0 https://repo.anaconda.com/pkgs/main pycparser 2.21 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main pygments 2.13.0 pyhd8ed1ab_0 conda-forge pygrib 2.1.4 py39hb97199f_6 conda-forge pyhdf 0.10.5 py39h1ab0bd0_1 conda-forge pykrige 1.7.0 py39ha55989b_1 conda-forge pynacl 1.5.0 py39h09fa780_2 conda-forge pyopenssl 22.0.0 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main pyparsing 3.0.9 py39haa95532_0 defaults pyproj 3.4.0 py39h9727d73_2 conda-forge pyrsistent 0.18.0 py39h196d8e1_0 defaults pyshp 2.3.1 pyhd8ed1ab_0 conda-forge pysocks 1.7.1 py39haa95532_0 https://repo.anaconda.com/pkgs/main python 3.9.12 h6244533_0 https://repo.anaconda.com/pkgs/main python-dateutil 2.8.2 pyhd3eb1b0_0 defaults python-eccodes 1.4.2 py39hc266a54_1 conda-forge python-fastjsonschema 2.16.2 py39haa95532_0 defaults python_abi 3.9 2_cp39 conda-forge pytorch 1.13.0 py3.9_cuda11.6_cudnn8_0 pytorch pytorch-cuda 11.6 h867d48c_0 pytorch pytorch-mutex 1.0 cuda pytorch pytz 2022.1 py39haa95532_0 defaults pywavelets 1.3.0 py39hc266a54_2 conda-forge pywin32 302 py39h2bbff1b_2 https://repo.anaconda.com/pkgs/main pywin32-ctypes 0.2.0 py39hcbf5309_1006 conda-forge pywinpty 2.0.2 py39h5da7b33_0 defaults pyyaml 6.0 py39ha55989b_5 conda-forge pyzmq 23.2.0 py39hd77b12b_0 defaults readme_renderer 37.3 pyhd8ed1ab_0 conda-forge requests 2.27.1 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main requests-toolbelt 0.10.1 pyhd8ed1ab_0 conda-forge rfc3986 2.0.0 pyhd8ed1ab_0 conda-forge rich 12.6.0 pyhd8ed1ab_0 conda-forge rtree 1.0.1 py39h09fdee3_1 conda-forge ruamel_yaml 0.15.100 py39h2bbff1b_0 https://repo.anaconda.com/pkgs/main scikit-learn 1.1.3 py39hd77b12b_0 defaults scipy 1.9.3 py39he11b74f_0 defaults seaborn 0.12.1 hd8ed1ab_0 conda-forge seaborn-base 0.12.1 pyhd8ed1ab_0 conda-forge send2trash 1.8.0 pyhd3eb1b0_1 defaults setuptools 61.2.0 py39haa95532_0 https://repo.anaconda.com/pkgs/main sgp4 2.21 py39hbd792c9_2 conda-forge shapely 1.8.5 py39h7c5f289_2 conda-forge six 1.16.0 pyhd3eb1b0_1 https://repo.anaconda.com/pkgs/main skyfield 1.45 pyh1a96a4e_0 conda-forge snakeviz 2.1.1 pyhd8ed1ab_0 conda-forge snappy 1.1.9 hfb803bf_2 conda-forge sniffio 1.2.0 py39haa95532_1 defaults sortedcontainers 2.4.0 pyhd8ed1ab_0 conda-forge soupsieve 2.3.2.post1 py39haa95532_0 defaults sqlite 3.40.0 hcfcfb64_0 conda-forge stack_data 0.6.2 pyhd8ed1ab_0 conda-forge statsmodels 0.13.5 py39hc266a54_2 conda-forge tblib 1.7.0 pyhd8ed1ab_0 conda-forge terminado 0.13.1 py39haa95532_0 defaults testpath 0.6.0 py39haa95532_0 defaults threadpoolctl 3.1.0 pyh8a188c0_0 conda-forge tiledb 2.11.3 h5689973_1 conda-forge tk 8.6.12 h8ffe710_0 conda-forge toolz 0.12.0 pyhd8ed1ab_0 conda-forge torchaudio 0.13.0 pypi_0 pypi torchdata 0.5.0 py39 pytorch torchtext 0.14.0 py39 pytorch torchvision 0.14.0 pypi_0 pypi tornado 6.2 py39h2bbff1b_0 defaults tqdm 4.63.0 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main traitlets 5.6.0 pyhd8ed1ab_0 conda-forge twine 4.0.2 pyhd8ed1ab_0 conda-forge typing-extensions 4.4.0 py39haa95532_0 defaults typing_extensions 4.4.0 py39haa95532_0 defaults tzdata 2022a hda174b7_0 https://repo.anaconda.com/pkgs/main ucrt 10.0.22621.0 h57928b3_0 conda-forge unicodedata2 15.0.0 py39ha55989b_0 conda-forge urllib3 1.26.8 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main vc 14.2 h21ff451_1 https://repo.anaconda.com/pkgs/main vs2015_runtime 14.32.31332 h1d6e394_9 conda-forge wcwidth 0.2.5 pyh9f0ad1d_2 conda-forge webencodings 0.5.1 py39haa95532_1 defaults websocket-client 0.58.0 py39haa95532_4 defaults wheel 0.37.1 pyhd3eb1b0_0 https://repo.anaconda.com/pkgs/main widgetsnbextension 3.5.2 py39haa95532_0 defaults win_inet_pton 1.1.0 py39haa95532_0 https://repo.anaconda.com/pkgs/main wincertstore 0.2 py39haa95532_2 https://repo.anaconda.com/pkgs/main winpty 0.4.3 4 defaults wrapt 1.15.0 py39ha55989b_0 conda-forge wrf-python 1.3.4.1 py39heacfe52_3 conda-forge xarray 2022.12.0 pyhd8ed1ab_0 conda-forge xerces-c 3.2.4 h63175ca_1 conda-forge xgboost 1.7.1 cpu_py39ha538f94_0 conda-forge xlrd 2.0.1 pyhd8ed1ab_3 conda-forge xorg-libxau 1.0.9 hcd874cb_0 conda-forge xorg-libxdmcp 1.1.3 hcd874cb_0 conda-forge xyzservices 2022.9.0 pyhd8ed1ab_0 conda-forge xz 5.2.6 h8d14728_0 conda-forge yaml 0.2.5 he774522_0 https://repo.anaconda.com/pkgs/main zeromq 4.3.4 hd77b12b_0 defaults zict 2.2.0 pyhd8ed1ab_0 conda-forge zipp 3.11.0 pyhd8ed1ab_0 conda-forge zlib 1.2.13 hcfcfb64_4 conda-forge zstd 1.5.2 h7755175_4 conda-forge ```
lgolston commented 1 year ago

I suspect this is a bug. Using your example, setting the first term in set_extent to be between 0 and 1 (for instance, 0.6 in the image below), progressively adjusts the boundary; at 1 the whole panel is blank, then >1 the boundary is ignored. That makes me think somehow ax.transAxes in set_boundary is affecting the call to set_extent. fig1_c

lgolston commented 1 year ago

A work around is to use data coordinates instead:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import cartopy.crs as ccrs
from cartopy.feature import LAND, OCEAN

crs = ccrs.PlateCarree()
fig = plt.figure()
ax = fig.add_subplot(projection=crs)
ax.stock_img()

theta = np.linspace(0, 2*np.pi, 100)
center, radius = [95, 30], 30
verts = np.vstack([np.sin(theta), np.cos(theta)]).T
circle = Path(verts * radius + center)

ax.set_extent([60, 130, 0, 60], crs=crs)
ax.set_boundary(circle, transform=ax.transData)

plt.show()

fig2

rcomer commented 9 months ago

Another workaround is to set up the axes with a different central longitude:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import cartopy.crs as ccrs

crs = ccrs.PlateCarree()
fig = plt.figure()
ax = fig.add_subplot(projection=ccrs.PlateCarree(central_longitude=90))
ax.set_extent([60, 130, 0, 60], crs=crs)
ax.stock_img()

r = 0.5
t = np.linspace(0, 2 * np.pi, 100)
x = r * np.cos(t) + 0.5
y = r * np.sin(t) + 0.5
verts = np.column_stack([x, y])
path = Path(verts)

ax.set_boundary(path, ax.transAxes)
plt.show()

image

ZhaJiMan commented 9 months ago

Thanks for workarounds. I found that ax.set_boundary will set the _original_path attribute for ax.patch and ax.spines['geo']. And in their _adjust_location methods there are

class _ViewClippedPathPatch(mpatches.PathPatch):
    def _adjust_location(self):
        if self.stale:
            self.set_path(self._original_path.clip_to_bbox(self.axes.viewLim))
            # Some places in matplotlib's transform stack cache the actual
            # path so we trigger an update by invalidating the transform.
            self._trans_wrap.invalidate()

class GeoSpine(mspines.Spine):
    def _adjust_location(self):
        if self.stale:
            self._path = self._original_path.clip_to_bbox(self.axes.viewLim)
            self._path = mpath.Path(self._path.vertices, closed=True)

The problem arises from the self._original_path.clip_to_bbox(self.axes.viewLim), which will clip the _original_path using ax.viewLim. The coordinates of _original_path are between 0.0 and 1.0 due to ax.transAxes transform, but the coordinates of ax.viewLim correspond to the values of extent. In my case where extents = [60, 130, 0, 60], the 0 to 1 circle is out of the range, so ax.patch and ax.spines['geo'] will have empty _path attributes making the spines disappear. This also exlains the half plot in @lgolston example and why changing central_longitude works.

In addition to using transData, I tried removing the clip_to_bbox line and it worked:

class _ViewClippedPathPatch(mpatches.PathPatch):
    def _adjust_location(self):
        if self.stale:
            # self.set_path(self._original_path.clip_to_bbox(self.axes.viewLim))
            self._path = self._original_path
            # Some places in matplotlib's transform stack cache the actual
            # path so we trigger an update by invalidating the transform.
            self._trans_wrap.invalidate()

class GeoSpine(mspines.Spine):
    def _adjust_location(self):
        if self.stale:
            # self._path = self._original_path.clip_to_bbox(self.axes.viewLim)
            self._path = self._original_path
            self._path = mpath.Path(self._path.vertices, closed=True)