From 65ef3bc62538e8048013d7161a5d215ce265bc56 Mon Sep 17 00:00:00 2001 From: Robert Coup Date: Tue, 27 Jan 2015 17:15:14 +1300 Subject: [PATCH] Handle bounds reprojections which cross the anti-meridian. #2648 When doing an envelope-points reprojection to a geographic CS, check the points stay in clockwise order. Otherwise expand the resulting bounds to include the world. Includes visual test. Cairo tests aren't finding differences, but the renderer is doing the right thing. --- src/proj_transform.cpp | 58 +++- tests/python_tests/projection_test.py | 36 ++- tests/python_tests/utilities.py | 8 + ...ian-bbox-1000-1000-1.0-grid-reference.json | 306 ++++++++++++++++++ ...ian-bbox-1000-1000-2.0-grid-reference.json | 286 ++++++++++++++++ ...idian-bbox-1000-1000-1.0-agg-reference.png | Bin 0 -> 938 bytes ...ian-bbox-1000-1000-1.0-cairo-reference.png | Bin 0 -> 2203 bytes ...idian-bbox-1000-1000-2.0-agg-reference.png | Bin 0 -> 1974 bytes ...ian-bbox-1000-1000-2.0-cairo-reference.png | Bin 0 -> 2414 bytes .../visual_tests/styles/antimeridian-bbox.xml | 93 ++++++ 10 files changed, 777 insertions(+), 10 deletions(-) create mode 100644 tests/visual_tests/grids/antimeridian-bbox-1000-1000-1.0-grid-reference.json create mode 100644 tests/visual_tests/grids/antimeridian-bbox-1000-1000-2.0-grid-reference.json create mode 100644 tests/visual_tests/images/antimeridian-bbox-1000-1000-1.0-agg-reference.png create mode 100644 tests/visual_tests/images/antimeridian-bbox-1000-1000-1.0-cairo-reference.png create mode 100644 tests/visual_tests/images/antimeridian-bbox-1000-1000-2.0-agg-reference.png create mode 100644 tests/visual_tests/images/antimeridian-bbox-1000-1000-2.0-cairo-reference.png create mode 100644 tests/visual_tests/styles/antimeridian-bbox.xml diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 95776fc12..37ca8d703 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -219,6 +219,8 @@ bool proj_transform::backward (box2d & box) const return true; } +/* Returns points in clockwise order. This allows us to do anti-meridian checks. + */ void envelope_points(std::vector< coord > & coords, box2d& env, int points) { double width = env.width(); @@ -236,15 +238,32 @@ void envelope_points(std::vector< coord > & coords, box2d& env double xstep = width / steps; double ystep = height / steps; - for (int i=0; i<=steps; i++) { - coords.push_back(coord(env.minx() + i * xstep, env.miny())); - coords.push_back(coord(env.minx() + i * xstep, env.maxy())); + coords.resize(points); + for (int i=0; iright + coords[i] = coord(env.minx() + i * xstep, env.maxy()); + // right: top>bottom + coords[i + steps] = coord(env.maxx(), env.maxy() - i * ystep); + // bottom: right>left + coords[i + steps * 2] = coord(env.maxx() - i * xstep, env.miny()); + // left: bottom>top + coords[i + steps * 3] = coord(env.minx(), env.miny() + i * ystep); + } +} +/* determine if an ordered sequence of coordinates is in clockwise order */ +bool is_clockwise(const std::vector< coord > & coords) +{ + int n = coords.size(); + coord c1, c2; + double a = 0.0; + + for (int i=0; i(env.minx(), env.miny() + i * ystep)); - coords.push_back(coord(env.maxx(), env.miny() + i * ystep)); - } + return a <= 0.0; } box2d calculate_bbox(std::vector > & points) { @@ -276,7 +295,7 @@ bool proj_transform::backward(box2d& env, int points) const } std::vector > coords; - envelope_points(coords, env, points); + envelope_points(coords, env, points); // this is always clockwise double z; for (std::vector >::iterator it = coords.begin(); it!=coords.end(); ++it) { @@ -287,6 +306,16 @@ bool proj_transform::backward(box2d& env, int points) const } box2d result = calculate_bbox(coords); + if (is_source_longlat_ && !is_clockwise(coords)) { + /* we've gone to a geographic CS, and our clockwise envelope has + * changed into an anticlockwise one. This means we've crossed the antimeridian, and + * need to expand the X direction to +/-180 to include all the data. Once we can deal + * with multiple bboxes in queries we can improve. + */ + double miny = result.miny(); + result.expand_to_include(-180.0, miny); + result.expand_to_include(180.0, miny); + } env.re_center(result.center().x, result.center().y); env.height(result.height()); @@ -306,7 +335,7 @@ bool proj_transform::forward(box2d& env, int points) const } std::vector > coords; - envelope_points(coords, env, points); + envelope_points(coords, env, points); // this is always clockwise double z; for (std::vector >::iterator it = coords.begin(); it!=coords.end(); ++it) { @@ -318,6 +347,17 @@ bool proj_transform::forward(box2d& env, int points) const box2d result = calculate_bbox(coords); + if (is_dest_longlat_ && !is_clockwise(coords)) { + /* we've gone to a geographic CS, and our clockwise envelope has + * changed into an anticlockwise one. This means we've crossed the antimeridian, and + * need to expand the X direction to +/-180 to include all the data. Once we can deal + * with multiple bboxes in queries we can improve. + */ + double miny = result.miny(); + result.expand_to_include(-180.0, miny); + result.expand_to_include(180.0, miny); + } + env.re_center(result.center().x, result.center().y); env.height(result.height()); env.width(result.width()); diff --git a/tests/python_tests/projection_test.py b/tests/python_tests/projection_test.py index e45b37da4..5c6bf62e0 100644 --- a/tests/python_tests/projection_test.py +++ b/tests/python_tests/projection_test.py @@ -5,7 +5,7 @@ from nose.tools import * import mapnik import random import math -from utilities import run_all +from utilities import run_all, assert_box2d_almost_equal # Tests that exercise map projections. @@ -114,5 +114,39 @@ def test_proj_transform_between_init_and_literal(): eq_(math.fabs(coord.y - lon_lat_coord4.y) < 1,True) +# Github Issue #2648 +def test_proj_antimeridian_bbox(): + # this is logic from feature_style_processor::prepare_layer() + PROJ_ENVELOPE_POINTS = 20 # include/mapnik/config.hpp + + prjGeog = mapnik.Projection('+init=epsg:4326') + prjProj = mapnik.Projection('+init=epsg:2193') + prj_trans_fwd = mapnik.ProjTransform(prjProj, prjGeog) + prj_trans_rev = mapnik.ProjTransform(prjGeog, prjProj) + + # bad = mapnik.Box2d(-177.31453250437079, -62.33374815225163, 178.02778363316355, -24.584597490955804) + better = mapnik.Box2d(-180.0, -62.33374815225163, 180.0, -24.584597490955804) + + buffered_query_ext = mapnik.Box2d(274000, 3087000, 3327000, 7173000) + fwd_ext = prj_trans_fwd.forward(buffered_query_ext, PROJ_ENVELOPE_POINTS) + assert_box2d_almost_equal(fwd_ext, better) + + # check the same logic works for .backward() + ext = mapnik.Box2d(274000, 3087000, 3327000, 7173000) + rev_ext = prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS) + assert_box2d_almost_equal(rev_ext, better) + + # checks for not being snapped (ie. not antimeridian) + normal = mapnik.Box2d(148.766759749,-60.1222810238,159.95484893,-24.9771195151) + buffered_query_ext = mapnik.Box2d(274000, 3087000, 276000, 7173000) + fwd_ext = prj_trans_fwd.forward(buffered_query_ext, PROJ_ENVELOPE_POINTS) + assert_box2d_almost_equal(fwd_ext, normal) + + # check the same logic works for .backward() + ext = mapnik.Box2d(274000, 3087000, 276000, 7173000) + rev_ext = prj_trans_rev.backward(ext, PROJ_ENVELOPE_POINTS) + assert_box2d_almost_equal(rev_ext, normal) + + if __name__ == "__main__": exit(run_all(eval(x) for x in dir() if x.startswith("test_"))) diff --git a/tests/python_tests/utilities.py b/tests/python_tests/utilities.py index 9d413a97f..e7ee26b6d 100644 --- a/tests/python_tests/utilities.py +++ b/tests/python_tests/utilities.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin +from nose.tools import assert_almost_equal import os, sys, inspect, traceback import mapnik @@ -86,3 +87,10 @@ def side_by_side_image(left_im, right_im): im.blend(0, 0, left_im, 1.0) im.blend(left_im.width() + 1, 0, right_im, 1.0) return im + +def assert_box2d_almost_equal(a, b, msg=None): + msg = msg or ("%r != %r" % (a, b)) + assert_almost_equal(a.minx, b.minx, msg=msg) + assert_almost_equal(a.maxx, b.maxx, msg=msg) + assert_almost_equal(a.miny, b.miny, msg=msg) + assert_almost_equal(a.maxy, b.maxy, msg=msg) diff --git a/tests/visual_tests/grids/antimeridian-bbox-1000-1000-1.0-grid-reference.json b/tests/visual_tests/grids/antimeridian-bbox-1000-1000-1.0-grid-reference.json new file mode 100644 index 000000000..0f716567a --- /dev/null +++ b/tests/visual_tests/grids/antimeridian-bbox-1000-1000-1.0-grid-reference.json @@ -0,0 +1,306 @@ +{ + "keys": [ + "", + "42", + "41", + "40", + "24", + "44", + "26", + "38", + "23", + "46", + "36", + "22", + "28", + "21", + "47", + "34", + "29", + "33", + "30", + "19", + "15", + "14", + "12", + "18", + "16", + "11", + "31", + "49", + "48", + "10", + "50", + "51", + "9", + "52", + "8", + "54", + "6", + "56", + "5", + "58", + "4", + "60", + "3", + "62", + "1", + "63", + "66", + "65", + "64" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !# $ % ", + " & ' ", + " ( ) ", + " * + , ", + " - . ", + " / 0 1 ", + " 2 3 4 56 7 ", + " 8 9 : ", + " ; <= ", + " > ? ", + " @ ", + " A B ", + " C D ", + " ", + " E F ", + " ", + " G H ", + " I J ", + " K L ", + " ", + " M N ", + " OP ", + " Q ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/antimeridian-bbox-1000-1000-2.0-grid-reference.json b/tests/visual_tests/grids/antimeridian-bbox-1000-1000-2.0-grid-reference.json new file mode 100644 index 000000000..17039986c --- /dev/null +++ b/tests/visual_tests/grids/antimeridian-bbox-1000-1000-2.0-grid-reference.json @@ -0,0 +1,286 @@ +{ + "keys": [ + "", + "42", + "40", + "24", + "37", + "46", + "22", + "28", + "35", + "20", + "30", + "15", + "12", + "32", + "17", + "48", + "10", + "50", + "9", + "52", + "54", + "7", + "57", + "5", + "60", + "3", + "1", + "63", + "66" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! # $ ", + " ", + " % ", + " & ' ", + " ( ", + " ) * ", + " + , - ", + " . / ", + " 0 ", + " 1 2 ", + " ", + " 3 4 ", + " 5 ", + " 6 ", + " ", + " 7 ", + " 8 ", + " 9 ", + " : ", + " ", + " ; < ", + " = ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/images/antimeridian-bbox-1000-1000-1.0-agg-reference.png b/tests/visual_tests/images/antimeridian-bbox-1000-1000-1.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..b6b609827ebcdc3695f9940ab23df923ed82cc86 GIT binary patch literal 938 zcmeAS@N?(olHy`uVBq!ia0y~yV15C@EX+WW{kfY20fj8 zATtLN@LO)}50_{9o#p$*VC~n%+rKq6C(18kw{m~~{{C-|8@}f6b_9P}^(?KROZ=Pg z-(~+ScWKrJE@Ge6ZMV5Q$fZ3*?`xNs+!>ekFY-&wzX}*%Tt9nJ_!fb?yJAWgr3>#} z_cVIji>EV|vwqr|wcz%P>o*p$M|Ql6S+PR=?=IUuuE)zF9W3{HM}B#w=es=7b^SW& z+CP83O4&RKz0z6tb4_WY_M+K`+y(aTS-N8O;@z%$^e-~o=Kc`-TWhQNYo+PM%RA2T z=SJIINQ?{sAdk#LQy!BmC=m<(V%+J3#_rcYZw0 zS&@?_BEHuMs95fVitVM^GIgiQMeIVh6J9U~^1N$wIdAY%r>gB_{jZLB2jwkUfA!VX z3ETF(XuNZlxpUsJ9bkjmg=7aZriZfK3nuw*36N}D{`ckskT*PC{an^LB{Ts5o|)!4 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/antimeridian-bbox-1000-1000-1.0-cairo-reference.png b/tests/visual_tests/images/antimeridian-bbox-1000-1000-1.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..dac432bc929d8b2eb10ce5dffe73c40d3e5542fe GIT binary patch literal 2203 zcmeHHjZ=~b7=Nu!P>1N1c|%1jo7qU(X=>z00jZqDG(S-Ro6A{vL=Mw%L(nOR(ob%qyrA2klJbM?mghmfM< z)4tBmE%?6tY*pRmmfH`0?d=;J*1b01IWLa@0HT*d-W8u;H>K`R5vKq}vAfniS+!-G z;&+Y37tGAOApGU3unA6a)y+E-mR=>1pLGt{yzeVM=>9KEWBpkHeGCTU(Kyx)s+k@c z8BuyI`-jd)6-5}8x7#v{u`3=lgTbL(mW(7G$>Y7Ty-=b3Bgv1*&S|r4HJfl zxiETZY7v9<7`}qkf=iV1Tnqc;iPlcRLoJ~{ee0%MxE(#Fq75~rIZLe6s{PS~ z-`4K;6~xNhxahFMr^kXd{2Xj>gMz3R$mlcnt^U5sw-+bJ!qlquTxkS8+)gG>#w}0V zR_o*7iSNR|ps656Ya(m!yw9%ux6*-$Qo$|N{uSXj*YX~iucfMuDKL8W8#yF$5pUXj zY77*Z;x-*MY~#v_p8UETDhz$*`Rc67dC@qZ{pN%~ATTDu$1Yr1{sR;~@A;nJ?7MPIfwFTRpU??6MfHdw#ZAIBG(gk@+LU;U7O{-*=9 zG%75^Dd&>ewx*UQd5*q=MR0cv*ESrlfP!SBfOfl=aqpNaJ8-)uYi>O^_z9X6euwSF z4UP}2-E+5&BPS=Ay8;@(`U%13iGpdedmSS_VepT~y>=dtb@46jgFdF}@|QWj++dlo z?0AU<@oXo|anK~Cuwxhr34UBDn>l?7alH~6{nMow8eQRC-t*OSh&41B$@d>};cU)Z z_efI4D9{m)bWhlMuy+bYl_g~iOfb1lY}wKIOMyffq7nseoER7lf?(#ElDXO~ z)k@7hgiS!(wdT#5o1i&AAa3>>U`BlwDTS(B3s^=KMt)w(dT3;_QX1w;w!v@%hN?_*Mo6wp*Sqjv*Cu z-rl_(b<2yPAyD{S(AogkE4#{Xf3H80Yu%iuqPbjV=GJ!}$5QhC@vEFHC}pLOZw93; z4(z`1&AYd$GhKQ9EBwRSx19`AXWOyI^YPg3=NCKc!@uH?&9}Wa245UyzTGA=ln+YkDkXK(u_)Xw{AmO{b4+Y+zdK9>aw#J;#t3p7qf@|S|$$)e3S6-r(- zDm%*`UHkeh+d^l4pq&9yzY0WBqN7{+YD1)c&A#|n8P;EH*11otl?xO2Wt2CITXt8T^_Sy6vY!901Zv2QcNe!(Szz*|>HHU`_IW$| zv%PGmw*Jc#uxC8e!dLrQ%KNVTFO|NCQiU%MRc>saqAL(0@~gNxc;Bxd&mZo(dD$s` zuF$Uvxh>`Vy%!#8%)Su*pJnl-iSi4#`@bld;``#ayq~bumubM@oZ2$)FNf6cziJB) z2Xs}0>eUQ zrWQWV71m$Ymp5Km=vz6@f8M<{*I)0J;*?~nI*ZqiW(%F|=ZOCLp;}-qQxZLQwHKpoq0@`z=K8&oFWQ8i;*Z-G zMq7Vrg`_eLSq-I<7wf0XJMPP0aAD#8f4zUXWc6+wT&O?4i7UL7U8<UD-~d9H#pX$oXs~K jlzDm7QNuX|IDhj0n)|#c?ANEMAa8oQ`njxgN@xNA@P)<- literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/antimeridian-bbox-1000-1000-2.0-cairo-reference.png b/tests/visual_tests/images/antimeridian-bbox-1000-1000-2.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..855cf05d93e2777ae3bb910cfecd16d77d23714b GIT binary patch literal 2414 zcmeHH`BTzq7)Px{G|JH2OuUaaugWv>SV7G+@b1#oG8HUSi^|B>BZN&??eJDqG>_E; zTh_DG8Oa>iRas3dm5e<2W`QCoqDw5!{tvr9w9m{tpPA?L%=^60=lRTg-w$(qCqx?p z0)cj(@Ny3Tfs}x)16Gn}2zQMq*!_2yIRFdd^9 zWa*vWF6Q=(uFtZnW6Th)m5T2!om*UU)gm;yT4`PtP>*h;pk}IlN#&Nz3k;FF892Fu z#esm~v{X5~Ack4+eUzxozS}BY`SUeFKtf{X{78VS2u}ALzco=lB+IL9dQ34~KHu~r z1fm7B7v*{K&i9+K!@jr4fuc2id$T1=ADPUmC+EG#p>`9x+e)?gz9ijUeDBA@0*v}P z%?*(Ba9(jM)SQb+Ox=~)t-F*--4fF*7F7kR<_sq~ob7C!nM0CI9S@24^kspqN{TAH zBq9c=4zKB(O3#3ze=`@=!#&4^b3^^|vPsPi*AY}aoiuEZ$|Yy@tqeTHniQ0zb;jle;Gk?Ui%~GxdsoGQ5T4vOw{TqB~j99G>ocyMMC5%dXJnso4 z7_<`KAM7o)psem%X`<5W#$V!!cFwH8bYnkNE8n;rg3SHZAGa=IblFe}cZA(ZJ4b*K z@}g^oqnoFYdKtN2*D9{A>AjaWD96sB0YSvs&O!T}JqX*$QfeE8&M>KNemQ+bx>FyI zEyA|c1|it$gglbTLKu5Y6|QZ{&#%RCF?~c#3UeZ%Oa~+= z->iT)zvnOS3y0iYZxhv}&^RsFL(7(%r!DZ<1}kT!PoHo$XS-s@C0Jb-dAf?|AugzZG==}PCbR)u1*cntGM=K=y9O5{pC zS0OnV7(2r`ps)g+QIj1 zd{&lwFF)_3(z&eTo@14ms#TXp&E1IC{-gT~3FFg|s_@17j|%Zr6g*gmuypu~#$gS_ zYp*_PT~}eYVd`YPp~zTus;$;)*3UPXSZ=NB%@i)d6s`n%0CtnRcf2+2k_L9d5TP{3 zrTmq6_k;L$MfnzgVy64@ta%*=@L19p`=^|@GVextdVQkt6QvaQ%b^@-%UTnw+Bm_D zOgQEw_jg$Ih^3_hIxz_l05Q07J>iQ~2wazNL`Bv|=N}$Xt$(nkfXfS0Jhp6=SZr*` zW1FJ^R_H*)DebyVs0PCJ6hc*M#c)=Jz)L=lQTsiLpbo9E8n(lAD49BafmtkuWD6y% zv{#c_gh#>M*|3DzP2|YJg@wx*`)w5KCbX?(9ToEe*CpB%JDighv3PzjmUdvMe6IQ( ze&v#g|4{Cii!U7vxcwJ};Y6rbq><>f5e`Yt64;Bdb`A@*M)-F9cvP<0=bkP07Qjnv z?-Z-i-NtxOX_SE%EV}a3$3G)+XS++*5cm%l-Fa27 + + + 1000,1000 + 200000.0,1087000.0,7007000.0,7173000.0 + + + + + mystyle + + -180,-47.2754736667,180,-34.0036943 + csv + +WKT,id, +"POINT (-176.662157383264883 -43.096109795145765)", +"POINT (-176.854671182715663 -42.903595931039007)", +"POINT (-177.252533072573982 -42.646910782400411)", +"POINT (-177.611892228793693 -42.415894147047872)", +"POINT (-178.099593973519461 -42.159208996768882)", +"POINT (-178.56162722744844 -41.735678488584703)", +"POINT (-178.72847257314487 -41.555998877995457)", +"POINT (-178.985157723427307 -41.222308171291367)", +"POINT (-179.152003072780786 -40.965623011559309)", +"POINT (-179.511362290676971 -40.490755465927869)", +"POINT (-179.80655022231997 -40.054390693250525)", +"POINT (179.923930360184784 -39.784871275110177)", +"POINT (179.75708500598833 -39.643694437033751)", +"POINT (179.346388748199729 -39.772037019858125)", +"POINT (179.025532296262895 -39.861876827647727)", +"POINT (178.563499004992451 -40.067224958370574)", +"POINT (178.281145326853419 -40.208401797959127)", +"POINT (178.02446016489057 -40.054390701181269)", +"POINT (177.677935196187519 -39.900379604399049)", +"POINT (177.485421324683159 -39.669362958813636)", +"POINT (177.331410227479353 -39.425512055075657)", +"POINT (177.215901904577578 -39.181661151299444)", +"POINT (177.023388033074042 -38.86080469896423)", +"POINT (176.76670287107433 -38.604119537111721)", +"POINT (176.535686225282944 -38.565616762876971)", +"POINT (176.317503837598906 -38.783799150566402)", +"POINT (176.176326998513417 -38.989147280139598)", +"POINT (175.932476094645182 -39.425512055467188)", +"POINT (175.701459448881849 -39.759202766009246)", +"POINT (175.52177983551357 -40.080059218446856)", +"POINT (175.149586350685809 -40.37524715469236)", +"POINT (174.880066930641647 -40.298241606113201)", +"POINT (174.700387317279876 -40.131396250851466)", +"POINT (174.469370671529759 -39.861876830812001)", +"POINT (174.418033639140958 -39.707865733646173)", +"POINT (174.212685509585867 -39.374175023120273)", +"POINT (174.148514219099951 -39.143158377371385)", +"POINT (174.05867441241972 -38.937810247816806)", +"POINT (173.930331831447972 -38.719627860165083)", +"POINT (173.699315185698993 -38.527113988707669)", +"POINT (173.327121700881207 -38.552782504902005)", +"POINT (172.993430990354909 -38.655456569679323)", +"POINT (172.839419893188989 -38.732462118262291)", +"POINT (172.659740279828696 -38.899307473525418)", +"POINT (172.45439215027406 -39.027650054497059)", +"POINT (172.197706988330737 -39.284335216440311)", +"POINT (172.018027374970359 -39.669362959355176)", +"POINT (-170.809757996124091 -39.258667337666161)", +"POINT (-171.092108440755396 -39.489683796643384)", +"POINT (-171.374459297976472 -39.72070029102813)", +"POINT (-171.669644665725599 -39.95171681078768)", +"POINT (-171.964830399850541 -40.195567616117053)", +"POINT (-172.208679740446428 -40.426584197598665)", +"POINT (-172.542368540167502 -40.631932262228219)", +"POINT (-172.696378898013165 -40.785943335635686)", +"POINT (-173.055736583802087 -41.068296973781855)", +"POINT (-173.273918197572641 -41.299313602634044)", +"POINT (-173.658944763471993 -41.645838554189496)", +"POINT (-173.504934101572132 -41.491827462434976)", +"POINT (-173.979800429072611 -41.992363516983445)", +"POINT (-174.108142742586438 -42.172043129406539)", +"POINT (-174.313490466537729 -42.377391260144812)", +"POINT (-174.608677910682047 -42.736750491079746)", +"POINT (-176.058947562102475 -43.429800480947527)", +"POINT (-174.955202379135329 -42.967767146816229)", +"POINT (-175.481406377455045 -43.160281038130286)", +"POINT (-175.802262571951218 -43.352794922023079)", +"POINT (-176.328466827030041 -43.339960685516779)", +"POINT (-176.508146353344472 -43.250120886092468)", + + + + + \ No newline at end of file