From 1a4824496f17f2562991b323650aa304e340d7a4 Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Tue, 27 Aug 2024 14:37:26 +0200 Subject: [PATCH 1/9] add a projection for L2E this projection is relevant for mainland France, and is necessary because `cartopy.crs.epsg(27572)` does not work when used as a ``projection`` argument for geoaxes --- lib/cartopy/crs.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py index bc3541987..3f42ed3ce 100644 --- a/lib/cartopy/crs.py +++ b/lib/cartopy/crs.py @@ -1815,6 +1815,60 @@ def y_limits(self): return self._y_limits +class L2E(Projection): + """ + Lambert zone II projection (also known as "Lambert 2 étendue" in French) + (https://epsg.io/27572). + + """ + def __init__(self): + proj4_params = [('proj', 'lcc'), + ('lat_1', 46.8), + ('lat_0', 46.8), + ('lon_0', 0.0), + ('k_0', 0.99987742), + ('x_0', 600000.0), + ('y_0', 2200000.0), + ('pm', 'paris'), + ('units', 'm'), + ('no_defs', None)] + + globe = Globe(semimajor_axis='6378249.2', + semiminor_axis='6356515.0', + towgs84='-168,-60,320,0,0,0,0') + + super().__init__(proj4_params, globe=globe) + + x0, x1, y0, y1 = [0, 1.2e6, 1.6e6, 2.7e6] + + self.bounds = (x0, x1, y0, y1) + + self._boundary = sgeom.LineString( + [(x0, y0), (x0, y1), (x1, y1), (x1, y0), (x0, y0)] + ) + + self._x_limits = [x0, x1] + self._y_limits = [y0, y1] + + self._threshold = min(x1 - x0, y1 - y0) / 100. + + @property + def boundary(self): + return self._boundary + + @property + def x_limits(self): + return self._x_limits + + @property + def y_limits(self): + return self._y_limits + + @property + def threshold(self): + return self._threshold + + class LambertAzimuthalEqualArea(Projection): """ A Lambert Azimuthal Equal-Area projection. From aafe3f533aa59bd5844ac5a6111905aab076e50a Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Tue, 27 Aug 2024 15:06:40 +0200 Subject: [PATCH 2/9] add unit tests for L2E projection --- .../tests/crs/test_lambert_conformal.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/cartopy/tests/crs/test_lambert_conformal.py b/lib/cartopy/tests/crs/test_lambert_conformal.py index da754c4d9..5994c9478 100644 --- a/lib/cartopy/tests/crs/test_lambert_conformal.py +++ b/lib/cartopy/tests/crs/test_lambert_conformal.py @@ -114,3 +114,29 @@ def test_single_npole(self): assert_array_almost_equal(n_pole_crs.y_limits, expected_y, decimal=0) + + +class TestL2E: + def setup_class(self): + self.point_a = (48.13277955695077, 1.4868268900254693) + self.point_b = (48.68412929316207, -2.3188020040300126) + self.src_crs = ccrs.PlateCarree() + self.nan = float('nan') + + def test_default(self): + proj = ccrs.L2E() + res = proj.transform_point(*self.point_a, src_crs=self.src_crs) + np.testing.assert_array_almost_equal(res, + (536745.89626, 2348522.77899), + decimal=5) + res = proj.transform_point(*self.point_b, src_crs=self.src_crs) + np.testing.assert_array_almost_equal(res, + (257266.90019, 2419663.00145), + decimal=5) + + def test_nan(self): + proj = ccrs.L2E() + res = proj.transform_point(0.0, float('nan'), src_crs=self.src_crs) + assert np.all(np.isnan(res)) + res = proj.transform_point(float('nan'), 0.0, src_crs=self.src_crs) + assert np.all(np.isnan(res)) From 20f1a6ad6bcdfc0f067720eb5b2a9b64e018a195 Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Tue, 27 Aug 2024 18:04:57 +0200 Subject: [PATCH 3/9] fix swapped lat/lon in unit test --- lib/cartopy/tests/crs/test_lambert_conformal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cartopy/tests/crs/test_lambert_conformal.py b/lib/cartopy/tests/crs/test_lambert_conformal.py index 5994c9478..c146e23f8 100644 --- a/lib/cartopy/tests/crs/test_lambert_conformal.py +++ b/lib/cartopy/tests/crs/test_lambert_conformal.py @@ -118,8 +118,8 @@ def test_single_npole(self): class TestL2E: def setup_class(self): - self.point_a = (48.13277955695077, 1.4868268900254693) - self.point_b = (48.68412929316207, -2.3188020040300126) + self.point_a = (1.4868268900254693, 48.13277955695077) + self.point_b = (-2.3188020040300126, 48.68412929316207) self.src_crs = ccrs.PlateCarree() self.nan = float('nan') From 5d38ab39616b63c5df623aa5b7b066c224c50a5e Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Sat, 28 Sep 2024 16:04:22 +0200 Subject: [PATCH 4/9] rename class to LambertZoneII --- lib/cartopy/crs.py | 5 ++--- lib/cartopy/tests/crs/test_lambert_conformal.py | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py index 3f42ed3ce..ac3091664 100644 --- a/lib/cartopy/crs.py +++ b/lib/cartopy/crs.py @@ -1815,10 +1815,9 @@ def y_limits(self): return self._y_limits -class L2E(Projection): +class LambertZoneII(Projection): """ - Lambert zone II projection (also known as "Lambert 2 étendue" in French) - (https://epsg.io/27572). + Lambert zone II (extended) projection (https://epsg.io/27572). """ def __init__(self): diff --git a/lib/cartopy/tests/crs/test_lambert_conformal.py b/lib/cartopy/tests/crs/test_lambert_conformal.py index c146e23f8..a8960d037 100644 --- a/lib/cartopy/tests/crs/test_lambert_conformal.py +++ b/lib/cartopy/tests/crs/test_lambert_conformal.py @@ -116,7 +116,7 @@ def test_single_npole(self): decimal=0) -class TestL2E: +class TestLambertZoneII: def setup_class(self): self.point_a = (1.4868268900254693, 48.13277955695077) self.point_b = (-2.3188020040300126, 48.68412929316207) @@ -124,7 +124,7 @@ def setup_class(self): self.nan = float('nan') def test_default(self): - proj = ccrs.L2E() + proj = ccrs.LambertZoneII() res = proj.transform_point(*self.point_a, src_crs=self.src_crs) np.testing.assert_array_almost_equal(res, (536745.89626, 2348522.77899), @@ -135,7 +135,7 @@ def test_default(self): decimal=5) def test_nan(self): - proj = ccrs.L2E() + proj = ccrs.LambertZoneII() res = proj.transform_point(0.0, float('nan'), src_crs=self.src_crs) assert np.all(np.isnan(res)) res = proj.transform_point(float('nan'), 0.0, src_crs=self.src_crs) From 6c61a5c71491a022974188fb5831e81c8474e476 Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Sat, 28 Sep 2024 16:05:25 +0200 Subject: [PATCH 5/9] update expected values in test as this is due to using PlateCarree instead of WGS84 see https://github.com/SciTools/cartopy/pull/2427#pullrequestreview-2331771659 --- lib/cartopy/tests/crs/test_lambert_conformal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cartopy/tests/crs/test_lambert_conformal.py b/lib/cartopy/tests/crs/test_lambert_conformal.py index a8960d037..1ff2ac3b2 100644 --- a/lib/cartopy/tests/crs/test_lambert_conformal.py +++ b/lib/cartopy/tests/crs/test_lambert_conformal.py @@ -127,11 +127,11 @@ def test_default(self): proj = ccrs.LambertZoneII() res = proj.transform_point(*self.point_a, src_crs=self.src_crs) np.testing.assert_array_almost_equal(res, - (536745.89626, 2348522.77899), + (536690.18620, 2348515.62248), decimal=5) res = proj.transform_point(*self.point_b, src_crs=self.src_crs) np.testing.assert_array_almost_equal(res, - (257266.90019, 2419663.00145), + (257199.57387, 2419655.71471), decimal=5) def test_nan(self): From 950b22041f738f3e393d75468f0839847f13caf1 Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Sat, 28 Sep 2024 17:56:31 +0200 Subject: [PATCH 6/9] add test image for LambertZoneII --- .../test_global_map_LambertZoneII.png | Bin 0 -> 6293 bytes lib/cartopy/tests/mpl/test_mpl_integration.py | 1 + 2 files changed, 1 insertion(+) create mode 100644 lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/test_global_map_LambertZoneII.png diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/test_global_map_LambertZoneII.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/test_global_map_LambertZoneII.png new file mode 100644 index 0000000000000000000000000000000000000000..14e55c694c97ee85d8fc2f22e151c3e41235a203 GIT binary patch literal 6293 zcmcIp_dk_k|33$DNJfOr6S9&O*&LgYEre{6m94@N$;{q+ltgxkV~-?MvO=;qg^*-? zKj(RV`u+ir7l+q{*@!>~*KReIir-WTF{sN;AP zc(skUQvJIu#O!RnWo`7!vSykytKQ$!))HlXu17Db%bs>CQH9+m#_D1dDaBLewosu6 z^3MLIeC?BRU!KPbaXlvNNJmki zY}qByF_AO>^9u`0PRd1tn6i<~B3_5(?Ck8BxjCD<&({JlqKxN~Z(NRwj@F){wRIY+ zU@_!N8C0~{!8*M$qot=Ws;Z)TZT7}_RE9B@n3|eeT|=Y&8H@DR#J$RlcOOfN#HmDn zfAsiMK>Yf4BRW5cfI_68cXfVlPRQ{SbJOlu&2O#2tt)>Lva+I;o>I)Vg%I-a@hMhX zHVZx6cL{s?v=hE)qiy$woyDZQR}im_?=@M5X_YrMWg~P00s?AZ+$tNPJ%3(NKtLcl zJ>6+;t>5wY(f|?Gp+8+=WMm}vrq`dJ7Kgh-I(KK6r>1z>*&lz(lh+{*ZSTKu zJCEC9EVHwa!1MGZkc^z1)6dWEhPJkt&s~RtvGvvFKR-ASb>6G`U)T5In(r7HsXV1* zdm(K5KHgk_yTSaXwY4=Z4UJM9t8C&+=XJXwBrhKydvI{@&i?+3{(dckGJ8me*Q#;s5$v+qkgpWt;JrB^W{_q_ zx45{7KisEJpLR!X-4T--xKi1qDA;nqZqXVv)ju-MWkA%$j|=Fwb9A&FeyQg)^6G-V zfx+zh`oI3X2Kzob{Pp?wv0J;lkLLdRNU>B{Hb?dM_a6qsgFU>wl%nabvi=(zzIXer zi$YM4+|68>$o%|#)k$?79W^^U&PKmqC;ff>T1sEB+0uR#MQU-XB{y?Cjt=hE-5pxW zkc*3`di2+`{B}J>MMZ_Wwzi6k3;*HX`q+YuR1U>h<(-}pCj$JcBkxNGh7i96I=OK&G9K)k}x>< zRCTi1f190E?omYAouI!NsTmpRgNKD&q9dC*G69L-zkhf7R%N~0C)g_EB~2U}@+0t% z1p#J#tg__$cXKin3hn6VIMEU)eUY5_>#Dc+-yQo2oS)!TlPWARC94+foCr&#kpFWE zH?+Gtba&{5w)f%gUH!5V9iwRDvdcL)xuphr*n+j(+}yN(4%+B^a(IufuC88KSy6|8 zy!iO>qobQr<=D{o1}{=X;7%|1Uga$#qrs+t-zdc1#&{C!4~0PHyG=C?;-3%cNY2c3 z9u|Bf`99{N(xpq699)M+$CWX@zkXDC&Qdjd{dO?G+1c4?bK;GtO&1E<>w>+V zo#>Yi`y9yp`spBC?*%z-?x)1(7?oia)o0A6txSdmy1M@U5}QAov&hb#jeO~A;P5e- zcVT7*Lqf?ax>v|B&>c-ripY@*G+Wbmi83NtI63||{L1KxJ`b%o9E5lXVtP0iE%;I; znr`^HCjG|`AJBypKR9J&bBxPP6hcBmI8g*hG;{=`jK7eil$5@?d3Gs%=gYS)FX=n_B^|c*j>tU*H=+dNy_v4 z^+Pr)GO}R2*3kfiL0snM&U!!{<2Kh7NlQ!1>2vXV&l;hkvZ0=y!ZpWFoCtjD0d7#e zxjPhYR_~^*7RM^)Bbj)OfqY?eQ@bxsFs+d`%a#UN>a{ha;OXbbji6;@ywTm={X(Fd z-Mr;d2I5PpK}oSd_tLlF1V~?r?bb~DJMY!=?_-%r6r2u4@88BKL*;kxEcVSVEQGa( zl4x3-zelVg*kHt$!XO{ir2RBBB0e$kae>lPo304zm*wSMgGFkCg(_!DHEjpl#)`8d z+O06==FHF&RE&&dq3zh>Vop1I`&sDtlt!6REoLeXNUMbZ7W%=TpRv73+)4$yGgnM=I2*yCb3NibJ6MI?yRrM%3^l{0Cv7LcyU7qKf8F%0aI!?w=rIO0AUn@ zdZGwVfe$37q|E;QEZi^A|fe?rlzJw$YTZ*!z#;IcB?YH-HIyb7lg_L>RQToBf`Ef)%xgQ`(40qu9l-6 z&E1v3POXt^wZaqBDO~AuGqJ(|G0$kp&QOo!3bZ;5Fanrb2JRWb;VeT}qobqmu6}(! zTw|~4>ErVpDsd!Fw3k0rn?)nd%-dTO>Azv~nuh!47q8Et&agM+fs1Xt@OBW7F!2>bk z3-tEEzkjxESY*2F!|O-K$H0OKP`zDU$}ZC_Ebtf6YHsedRDFaW^zCFR6xxhJ@D=`R)T*OaIv?hd=CLEAhR~_58K9wSy%( zY{exdwjbgzsowE*u+*uk5X%~T_EL0KgW`vwp&=Dw;;rlL&}Ao?Simn`$bIw4;d-$y z4+??re}{ogmHYSa??TPfAf!BI+OE}i7dsk^6^p;9aMb0Y-3wmKd!ks-He6~T?6YRL z;w=TFSJC1(4s5~9!h#f)G5KJ^5>5W$SB~C4(FIS*a0-?vXlr&pJ~F-(vfkca37<7u zXyce4thMLpF2pxlhH6Rk6X;4~^5lc%mOkgX@4QXlt9dz(_K}T{BWW|87$TBut&xqwyNBxwn6XAu+>h1P44b^Qs-qFIbbf6u3QBwq5Hun(viulTBjVy` z<^ny*yassj@a>xkv$QWc9Bw{0>|(4DN%1o@DqZyMdEd>6CjeEmMR9V8jhqe~{A&;5 z9mTwsw17l7L`2R*ucr&!h7VsBzT#+rL}C~F(v+U-&&G=XXoC`no9%oGP+e5%Uma=d{>19ZtM8Z zw5A0`tq7gZx}L${syB+9JPeJJ2tJWvW@hFr4b4d99Tm&^rGTB__?Z{De-WZw75LA$ zw9neOOMrj?5lVcn11KO8a*>>ztPYPl?@L34I9Mr)o0*xxUe-)iw;+RS7pUCb-IY~T zWDe4pdDdd45G}4w$GpJsdt(*bMY-d@ zYH(Nt=Je!P*zc!#x!D^s;9&iMp1Yx`*+61_&I5z^ z-V(@!kU*CsDNxShl?V#dy$C`Acx5CZ!YC*po0^+v*Vg!ac>6m%Fl{)0(;*4;47TdU zeM}qDT6-Rw?@Qi6LTYNeA%}K;!|41b^C8tJ4~`P`YtG(A0?kat)$x;1Uso5Ap%pHF zG)sx!d;AnhG597qIk`tqRYrLz@b|LA=g*uu1KZ_<58vVG?)v6~i9pr6PcN}{DUJ*e zTYb)zT^W7NgjWHw5BKvM8z;)e;2uz}B(bWU$Z8=V3BU-v9igJ84v`By%=cRU6cG`D z0oA@W`;=`CIM<=HyW&6F!N!G{ByMcD>~4(H)H)0(=E((mtbV-=tv$CgSoALFSPDAy zso1^Ie2Aw>l@$^cto_8}4_zPo`bZHeX=z!FrQE&?AE*g1pqJoO5uj~ir2Kwrfp`P= z)6Z3Mg_pMg7%Q>9UcA>%BvU3p1XOIg9q=XAWvVd+T&8;En5IS4)X@5#s6#))&hBn8 z$YqBC15;Ctyx) z`lZq5UTL3m^3<8);$ouU2_FBG4 z&M2zB_BGS)t#z-U_^h**F3_Z_SI`QBM zIz-y7iF^QN{Hy>7`7Aeg3AeL6pdkRw``hl#dxp64<4GLs{H8TTfEE}- zL)ugU3qBtW9j(M33_UF^T278t?HRKIup2qCQqk{^b|R?9h-S;_8QCX_+a^|-hs|zV z;@&H|-&=#(=mjm6`%lHZhN8JDz-d>&kR;{43ZN{^oKYqKyklJ(65CdrhZI zq(FsE>RnUXp4<+(S<*R$^V2gok4a2S>h5gkAAC4E~=IcSwn8{BnZ^7wJd)+j!Mx~+rctq z)z)4E*V0xJe{`d0a0cQY5go0hs7L^26Z{DGhegkqhOZ6>ZowCf3N8c%1;w4|`TUs@ zz|?h=RsOYcH27GsmPlb?VH72$_}*Mb_Q07iBp^dawQUa-J^fQK86cTv;)0JjPWJ0t zt-ls)tW4Gm5-DJ`waRW8ypDBm zb=|eFsY#|(^I9}p&_M`T5b!#2KY~vKJ@4NySX*;$DU2Vvp`*i%*!>)Qk`xscRV>g` z-tzCKGD^d`ZiM!7ZU_zT#>;^)sZinS>sF6fsUZtd@f<8Zj)=jqy@I668ysAy@!fcOvX z)A|0|T&| z<9{FFM)|CPjS!vk^{alJ>*T&)36qFjgvP`&)+A#&_aOzs14ej}SA^q8X}HjrF3tM6 zALyBxIVa+me?K|NgwU#yw2pkCl|k^vEEZ5S`le%)tOcKx(`1s;;a$-XWNf?`5A(b`tSe}#{faWM@sMwZMkb`Yj zLLQVI&J7I><3=DI2g+gKA@=Syjjr^`*47s0&(EpY9|9y@AMqj%3WVXhOFEQ+5l|1L zY;Jy@sVOZXAp};)T+*;s#qGW#eWX%wpMjkC!Rhgz0nfPGnqrR*Jb*(B037t76RAgn z1T8Hs>pT~4v@DETuI@d^1b2eWhvqO@^W;oQOH&&v(c#X}QU!Seb3QHr9d?BGTo)-t zgzT%*(gLWVL^P_-wuhp$uNo!p{-YQM5lJu*1yTTK9`tvSKB@fPqe-^2#ugT_V|RjC zAg3_ql?VU8<)cA&Sx}Jj^l+>-e`vJ|xUEGnRW@LEg_`STcEs?oAxyNsx%lzbIT#22 zc79{#TJgfAL;6=!XkDEsyu|>0dvq)o%G<(`^al+SXRx&RX^l&`Fam?~-OSf7#SgBN z@q=sZL_CbB4a7ScKxo9!QM73xt^3Wk6TIIm|3BZwO!Ysya76hK`OzsXO71fJp8=tv Ma#OiN(dzO40p?}O^#A|> literal 0 HcmV?d00001 diff --git a/lib/cartopy/tests/mpl/test_mpl_integration.py b/lib/cartopy/tests/mpl/test_mpl_integration.py index 302505d99..fbf971c14 100644 --- a/lib/cartopy/tests/mpl/test_mpl_integration.py +++ b/lib/cartopy/tests/mpl/test_mpl_integration.py @@ -172,6 +172,7 @@ def test_simple_global(): pytest.param((ccrs.InterruptedGoodeHomolosine, dict(emphasis='land')), id='InterruptedGoodeHomolosine'), ccrs.LambertCylindrical, + ccrs.LambertZoneII, pytest.param((ccrs.Mercator, dict(min_latitude=-85, max_latitude=85)), id='Mercator'), ccrs.Miller, From bb49798c6bc9fcaa6ff6f59a5db70c8b557b8ab1 Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Mon, 30 Sep 2024 17:53:59 +0200 Subject: [PATCH 7/9] fix CRS used to determine bounds --- lib/cartopy/crs.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py index ac3091664..1e1b8cbfe 100644 --- a/lib/cartopy/crs.py +++ b/lib/cartopy/crs.py @@ -685,7 +685,9 @@ def __init__(self, *args, **kwargs): y1 = self.area_of_use.north lons = np.array([x0, x0, x1, x1]) lats = np.array([y0, y1, y1, y0]) - points = self.transform_points(self.as_geodetic(), lons, lats) + points = self.transform_points( + PlateCarree().as_geodetic(), lons, lats + ) x = points[:, 0] y = points[:, 1] self.bounds = (x.min(), x.max(), y.min(), y.max()) From 02d884215aac742c689f6cf385c944378a43eb67 Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Mon, 30 Sep 2024 17:54:52 +0200 Subject: [PATCH 8/9] update docstring to mention its geographical relevance --- lib/cartopy/crs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py index 1e1b8cbfe..c0fd8c58f 100644 --- a/lib/cartopy/crs.py +++ b/lib/cartopy/crs.py @@ -1819,7 +1819,8 @@ def y_limits(self): class LambertZoneII(Projection): """ - Lambert zone II (extended) projection (https://epsg.io/27572). + Lambert zone II (extended) projection (https://epsg.io/27572), a + legacy projection that covers hexagonal France and Corsica. """ def __init__(self): From 871222c04c7100782d117a60e3c4f5aa2877c39e Mon Sep 17 00:00:00 2001 From: Thibault Hallouin Date: Mon, 30 Sep 2024 17:55:37 +0200 Subject: [PATCH 9/9] rely on EPSG code but redefine bounds manually --- lib/cartopy/crs.py | 49 ++---------------- .../test_global_map_LambertZoneII.png | Bin 6293 -> 6396 bytes 2 files changed, 5 insertions(+), 44 deletions(-) diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py index c0fd8c58f..600f8ac24 100644 --- a/lib/cartopy/crs.py +++ b/lib/cartopy/crs.py @@ -18,6 +18,7 @@ import warnings import numpy as np +import pyproj from pyproj import Transformer from pyproj.exceptions import ProjError import shapely.geometry as sgeom @@ -1824,51 +1825,11 @@ class LambertZoneII(Projection): """ def __init__(self): - proj4_params = [('proj', 'lcc'), - ('lat_1', 46.8), - ('lat_0', 46.8), - ('lon_0', 0.0), - ('k_0', 0.99987742), - ('x_0', 600000.0), - ('y_0', 2200000.0), - ('pm', 'paris'), - ('units', 'm'), - ('no_defs', None)] - - globe = Globe(semimajor_axis='6378249.2', - semiminor_axis='6356515.0', - towgs84='-168,-60,320,0,0,0,0') - - super().__init__(proj4_params, globe=globe) - - x0, x1, y0, y1 = [0, 1.2e6, 1.6e6, 2.7e6] - - self.bounds = (x0, x1, y0, y1) + crs = pyproj.CRS.from_epsg(27572) + super().__init__(crs.to_wkt()) - self._boundary = sgeom.LineString( - [(x0, y0), (x0, y1), (x1, y1), (x1, y0), (x0, y0)] - ) - - self._x_limits = [x0, x1] - self._y_limits = [y0, y1] - - self._threshold = min(x1 - x0, y1 - y0) / 100. - - @property - def boundary(self): - return self._boundary - - @property - def x_limits(self): - return self._x_limits - - @property - def y_limits(self): - return self._y_limits - - @property - def threshold(self): - return self._threshold + # Projected bounds from https://epsg.io/27572 + self.bounds = [-5242.32, 1212512.16, 1589155.51, 2706796.21] class LambertAzimuthalEqualArea(Projection): diff --git a/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/test_global_map_LambertZoneII.png b/lib/cartopy/tests/mpl/baseline_images/mpl/test_mpl_integration/test_global_map_LambertZoneII.png index 14e55c694c97ee85d8fc2f22e151c3e41235a203..c2ea22e45ef63986126c5b4e0c12ef486989efde 100644 GIT binary patch literal 6396 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 Ma#OiN(dzO40p?}O^#A|>