From 9bedde397f2f61675bc687b95875893aa7cd7f2f Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Wed, 5 Jul 2017 17:09:07 -0700 Subject: [PATCH 01/75] removed org.json dependency --- DepFiles/public/jackson-core-2.6.2.jar | Bin 0 -> 258824 bytes DepFiles/public/jackson-core-asl-1.9.11.jar | Bin 232131 -> 0 bytes DepFiles/public/java-json.jar | Bin 42100 -> 0 bytes DepFiles/unittest/junit-4.12.jar | Bin 0 -> 314932 bytes DepFiles/unittest/junit-4.8.2.jar | Bin 237344 -> 0 bytes build.xml | 6 +- pom.xml | 15 +- .../esri/core/geometry/GeometryEngine.java | 134 +- .../core/geometry/JSONArrayEnumerator.java | 67 - .../core/geometry/JSONObjectEnumerator.java | 80 -- .../com/esri/core/geometry/JSONUtils.java | 21 +- .../core/geometry/JsonGeometryException.java | 18 +- .../esri/core/geometry/JsonParserReader.java | 147 ++- .../com/esri/core/geometry/JsonReader.java | 59 +- ...arserCursor.java => JsonReaderCursor.java} | 28 +- .../esri/core/geometry/JsonValueReader.java | 233 ---- .../com/esri/core/geometry/MultiPathImpl.java | 44 +- .../java/com/esri/core/geometry/Operator.java | 3 +- .../core/geometry/OperatorFactoryLocal.java | 17 +- .../geometry/OperatorImportFromGeoJson.java | 13 +- .../OperatorImportFromGeoJsonLocal.java | 1143 +++++++---------- .../core/geometry/OperatorImportFromJson.java | 26 +- .../OperatorImportFromJsonCursor.java | 55 +- .../geometry/OperatorImportFromJsonLocal.java | 38 +- ...ursor.java => SimpleJsonReaderCursor.java} | 16 +- .../esri/core/geometry/SpatialReference.java | 23 +- .../esri/core/geometry/ogc/OGCGeometry.java | 48 +- .../com/esri/core/geometry/GeometryUtils.java | 9 +- .../esri/core/geometry/TestCommonMethods.java | 11 +- .../com/esri/core/geometry/TestContains.java | 16 +- .../com/esri/core/geometry/TestDistance.java | 14 +- .../esri/core/geometry/TestGeomToGeoJson.java | 25 +- ...omToJSonExportSRFromWkiOrWkt_CR181369.java | 43 +- .../esri/core/geometry/TestImportExport.java | 7 +- .../TestJSonToGeomFromWkiOrWkt_CR177613.java | 11 +- .../esri/core/geometry/TestJsonParser.java | 12 +- .../java/com/esri/core/geometry/TestOGC.java | 12 +- .../com/esri/core/geometry/TestPolygon.java | 13 +- .../com/esri/core/geometry/TestRelation.java | 3 +- .../com/esri/core/geometry/TestSimplify.java | 26 +- .../esri/core/geometry/TestWKBSupport.java | 58 +- 41 files changed, 902 insertions(+), 1592 deletions(-) create mode 100644 DepFiles/public/jackson-core-2.6.2.jar delete mode 100644 DepFiles/public/jackson-core-asl-1.9.11.jar delete mode 100644 DepFiles/public/java-json.jar create mode 100644 DepFiles/unittest/junit-4.12.jar delete mode 100644 DepFiles/unittest/junit-4.8.2.jar delete mode 100644 src/main/java/com/esri/core/geometry/JSONArrayEnumerator.java delete mode 100644 src/main/java/com/esri/core/geometry/JSONObjectEnumerator.java rename src/main/java/com/esri/core/geometry/{JsonParserCursor.java => JsonReaderCursor.java} (68%) delete mode 100644 src/main/java/com/esri/core/geometry/JsonValueReader.java rename src/main/java/com/esri/core/geometry/{SimpleJsonParserCursor.java => SimpleJsonReaderCursor.java} (78%) diff --git a/DepFiles/public/jackson-core-2.6.2.jar b/DepFiles/public/jackson-core-2.6.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..a7d87f067340ac378230a8ccf8b4dfc9512a94c1 GIT binary patch literal 258824 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%0ANnsM4|)f9WP^dq=- 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

F9Ck<@RiJoLX=RjXyZyA$)Ipeh4?TNP+Eozyr@& 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

SN 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 literal 0 HcmV?d00001 diff --git a/DepFiles/public/jackson-core-asl-1.9.11.jar b/DepFiles/public/jackson-core-asl-1.9.11.jar deleted file mode 100644 index 145fc4892222e773e7807b6cb25c9c7162f7bfac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232131 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%0Di*Io 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�pcp09 zyo^2ut4fa1F6E?5-sWYD@WX}ch4=SAiSy=^fFYwM9-CsAJz;KuR))nDu}}$ z)X#Syo0{jFaP%x~NSis&UYjQfqn~9PUXDaUSCU)Xq3_zGpSFizT8G`pZA>Cpk@4@S zhrWnTf>>?2p_{2B&v0??A& z=hEL@SV{(=1$muUGl6p0bcY}&L8**Z5Cx^xk;`Y9zwU>qiz%p!50qtOm1QQBWG0kl z=!i3Op%dK+XBS+H{ zHad)}lk8pAyLiJg=Cfzf)Au)5Y3{^+Pb)}8vvWP~nKx-s`6MQbdnQSEIX`q>*PYYV z3}A3c^9P>5L&-!W2=OQ?;Wv=w<1KeA5L688*SQV=8M(6Q0A?QMP#lR#^UnjrW#(PN z)~G$W?7j%_d%DCJ0fO1~P*^>L4KIkJdmYFg_WmNiWRrVb!VoDt_n+N3jEIA2fheLAcCUI0tS&l$w2}0mLuZkMtf`x0{t+yD!SkiJidE z*Nz)(KO}?w>w&)?VD6EA;6%5vd%9mR-ZO$Bxi2SCw@hoqUl@(|wc51bys`&74Ywb> zDFfeQB{#XN@gJ6)+28#!M?DR+U-r#e-@`f{vGJp8v%}n(5mIF)`(Hd)&WQUlk1TSR zv4a`O1d(e>0?SsCSW$UUa1DjvuJb4ElB$d#qG_Q7WYaq;Yp|RIKUs?!hg$Oi)T|M! zA4ZgREDuHBaJB>K9*Km4iZyW-+$|y|jMj@eEmEkIj0%OWWF`;X0R`|(uSs?Q4ns$3 zvw4_PuhJtrm2R2m4kHwUSsPleF?zD+UPd{vA==UdS`&!S25Qe$4mH7x`66$Kt%Abu z0L||Cx!;+h+dv@t*yT*G*>?UWn5Bw^p9XoOARa%2ri3PU`8TVpPda$Lg!DIu^Z4&D zr#)H8JSGG&zPTWQlv7t~6siHoQ*+MFyi5W<^c64|7gez`k2k&3#E|cMy|Qqd><);- z-cU6uCh4K2;mgD8KrbivP#LO_#Sl)f{sXr5J^U6lpKS*hw!eyjCQSkeRrADk(ymeo zK%t65e|8!S3)umq77RXhWvMHX!j!Wy=dUOtGcm~0R14EseP193-|ZI`OtpF*l}mD!pTj|8IuzC0{C zK0-T2t^clw`@*U`3Pb8%yIgJTSX$k-zA3IcF2*!kh2v*}O}e4ZWKB{^!`3{jYh+WF zi!|M;!I_wAZc~B}wZ~eE3fjAZjfJ2zLzU#6BW3k5j0&Bb%+D98v6yhB@Wh)f1=zGzM8$v9)qV>3ZA z8ET~vuQ(C>{Qijx8v@ByK2DX9cmZgo!H8(Spdj-7cM9bpqXUrF;+1Lx~ORhoF(RUeI$VT#Vi58qMJW@qStf)i4_f&P=hlG zplFI&rXAd=NY*&;feN70j&C8Y*~fQgQG~-JzU{a^;o2{&oRi=TGv_h->O%mwR=Ei?Vyx6i zY3NVF@Y*lqmJ`uoioPbkkIcW69cnHDYkLL40l|0%oM@MmdPghJBJ5i`I<{7WTI9L> z%2uK|?hHKcyz|RO3wlsLZDfJbqsTUs%FdH%89+Wm#Ae)rIh!{aO}q*$pWix7dCyZj zmq^`2dYtca$Z#ggqS}hBc?PjfCJe?a0-I&vhp&~1?c10?IJR)*oV55oXz>Kw2qfh| z+jEOjlHlM^dKAFTojArh2M8l+IMgo)c!v76J8%$ukfTdAicwOQ@*Zy0?Gv_Iv?r9{ zk7`PDoh>lqYT=*Tr6rUA=+T-3H;n6Jw_z5nth$%786PBQ3Z;~)&Jcf+fv%*~z`vJa zhMFH$$!F~ic6eT4f}y+dxVTZ{Jk7lu|5Wo|N~;ZgV1>QGh%&J+K;8+=pWg_xzRp|f zhBGaGCf0pJrj+#yGA)iZs(D~hlgbsUexPBOH53tggAJTt3H!BE;P4%=>@_=yLTdz0 zhvv(N0~^vypO(JT@M`-5mIBWW`-n71XfG|WYZbtR4O$vD>0cOl2BN$R6)bK+JYY?I z+~CU%TH1rcJouHF0~YzAcIeRbs^Gw>f=ksu(tOrn(8l?Xz>q4rB4b>Dtrb0(5Q5vx z@%9;nf0x8q%1>y&ptJKIb6yLF@!`72Lv{`xNN@xL)E6D%SQs__dMO|JP_ zNi6S5or!*|#PTkch%~Fq&Oa)jN&%}wceb3bWY$0K%z^M}HSY|kUvjK_#wuP^nZgdQ z6BF#*0IoVBybdNUNQ(Q3mo@LFRLakcLPBb2p+q*Zn~ZTYM%y%osYUhE0muhEot$XY z$cN3C9NN3&#HzZnslGnsX}oH!XQl3d5xlZec(OlW@_3^AQo;B& ztJs~?T>w>sTWA-UPa5{KJlYWH-dz9a9umDC=G7Zy`v;-o63|*N7#CAChihVoUQ{M% zYik}?nyI$l)a1ZL8*7+i>x5@?5ZOiRj9Fvr3JJho+|BLAS@u$UP)4O%2I%G>csRkx z#mnZaZG-_JPJ}F^E*aYwj@?$Z7SHSzN;3 zz>w#Y@m01p*5Q`z0iPk-9Y#fs7_pY?p|4nve**PERnfH|R^aGFGDr9);Ej_7gSP5= zx0@TOomNBFLPh@er;|^lo5=pcC~+hWXo>Qr%M){i6(fGfC5!3}JP%AMjY7QV1#Bm9i`9jH3ZM<1K}@|xNw=?wW~WQ=)pnlM3-@ZJ9`KM zAHPAYE&!9|ggrcZS=Rf9S=sPUEu%$Rj}*`on;17xJ$1Ez@l)k0JjNlPX=0;$7sSQxC7v1 z^r=h=-CPed=i$82^jH!)_X%DGzym7E@^b-5+M*Zp4ytUgP#oI2mSV&2cV~YHu`p zVdAn>dtvG>jOEd6hh}dmJ?b5t#KB*jd$x_nbzQ~vT7N-8bKt4yGUpPru?HW$iGJ`C_LN#jfX9Jps%&q?%M%$M{ZNL7uZ_Vfnnfm z`65y=sGAHx_G*W8e?Lf9fMKuTbs{GIObV`(51gg!U^5mH6~pL4V!Z%f6yi-<2WZ3_ z_z~hGBz6*2owpPeIuAW)Mg31-=iIm&(*~S#2C(3_3C~c^s8jUwYUlKfT%lB&S5B03 zmRVlgF3~O`AGAY7674T|j$7{azgT7AwQ~mFF;8y@=%Y}^IUfW`6W@cg-%Q|l*L&cv zl5#(M12JE*7Kdx=l)sQ{6TFPraCg;VgBT*fS7=!`%gP)wO#=8MFs_tQcS$Jbz%M<3 zKzb#_BN0)J)+y+FK>xop{qL+p-zODyS-lNKTBP~S!QV5%F6J})rQ#ghv-NvpZrYN^ zceRL4kV;n3LwG4iv>EtwmN)dKcjM6_H_$2fHT+n`PNG4`jXP0N3QtE2Nw};EONJ)P z7r~B*Irf6iUvPWmL#aP8!k~gzpEpipg_WRT9950+ zw;s2mRvqpYF~`R*H50Ag2NsW$-_RwJ6v+j+jH}(_^(s3Q30Xk=lQ4@)4CG0T27Q=z zg-?=zrT^N+a-V#c`q@TPjRSe5XYM}mZMcb3eK39cjq3LF07-CURYyDGub&R1Pz)kL z*GMc&6KtA9npTc3TCW0npUhgOaa;(E)hknskDDZ;RjekgR37p;P6`m!hPR}V-2*kp z$#{2aRnc~Yo^2Zk&yJLz<)%VB9esHI1}dfE?gSbX_q?!O#+hk`Q-T+gF3-!>NYwIC z;jXhMQ~;1g$5Ix|sQ_e!uBT8rp3jJ*WCvY8hW~PAQG2@dLU)QgZbZw8ps-$_a(gM- zUnphF3h2%X_*msu5{qktSw|2_(Eh+KZ4!<_4VIRHj!|3B7t)3c8RtnWtqP?*QfpdT zFiLmgS){QPYILGpztEno$wI(OmUpOdVzgD678TA#@>Ag~%wyubYz46i$up-84iTA^ ziOT!sfO3_O6p@O5g1ejvYT1CM{GyWkqHWo&#f`H8EpBqL448M!*!|UV8HN8DegXdz zuB=(e8>9iLNx<-$W<{jIiJ&#mf#rT^F<%^q-?~6tjjgM6)e7Xp^ND1${*&%0m_V9 znv&hY5DJj}B>X1t21U+&3B&7UmZGI@A>(!H#XeFP z)o3>=Xn>-mbL*QM-(rS)CZoW;fUNw9`&zAINMJNf6IaC`uAHYUktur0KQ;2zF-KxAcAVLC9$Cg zVw>-eHeZxBUzj#uoHk#GHeZakFF2=9NT*NCg2fF-Zu{s7k05LFXWXn@|FIh%6S~aP zW<|N~oz=LfkQ=Cdp%*z-OeEJ{=F+X|9sE;d-HlL(lCmy^JX@JpkjqC=vu9K6O7Fnw zTbxNH0ZH2z(E2^uGPUkN@$ntwkh@=UjNXBLqwv@aow<+3<#WL^$ut&|MUv9 z81;pGtto$27jm@<$zI3vQ*2)+Ip2zdn?#XsmC*cW-RQ~7On2bBgWdp!uH@Tv6k_b@ zJ15et74sJ z*yrQG5roh!&`2%Wo=K{ZFB)RekOK!!*kjFEti?v(6LoM8GsI)}*z4X)rI_G9R0+8k zz|sOlnUgh~4o^feD(OY4_-C;e(i&|i8RH(iJo`%L zf^5inc4BSc!$BQ%VWtg26{7R$-8h;ai)-K0?h?K{U6VXJ%(sY2mmPpH^8p>Isc{>% z{K(%+Eu{6`_+cj;k5;|c_A72*i5~AhS#SNX01=4_OIXu)Gn(nDG5rlFLHMy*S$x!? z_^0Se>gnj$krdC}xM=-PmyhP}9upHgZ_1?6!CHwlCDSyin9JE)U14YQ+fycjo;G>e z56nW6veW_!gXk1@grYKCyr&5O7OdN`>3tvWvR; z23-gliwat$+c6p*P!dVJ#*OVzd%Je4#aBU@i=VUA+h9lqMTF`^LI41WeHl_;$N9j` zKiRi;jQ}Ln64fr%BhBzqX?lgg1h9OjUitjKO3EjEO4ZOJ`JCc;TOewPnb?|PKg z3(mAe_o@gmzLCfvvhU1FAZ`VYm$Z~~pr9`CM5uD7yQuKQk?q7s-;d=iFZdbZe#;D9 zanR5}8$hmw49@_w+q7y_WR7g6n_$#n&MemmAE2FLM*Rmq#3KdWsu>`6F$#1BLp!yv zB&DA3S722t3W2Bx{uU*Gt9QsHK(<701n9zDgM5ZygtqL-gLEY8k7?d6n=X72{U_Id zO@{C7@sHUSGyLy3;Q!3^|L-cm|0mb~A93b?W&4vg-`&tHaeOTr$0#S_;z0Higs{r4 zEJQO@>Y?*j>k!)6$TTeh>z^E#P z;^+U`RXpcDzjclA13r3KQg-|RT_iew-+pDheiyhtT3d7bem^z`!Mn)>%+KP^2FwAR zMk9+Rm?=d`Vo2fRV@4g=5z!7DWi;Sj;n5uF2L~P<%v{ZH%&3R*_tWq*lZ<6*1W4D3 ze)XEZL{<4{u=6uE=f*|P4BdKo3v+f;&pYDeRE?yX9hC#RqtFVT)8G|X4(J};C0x64 z2O3$t<%Mkr=l*nFQEM&wiSd@W;JH4>^~@Iv5wKK+C$x02b5c@~hO)w*H{+)4{Zg%? zS+eI1xys63iPRap6eu`~X>X>0Z3x2IxOehvorbS-4E|#zoN(Aqx*YPsOWnxi|dF+>sbI_T}iOy zr@`2qwd~j($u6ZNmrDgKXx<41y@EQ(r5n5=$k^Ig+a4Sj`r`3Lg7`bj1`BKlKW)^r z{Lurp5 zXCBqXvftJ=)5XR!EL9?kq2w|xBd%=_;pYhNEZ*5R5>6$T=iPAKHYFw2hq$8;4Hix8 zl$IkLOq!dfL`w`1)%R(W5tff%<;DRO*quMettm!A5gAIZU^YmOO*5zqT6A!Iho zsK4*}QDO*67{Uvx-~Rp( z8DerY7^*zgtd|9@+<3xcsmT>qnMi0b?jvB>?j6H@Iog_J@kFYN+CBke- z!&`yTJ{kML+n2v!Fh(M2YCU-|49_xZ4Hr7^BsNHqW3W@TkW+GS6O3Y3CL5ke^NU{m^4}P!m z7Jq6hy4C3>*^-M8YL_M$H}e^YlyssPxyAEtF+Fi!NnY1*O+c&Q6@5CaJ84ln_@gI} zRAfL4EA8yEJ{Zgx<2)tF(_%I7r1qq-@t8wEudf)Gf1X)~Pr_*^OY0NFyE;Y&)Q7Qc z+(SI8Q3UN^m!&&>#oq4zm6Ofu2HpcHW*EO%WqzhGyofD%C-nPzn?Hyw{i|=UJASXP zOEg^og5Z8-FxnHQywBmC{x#Z^Z)K+_?YNDaPxmhy*8+CKBZrIXgtN32ralq#acr>O zO@zP(TlR!Kw88RvX*z{X4I1j%V-alQ-Ou^m6p1Y**`Kt$ikw~+Fq4K8lTOHNHm$sE zIa7a&7Fk5yKtW?mSV4=k7Z_+o5%e#9<7c*CwaO_>ScEO>j=2KzONTD6*eDdb=v+t#MWOj zkf{398wyQsLiC1r^v0JTEx`G-qClZyX8tD?!!TUl7qBf{0;C)ib~9Cflyv5*Ab5Vd zGgo*wlc5b4WH!Dq5{gf2!mqqW4s@e%0FZIDNqaC!igtdh?`E8VVJR`S<}8-b+*Av1 z-z|LMw?#miqXu)Z>M@da|G8w(n1}b!Z~uk+XYThID`r!6e}=3Ql3ss57@L)?HLYnp zHEm&AR0mhquLGhZhO$&0C;2lxuKHKh!$UB zQfXb3;ceqnd2K=yI{)OnT`kcw^yT%Tye~#DVU&}G2omtJQa3+DNep+++gGHhKvlT_nL?!e9PNE4EzJ3Lhrn_tR(EH z7*x+gf6FoT5xYW_B%AA@ohZ(Z zR{UC8<$|n_b=0{G&Edu4UE_4?9PM;oR+4F|qG_BUr}CAFkxY70x7_Z~Q!jv&DLS=K z-^A0$?Fw_DsxR<#tZBF6sNJX!JMd_K<|&4o{L5~vZ#K}=x85=M*^<^rw>qJi5_-ca z5bb8POG`Lxul=KEK-GN(X>=IGs2EXU7tNO-jQxkG|ncs(ohF;udW-W{tDQWW~w@i8$)!;ZNR7Hju#dGMlg{Xnrrw`QmKt&lg)>GY7mo+-~2m*KXG!fZ&zF)yM^X>>)O%(Q#v8#F=pt ztRd2Ask18ll!6z00ixn2+uf{yd*zG4-`OvLSv}OD-c&iMjTj-}$<(&!hr%dB5LK?m z2r+y<%I6-!I*j93enm(M;B}C+<3;Zo`g4Y{`!pd%5Mh=M(PD>Us^{k^-TTo^{7b9QdC8 zTaPL%>Rik}lf{ku?k4(ENy!#3cV+U7za<^CMNc4%AutSQQ&K4LV=9eD_@V!#f=!fm zhdIFEdNz|ST}BqDc9W=?pBsB;b2kO}8acoq!ZW_6FH?||s`Z|9_ zFvtWPv^_YkR6w7fdSdL9+y)G~>#NT>X{xRzNA_zNWAIlxtlzhhC16|9zTY_=MY+wl zlUoGBe-@+g$ERFRx{PGEnQCCzGCE^6sU z(7+ASz~}6%08YK}sF`&X;MH7ZmjotU+d;q6!f9LEluwerYS4FvDGS?ZwSC)9Z?*cI zpKfCBHqNcAG32rCRIRSee1p5Nd1sXf52dj9P8$D9%3|FmL{PISje6PgdUB0z?L&{U z1CVPtnKLz2uQaTiXxU-VzjTyzqQB;pRyji0+l~okK4PO89i9Z8sT_kZWr;_SsTZfk z|3O0g=+mk2d`B58l=>N*z^EIMu_g<^OCszW5$b($PUPj~CX!MZG|5*iY)tiSomVo}iz#Fo|F`;>($qDwrJG1hyI4YWd z0^tC8wagi@$|8C3$eF2_bm(buO%c^gv%WM@>0*A-zy}`RCyaLjRq=^to9-2n>~=v= zOCDCt&;!>jVH*um2^By>!juEMJ`(pH2Z|r`Lx0|dxZta!T8xMHJ zebpx1AyGhqH{rh9WGRg}b1^eT$ctcvDM=2^G^@m!@&*wekaw}5I4bS&UlZOBxr1`% zB0op<{(Y)c`+U{m#{~7_-crU_wX%w~OE5kJbY+hCjpd&-}y zEKUTm-B7<@`7iXg2Wz^oa6S9Mx_o@R%kuruz^)}TkokqbL9jY@jf1h~u&?t6sL_D_ z!WzsIx~Blnv`jS6-h<*IVc<&%~Ekt!{t9PulK7V32IdaP{aWROT@>& zj)nI(V|R=dP#VJ<8GB$wB&r=!)}$7#8*>+w5ISm2E$;~U)CO)i#EvR)pU64>X|)DJ z)nK}((zZ#EzQhRC${l~h1)*)QR!!jXH(fZ{sUEe3qhy@60*zsOE%w2jlqxHn;pG>R zJ9?@&OLBVZsyBs^wy7HYhM2#GDW9GpXFSyga8wPV{@m;r&8Jab-94|>eX(X49t+BN zAnXhvHM|NgLV|!i!~gfO`9J$F82(qQkGiu3K+@dK+{xJ4-s!)t?|-~u z+||UFpUT^1-FOJ3L~x6YNwN_yv^*vUIohVqKy zS7@_WxvMsN0{7aS&ME3gIrnBy=O4-`*<``{>nOy@YiCJy>XAU3o4?tZP#<1sSr zE3|a2az{vUt$O!^f=I;)n9!K?5tl%;wibK#ipKj+bM}FPG0nX?vpPfb3^)Fn;MC(( zXIS`<_8uMdnerKvu#*_&M?Cg5(kEcyS9FL*>w9kGN2>lkne(TyXSUU^_|V?<$!-3Y z$n{B)_Z?Fxsn90-877=k8Aj#+u5<%O&n-TQ)0{h4|$t&H-wTV}; zfD-XMUrC>JiJL|`znuh8AgOddl3iw=21h~~l7bN;uLVoHFLdJtnwRKoH{Cla+md@% z=c)vgP%JC9WD{Ga6Hy=~w$O}^0Fr}wbXfVamVSFXqm)n=-({%yqQB=K^y6a*}9 z93N`tNR>L>=3v3rn+L4RNMBu9o(fE(m$;Z29bWRIZ`8)`rzMD_|Fl))nOgr7O@W$@ zQoNzNv@(XeU6_W37A+Tx6sHcRhGtStVFg`*I)=qkGCVM>0`x*lJHxOo%7%;8A#8m- z`87mb?I3#jAElRkq$+P$Rnp`Qu{0UITvfqXi`q532Sry&M{BW&o~ov%ksm>^I$YLg zAD<<7p8U%~VgnF`+GWXHMep|u0YOJwRoy^UNncM-EuagqpWaku^-KPr>or0K(i_a= zL`zv;$A*1aL|xoP`JdZ3%TUKU1sFWROLmzZU*OQy!;f6DO|Bs?3*8qB-cAZXoC@U0 zC|L@{1)chuzG<5JdYkCa-)%~nZAx%jvmy*MKtlynm*4^Y;)EQK<$7;>p#|@ zcVur(K~YTH2MLMOpmcmqnyr(;Bbse|E=(%+evc5MTpm?1FH}b}FGmDxlsnpNHPDp7 z6JH6vXkTgnxbg>bcJpt1=e=$qLwpFlO#{>q8|i({BbQ9D$9R#dn%q?E!?8-7vPJ*C z+4+B%jJTz)eqP~t99b8;+O@s@<+W9QLzNoY6hqn7;g2GlpZ3`r1lFBa*2LJSHnh@8240w`)W5nhZ0LzYgv2mX!?`Pz@mNY(@!{$Wf27%dlMWtd|Ubp2vpC`hrVT7>nFR@G_jW9Frz_$$Skn8UBiQw zl__f>OhDt)XRo-iudbo(9-XfdYW|sQu-QAiK1z5QK3>HB@HGY|PBBTmb1eNc34%ZyVQS!nbUqB8pv{9}KC{m>QYd zn%8htA|3^4h6S09n$77~>OO zA9J;tV=-W!N}5_%*ZSO6xP;3N4YexYQ>_$HSF-sJ)Odf`67-shxg;^_*#hGnI-12C zt}gGuRMT5Cuz%G7BxY8}h(5AD?U$9jB*+jFR8+F^ATLm7V=!yMAtp?55$7lhcY-|0 z838VVONAU6M*O3?m|YM^VHKu?{r74d+G#vS7Nt5GEGi;V7Ab59GCF(L$CpCE$@Xw? zww}kTNvuv1M;?xMAYMuL!=L7{U|sKazB)ScaHJ$r7rQByHvh;=N-}RM)=|GMe0hu+ zr+$sd)(XR}{Q4Ae&-sSvQMMsCR|Rv=%cRxSWYnBTZ-Vy$@eOFB_IMh4G0?N z(IsOLBOq(7w@iiBjH;lFM4a=VVC;aB=4$(SdT|QP@k;R*{<}D&-U;YkU{bY>TJrpv zbgCk<4HYEZl*x^Mz9Vrzu56kPOvol>wJDEX2XYnq{Z^UOz=&Ap{yBIU0U7i3`dH2C z@1_Ri;XQYZMkjH}U3I6OQl-i|V#~hy1-K06qV~X3;MwDNi9zdztL5Dj1(+T*W_few z9t5}SQc!h@BKZ2l%p73x?CHDDz+4YVCm6vx=3^GR3;PuA~^pkq!V2?>4GlI z@}`Ndi%JEgCl&+N{>c4qAb;5$PUU^2=uD~zH9mDDY16;944)WFnPNysbg`i9Z*&$8g=5$8&?Ys8Uf_nj0zT)CvJofsQgMSaz zJJ-iF3&Fh+D1PplQZ2mlP#Mll%*Cb$1_yh&-XU~uj@gp;NhBC;g5)x1;O!W>;@YE; zPE|-9$!6P<`~G_>)}hiJV6DSNyOIp5SFh?H{+rdA!v*m07g!k86c3`SeF+Sp-VjGd zB>M|rNTN}XqOdF{O-4~zW=BeavW$bE*6Ct$E+N?(B_C76xt*sKpWO*F4OnyLTpG^I z?hLVaZCJAfCK?XwX4|q%wA^z3`yYYk@d#_-eLYHYMvm;~Gdajs>k6r8QJT`gyKZoF z#vCXD8LptD@Yf8>sqL372^7wfP#(7pjde5;^8o%$O4ed&=U$_LM{t8M{u7iyN7ELO zP>Dj?oyb&otFNFT;a;7W@l$HO7CGIuu)2I*VQJ+~hN>r~swp92r4g2@Ct&CFkgFbr z)3-5kr@zLjK^A7=G0C>*5VxWO70s8f2jSr6{xZdZ$k>kBfl32a%v=|@a~O1=BL&Z1 zG%r5u$0hgiP!}mRu4r~2q#SSOF%2-a`z$*~Yv=0F?S>zI_{8(GI{sM6Qnk^oQt$%7 zt-0lZc6&EExO3`@;fFnS7$iXUqukt=swZ((a|SodmaY6lGw^%`yMxS@jxV(ywQMc%EQvwBsTc9_E9_A{ zKYAzDYvA5~oC+PUlnNUxgWFOXc?Yu~y1xm(1XCUJxR$;`Te-VHBA9=4N7(kckZh*# zh(`~-s0?D|&ib2z?_$U8&hxO}ND;!}iVNcK6$pJ9AxiMN_m+YQmWawj$wpd3-3xYV zoZ%f^{MZ?ABe&}5kKhNxa7GaDq$F7ct^F&Dg_9F!?n%ZLjRX#{PV;=hX4~%vrSD1X z7fL|mzz8M-V`-fZO~h z%z*cykK>oGJ@MXidByk@-kFW%Lr*RH5g`EuuI=F(a@!EV*aOw zp;cp&vFI&tfS@gO%n}+TY2Do7>W{Q{^!kk!b4fQQ#KPs({f&myiSsD2_g8^8CK#6p zHjQeE&ib2}>bGMtgA=ZDnz35`MUdQ_lfP(AYbPjD1EitQ z_Wk8JK@)tUs#3%u7+y1S9+p!w=Oi@5fUc}@GI3!ggGH?i=5-S?M+M9squ_e#P?7i- zE^8o+=>YBu@|TfWdYa;?MWk#cUFuTRWNj6_j)C z7#lG7?G!xjpiU>AJ?jg{jmevbir$x$3%()x8xXS8~7vFIe9j2thrfGhgn_ zDmw#b!`RZHl$CZK9Z#1&yAkL#{B3AuP^xZ;yNTuciT@Nx=j4ufD(hTFA^U;WxRsU^ z@2}t?olpb1c@b~)tD!WD12o?%w)uJ56mzE> zC2Y9&J(BjpU}XmoLP$uc06Rh?=~+Ult;lGV z+N*#j4oPra!IDTj?7%bO*?f2vV)(PsaFkIPBqw8hr@m19v=B}M|7He}jT#}m8gabk zye;3r|3lb0#%LCOUA}DFwrxITb?GS^-DTT$mu=g&ZQFL2jh_C$Zzh?UWM-0m@6G*m zzMSOjlfBmZ37X;G4=C=FgT(WPwXw#3;95>e{5idafBy-3;u~RJ0XQ|lIBDJk3eFH&vkdl%CHMvT>Gq~Nu&?A594^?`**h8=gD4RPEN6|ERVrhx!fB?4nD zc*tBtCGH+Gbg$$dRQ1ij+`A7bM3P*(RT~eHG4=(uc~17CLlKPV^%u#P`MeH8Dvvev zy@3cMa{o1s}!kkv@&1Wk__F~=h%~~X1?Ep2dg8A|N z@pIoTj$7y)eM!KGvpq{D&V&^Q_p(f=U!U;s?f5P8l*4Q5D^J+pzUJ5R**&K>T4S&$ zy&%V!zS?Nry%s_d-%_*ZKANgYKEy$9UfU;-HDHnd0{9H>ZWR)*&^w2m~cUxhTPI3TuI3~AE;doqSj&t2*0O+j0+lU6I#z(fW2K#M@ zZp4uZp{mIx|5GS!*wK)5G6akZvtrFzbM%*Hla8HbD^ZW3IKip^hC}(bMftX5{w+0YCou=1T9yiSB~^Q)%ZR^1 zt)z{=(jter9y>9g$ibMOieqm?17xO&+V*gMvpmWchuu)f7m4h9zgw3@mb1ltQdNRv zs~tdB8d6k-!mr^0O&F(sUFN6RG|A5vt337?UzDU#7pIYm^~ikmU3y_PtP+NepVP?1 zC`Ys7++`W#Nt}_WWq6{M&<4#JsU}~s5VD4sv!j}Uu?Tkr@}&*o#o2(GYN039|H_ie z%+F~C#5HRH;V6OQDKKxitVd?gV!kVealHk^_k`izIKnuhNBpR7)#2XQWW9v(yAJwC z*WjeWn~|Sc{bae^I7hXgc4Ieyqgv4;H}d;cvinu?dv20@ZqoZ!lKa*i=r@E83Ra+T z;&GNx@a0Ab4&Rj+uVc)hgwzcAUK`!g-2tR+6|p1Cy%WYn@t$?AT>6n1OA3_z>HqM$ZElxIH9lD_jb^P{hpM7XNi5JoK8*SPc3z%u`Uc)OLgV}Cq^A!i#3!e4Q zU5O+8u*-FPd-e|^fw3L5vNwcjg{5aXGpiskEw-9Rf)i3&SYb*eVQQucC|`U^U*?XN z40In>g+~mnu~QP(ZTJ_&$W(YiDrP}teNTq2$H&v+(FwWP)PD{}BZU1YoGVa%a60}d zn7=UXZ>o=c#QCedVfv@1XD+^=sdWYb$`4G(2kyBsUwETue(^Wtx=bGgueDNp>6CBygfHL) zy=E`#M)vO+&ti26fDdhqxF2Bi7a<%oBvF+tIaVwYmn?~!B(c=}Y&i&+Tdl}%1cITgAwvP6$(b8fOwe!JJW6QxV*IY{RDFMV6sULCT?ZNgG$+R} z#L>1R>8?ut-WygX-zYL%VVTInq#`QCUaOc99 zyiwqc`mltY4iE@IV%?RS&zvibnDx;K!C$;tn;&9}V)x>>-g?;M=h``VwPx;Z$JDc; z(ty`U?>#S^+iIen3C#_~{8}eTyF1?M)NJw)qIdvXa)7;14`$V1o!XOAZbj3aNY!x# zPRg&R%B&w!j7aasy@nTgufI`pb@!!WbrKBgM;L45ttH0|R>t)%v!vDrsPwE1tg@+I zv0;1&_OG&S#o=_GH9!cVzgbq?Lzm00?Ol2lC(YP7`<eX1Op zBL3LYws-gq?Ex--2%0vFAMZC^mt`mU-P|up6s*02MEL0l4`YNLTn7tSgCNZU3Fd$x z?I1o+L8v02fMG>`qD;ad#ompSba zzOWkJw+;sG1vec`h|-Ht(S0v07{o5@`Y-H;FYNwa*acI4tF~wDMZ~)0&&#^0Pctp1 z{gUMvmm8peWFHq)$EKY z1k5>cuz>DA5l!f55)d4{c0F%SZz9gQ91N4Y2|%mR-g7udgzxk+h~9j=FYJ3$H9Ukt z5e|)f>a+JHpt?n8$<7rY&It(l)S@|>6=n6)|0g~imI+E{fHzBsG|d{=GM;1u1viNm zaMiJ_=mL7mAxT&_DXoWooCni2vZ@@f7EeU|?LEH$hyG;%n%oNdKi=4|Qv9cU zV>*5Ffu&n-cl*OO27j_ZE`tz>OxuUQs6UD)t;gpyr^46H^&nG1V;?_qO}8TMB!P3g zd-HHW>08M03_J_N%#cGE9{ZN~K>Hp2_Ri@H!Z(8dVz*D?vo-wYCeQybXvN##KB{ll z_X|aqU#}QUhkk)9f7!Pt{{HLOd;1qZiS4ugE;fZAj<7Qyln+S6O^-xw{cO9#n;eOt zbscCLhUL=td_^x|{DIKd3Y%bOH(AFZEjf2MSkX|mREZowzZxiqwXYmUIhU2bi9Nvp zKHk&J-&jDy=c6UB3^U~J>I+IsAf_79Zyyq*qik4FFhC#?B!@wWhr!=OizLT^$>D+o zM^Hy>Tf~I2ncq`CE}rN@%G;PjLI`=DaAG-B4n9P?U0hfe$hC+dB#XnwN#E;C-<#3l zWpD|dNkI@Tg>w9KuIRjo78qn5Y*mMwD zKY?>gs~>Dbz@RcxIGP1AnH-^1A|Lo9%cWcKnx{M-ke2|zN~^kO^b=2@WXj);mVMeQ zY`@J3kDkh%oR1+ex#S(4YDqEe(Q}|^6+JfGR1 zj+t;PBkS@m&+iOZTobpIi5?!cdN>>?)RqKDD`E&pmt|#8N&)n!fF(~jPA01+ms?;y z)Dz@eU`}Ed6=cc%fvgOkvCQ&ST?3Zyy1d4C9=$DSNPnp$9{y5)(@zq(PP%c$ zU1G#cD9$pY$E4oz3-ZQ5l`IbP%4sEj=_F?Lj^@@EZZX*rBJbWExO52Z!TV$(qxVG4HG1YwymZG7+N z+5EQ{Z7%3x_(LBK_0F5oRsf5B#DIP@%O7zZH`3p$2p}f%b2z`9iqf(Tw`vu*42OJL zgPymy53Vp!6-v5IlDn)c{{$?vib^K-0&PW(Y$3uN(SHE24A}1~Yf>ZSX9-nlDQcK5yh}Q` z2*|!1{O;2PdVoNB!gTL~j;Rv0z_{kqu7zBYxjKOLpJW8$@<>49`+;%g8NRNqX|PnS zo1#w9Jfm0PLwX@VdJ#Z+fkAqqLGrWt8$PUkLIg6t_Ok93!y>qYA-ba>z9Qh=YH{p2 znfIyEtVDt1*&F#eOr>>6MkfBuPEp3aq6m@zanPyE8`RJrY=0qi9;h9pIaZhqYn(zh ztCxVC!NO|ve%t>j-s~_%ftN&H$|Ep%HWl^2Pe^t%EW2mo3wtqaxEGq~MBXDiMyM$^ zV+0r&!}-7#sG)Gbz^$Xv-jh4lrrgNYCesIOUr;y9KN$>ZQNaWb2P z2OM;)r|K&nEIMSA2EkgtKz_5< zdVmSW1wl>8*j+hIKHyck3DW`7K}Y-|r(*m4u=jeimbOB+<1+ZLRi!GhRXO*kK?1ZX z>o5g)0zZBenMZbhD1C#w9s^;kv z!ijQX@+~>9tkm1|y*b$xZb(qZUMj>ne9$P?tB?ohi z+V#JJ_Pa)i4F!tT50PU3)nkZF%{;Ga*TvEU?{6vsf-UO?vZVU?5}?gL!Frqrkh&|J_M)O_k>rvv1cbZ|w`A(H;%bIH$MU-%$-yy1JA`rY1KyXk^>J$^@oU$pXr0i_SY^_bF2qIU$bHgJ zq7bgazel?-5uQk&bXEe(w$x4v{+c9Zas|;3+eDKgmu!7F z{Pe<0K%J+5Xd>7uvY2P5-4M0%`O$x#B+HNVP&N-}m9x^E+x}4L65|aOKL^e9Byi!2 z;1dkOa>t@7pY11j@@Uia0fk$_o^S7hD886fs_7wn98@40L1hnyYKp(~>XWVccTj3J z3k1-|d_mm^T3nD-FpxYI- z_T~3PLwQ0I&ULbg4xa&hh)XJn`{bX*oRBa4VIA!vh&hwfe*Wn+OFzjNR)5jySUitK zJI3QD9L+O8bDi(Ug(Vcc?E|J)F4jvS5qhoZa`ElsCYE~OF)A%I8`p3Fw?SHbk)W^PLQZuXsV=z~J?j<{MGzV;f1<{z`G!RN z(9jk9jv=}t4)5sE?BTQw)Zk*vwP89Pmco&2t%C$@J53uFin zh#%Y zn?}0Sj4p2NS6^2aH)e{R!#S>tIaY_)>jBaM>VeO?G0zNQUMYow8U=zH{lIFpUlwXC zij|>YHk=HrD|=ho@K()FJiS~ZK`p3(8&qrg%L6Xjgj;2teT3Q|&lb_ z2+>-86qS1*rIP1g6AnBxNnKz=8(NfXCoh3_o>G}n^+F})gjlUgwDPX*{~1Yk2CFHp zoxtK#+SXc7l{5M5x|mA#F8-Bz?^5k zxwd~)oBLDjgYQ$vD~Wc)WU5ARM$&xOw6KYKjptg1ONW0zwy9LJ*!6eyiszc-Z|3lX zP6wM^WbFP@`Tps%<2l-~bAPrHctWiB%894Ymq*0;}<_=`2Sy+g~u+C9aV*@G4J(aevU2bAzrN z32Z$CR8?8J=2*WAC%e}aFNbjxp9$8QPe~>CA#pe0S@gYd318?>x>2_sC8_u1Nm&*8 z(gE;H7cig_OUtm+S3J>)A-`zt12j3Fco;9Vf|d@@Ju+1kS`+zXPI-Up$Z}`fOjxw` z6`yADAy{B6PVi3<{uyO8Q?>};S97zNURuY!ere+`DSJImc;++Tz%M(?l#4?BgGyi8b`U|YrVqH{{X;25sAc~EB zixe&Xtr7)u=te*r)eaOVr_kM?rudZDg3W(ssjdJ>5(V-*mao&9nLomHLePdqpUW;2J)y{Aqw8TQsKzkYCfU zvJJJ|L1_7?smYC}%O)ZnNLwX=V+1qPBy)eVe(xqqh1LA8PF$8eS=kRwKBkp{b4SL{ zgG43)_T@Q1!4CT(3Vogex4FwUh-uxX-YS&`8`^E zBd~K+goVf%XhUXnU%7G=pJw$bdw++DFAzN->c}zK`Dy}NEjAyl+vEfwRwK7lm^@N1 z*Q@Ka%Ac9QwrPq)Z`AlD@_yZ1s2)x_tQRs|2W+CQY`5sAUW+=kZl0pJn|yZrS=Q0f ziM!okjzvL{0}L{x)0UVx>IhRAQ|W1`Kx7-)nPGoQH^@3j{k_%cMTz!eMOZ!^fbju! ze+*$!HV7VJ^yl>?WtdOR6OGE#Vh(ln!PWgIMA3V9bQfU`343&O7dL>7y{O!y?FNgv zRJ(1^N8Fv)7({+*zLoOnW^v}P@pqads2=EI7ONSfgheLeyrDjEIi;>r(0B742wb4` z9RLh;@qNZLN4@c21hq~MdlP_~X@;d$$M!j5VeOvrACgt6zUTW*um?-4zvqM*S*yQi zhmlN*yZ9xrkp6^yQj^m#)H&e&2MHY?Q_Kr_BS)v5OOJDT-OLj1(u zWD;E;u8EUk++0TjoiH!MRx0y}Nv$!}kg?l~8#R83o1ljf=7RIB$^q11QJ3FcapXwt z6Bz?8<|=<_(Oo%Uw!A_CFG95n$Rw$>n&N2G$s<$D#Tl&M1@q2d02#i-rWamDRldSg zOT>MU*P>-hFJeKyAOr7%_Kg25#rd7#gnip4#xAikd0wU%1^L31!AU} zuMv(^-DgcJ5k_i!vdiD}7-+iXm|Odi)iFXS2K+W&Tp3YNcBkCq4`@w z%{}7iLFt6?hdcI{&Ak7>3U?k$kvE>oqe=LO!_X(h(HS)(^jrJaOat$iaL&=H*D-LD z>J@XgoZ)dj%m|A$yvr>IulToIvrR1OSTP)w@@3_T+aOEf$76+%Vvze?RTQ%MlSUk% zwt#OJD%BTn>)q99KIPC;({YH5*cB5 zu}5M+%D2g6bJ?aq2Qg_N_+@ihww{?j;}!|U=uNIabWWg`_3Zj8ZQE6i>O9V6)6z$K2*g$vhR#~%oRR}A}vY^`rg9{jI1m2Pht=3okd*q2egvk{_+jgeE_$?6 z4Bh0oR7Zsg7up9E4oGec44lY}r-f_YZ9L(nz`8<&T_}XoOM3Nxolhm@gml zwjj^rqk-2#3T|JXx{pEdB~dIHD(jKtPi`Hrfpb=d@4wjyPQ41>|AYwSf1Z98zX2Rp zKfPMAtcoqu@TWc7f3Y0>&8~$o+I(tvYp~Gn?oj2zmt1UUt$d<>^a8Kqwv3Iw{?%-| zIN=AUHZ{!#$sUx~y`9&v4hozo`FV8zsITVP%fQX3K_ytk5<{@=ByNC0jf_Iv7bE<0 zhxA$9_wGfSg3EyX?g}C?*n}JilSnR)N=Gh_ULu)BI)&Jk~pqCf+ z-;BCA&N|4bs_0Yuu@M&0Ys#OA46zSKwWtb-*+UrT19Liro+EROVftQY!wvx)l6qr0 zXl>4(a-o){l*cN&AphB={BrRv|AEv!{XZdf|8KVKe^l`Q>n{CoA$+$Fv^#JZ?@YKf zcN>v{6h2siWQig(_(xH&Aq*%OZ4!tIg>?cXm<*PRIbEKyC_^|+pfq{}B&ISLo$;zw zr~af`*Yghls%vuB-&}StS9Gq4r=FL`$t+%{lc~?{sVS`-UXQ=5AUGtu$A)|#JEnLa z0g>py&&){T^4EyS-166uNQ3g%*l}NzUj90s^S;erVGwA8&=%nP%h_k z&A!0L(tT*9-hfb!a1jD)X)*IpdAgao;`~sKskl&n!z7NtjD|8C83``TLV|^K6(mHK zjL?bV7FOVqGHXiYk4I+$%)|1rQe&_H{`ed$rRumH#sY2DWh!Nx22zFmOQ0BCe#~N7 z+K*ubx*11l_F}CiqZZQXeAd|#jZ+n6OX&xMajETzv!1Ouy0Z)JqBmzf5k)K&Wf^dW z0%O+s?nJSQgo2}Vp8;L;)pB2Y(i*iluRw7SR`bN+$Al0P-_p-fX@ z7>{mcVe#SLT@n*};hOK@QzF!vwOQ9#I(6Y+x|^QlDk4z#$1rB_Rx(gmq7}cqEhAC^ z;+hk
o{)Rh{>qN^!2t|YZ7yhMb`1gu^Ix6Gya&z7^D8>9T!6q*Hro#S!Od_|eX zKA}tI(ydCZI^}!lJCeiKY%Cywe!U3x1a}N`bqj^Ms|wBlcA51q+f|S zU9!VgK!VZ(7qNG2y{TuGyHKw8 zeBnmg9jfLt1JBRKHo3ND#$Z&0Sg?_zw#kqIoGU{VXq#73v!kIZysfdkm&*H;=cDI4 zoe=uIB@)tWtNrzvk5IJ!hG0C90q^~k%n5FPyCAYo=ErNtU^Z7sqSTpZz`Min$hq{S zb3|{Ti(PiEL2$ty7@(}(+R(wE6w-$fxka4&g5TY+W1xXXbFcQ{A-%Hh7BB0b=G+}TfHT8>i&Yc<}{un(i8RC8EUAwn7 zBcRhT-Y&h?;AftJZ<$B%HX~012RFcCMipJYSg}papWkX4WP-ediZ9HmT zd{lhX)Av7Z!#(-T^J&sMd{eq0pRk|$g)K@u8{Gpra*kme?P{}U#o+j5 z`HgYx6Gp*1a(en8^c{s?Re9n_1RSu<>Ifa55YvTu{7w0kTo#0| zL8_AC4}oVni8{$69*wMaT&YFUM-Hq2>xmo?VSJ8LRZ(6rkt;8zVA*M%%2hS+zdfLk zl@$_nQqx#DVt7!4f?UEB~utc6>8d-L`t5O4FbfVW1az?F%;B{QV-HFl8;N2#C4 zfP_IEl#+>$-~)|9Q<+8Wa83x&q8q^*GqlI|hUrFgXux3w`~etL*LLL$mKPPx%nZvR z(m_PH2d_GNs_#jSN1=i5O$WY*5WIaVS>1iU(a>RWOKPmVT532>j*%22+Dno5vq3wB zRFo6P%TkHeJnqAH5A==IR@^h+svR#enU_7UE^S&<_f6o@RnkdcZ7TJKzE9BA-0?Oy z_aqlq@4OZiGC19`S!rinarle9uaZP&wV79LE@YvA$2BLvhGlm)+x#AbGg5Rb7j#ty zfm~0};6SDc_Y+d&|8|}6J~Bf!E0{P&e*;{b(0{36s(X3jTc=$}5zNCRWWkptep-R{ zD|*1vX341ZRa3VBQ8ADBEbYJtV1n4rl(e-pOba6qr;Fx|by~3?87Q-u>`C^~3XTds zJ~Q?hpU8;S_H%En%HUe=Q{lik;ji@3Rj5hWZ<#ZQqLCn!w5*0y-QcG&W>MCj<;Jw( zk^5XU;qArbb{JPX4ok+$L_w=-btNSW8cK4kWII*9U8|q?Dy$tRuC_k4N(X0Y2*3$L zs!a*yQb`$4YZ>73d@4i$Gxw`dZR|7#(kWqz99Y+BbsV%Di{}cML8@=quU3Pl>?esf zd(vayAY_$q8Vvib{pA3(Z*8Qb3ZQHi}UbMu>y)mnmE=1LL{E zP0q-qt&oMjUb|gHFPXJ1M*8O>zG$&Kq8Y~ozNHl`7zC9jW}h>i-dSaN*}Y<=MVZyD zT8IL=T|K9n49F92ov9Je`^e`6p0b3AGhW!=wXmO7<=qE8 zO;Ow=b^(p~&v27(IJj8#IE_AjraD<(w*g09PW+$dbJZ3FvZ&P)9U&=t14zp~m_-fy z)f^18Xt<Iw|HnIiAdD+hzFk)!lCRap@TrS(YPL zm1cfrhYnOM_joRNn$gz6xGk|B16!v-x!r5aO^Y;{(s#B0CWzQ{gNSrx6YO8B>hKW0 z+J8sNsE2Fmg)PNhOrSKXzK3~N&qQ#W&=td|SGRG+2C72$P9p*#EdysA!IzH?Bg8&e zdNd}g)3z-2(Jt0%Fid`UQ#FN!{ljKzE4Sw*SkJIUffI^zM|zJySw2`=fs3PG+0E2e zRaa6|=4(~!W7MT0S-S{_Bm4o8wH&}deF(3Y80{AgfJH)gwCFXJ4I$18pSkJjVTh5mGFwFzue6@cDH|p9P710o%ERtkij(iYpsz(!8R7AD> z&U#&Or$Od1geIQK8r5wyZ-+`$?QiK)}2 zz3|_q*v)nPjzJ<7l^23RG>N>_8RKh%kFdQ#v)1|PvVSAzX)id6d%`!NCbB(=5=ZS2ai zZmNLfjMKP@Ow9WO7n&+TEzK10=8F1_>I|v-j%Ft zGE?qxf*IObqbYaLREo*FJ+LX3Q8HWc4{t=l9fdQs%+^5r(K^Hm0o}|mNSsqBA9N&A z>pT^MD8hBIE2C6_)c3LnA2pX(OWJK3PDC{|CJ&Z1S`*Gg| zL2F%+AzkSsJz0vXpDs+#4Er3&<8&Hm2vOlxQO9(8HLl~Fj(wEO`Np*4`i$MqNrGp_ z*o$)54K7Tsv^qBlm-Zy>`nLA<%Hn4~mpt05SkK77c8k;m?wcX1;KT%k0nLG9D_*~Q zyBan$lA9?0rEcG_2pc|$*ofoV`|TxYOt9m)Kd3XnF2xm@*sE&&sg!cCeTY`O=VfY1 z)jKv`ZLDU(5=)`av0mh~Zj8D%iDqhv-rh@?EiV123vK1sz2fsUq283RX>D7hzEXX> z8`P0QII(b6_!Iv-an&)W zP&}csCzj+Y(WrKJ;z}vYqKLoYXyZmnA`7Ib!X$U^;o^s6T)2>(&A8O)UaV;1JwwAA zjplkiOO&;#%ue-Gu4}{kCX>2X2LEYl5nB*UqWQiH<_MmJ6mF?7?Ue7hFkjf6Z5-o~ zm;J!g&nJ)RapeCcuA0t8+J)4%05r!M?m1k?@uxUZJEQ=HtAb-oG0OdSXQ81=7dvY~FxD%W{r`Kf*t{W_pucs0uJ* z>zeB&8#LyRUVpy461)c^u8+la7az;us5Z48Q8MDDNt3DnMF4410xhq-w zkHqThkuBE~B)u>ArREDoYvYDQiwC)iu%PI-rJoi=(V9+kFJxo{ytlY+P%<{u#^>>t zkXvF^SUl$c>)f%S4-jX~t+UE@a+)(gIz7QSnw_90%*@qbDQTi9WwEo&qz^5Pk*cf# z^gX;~Xnz6Z_3u&7Ht=NK56G^u40Rj3S`red>X;JQSQBq4-_+7(^aFPeVqMuCl;$$lU1TeCsc#s%o12tLCPgeL7L9tSj zz`I3`ejXiy>#gRUkOBMd>Zh|7*XqxBtc&j`)E`#pww^jam=4m$THgJ)&9A9qPIOcd zmnrE}UoT4%OC{mL2t?M(!8z(E13VL6%dkq)GCeydX%X8&y~S#)P@P;+rx>cL&@U6u zTH$<}qe2i)9B)DyL`H5o2YP4THMU=mhsZW{h)8ibCDrt zY{<7Je>Y)SgRNc-A(OHqtTmDKHHFW84ZGZ3scBHN(pZ)CA}luAOqwaDB#b{NK>TPj@*vK)gnjw4({G@ByW%*JDI!Ko$h7K2!3Lv2l7JC zs=S3rv*CI#?oLl;10!Skx#b6sv-rLMSrp|IE2BokL!^bnDjZm81Z8-+ocFPJrtS0j z6~0T|TvlWo=27yG9Ccm5ojG=;i#Dnq&LW%U^?C~{g?xLw7$q!`$T(&v2>OM&tV0jj z;V=&cT8U5fdCfz&_QKl~%*a=hy(PA1_1q}(PvC< z7St?X?m*G!-b{z&x>^j6a!`Q3)~b>^_Ljuq2>F0TB2qrrM;6>dZG$aX%c%y*I^C&; zw$2KNJyXbUSob$@H)4Ew0-j)iDShNPO22A&F# z62}bt`=!?0h~mDQ(CrV;ofgentb8<)-=D^Lw&0sZ&G*&(;T;8(rlm!`a1+>=#{3xr z?s3^fRyw%O#$V>6f|iD%8F8Udj4CVU_~`RqLmwM*uIJI!s*87|>T&=G@ zQu8|zE+;objZB|AgJ`du@h-=!wx1rLG1)^MChOog8KO|o`qZ9_Xh`4>l2XJj1YqOz z#9-^04lo#YU5+q7yDm={4!bT_80T6YVTjOG8v?M!OD^PqLlPeJjJ{^XTu#xYZG!L| z&0k=o%7}O?8~xH}Ae?i!U~`x$BFvg_`eh;CN@0qZr0^;Inwp^KhM1QjcGInW#@$-P zzC7+^a=&Pu9dWJ7!}Er$^u?7=nmH&U2dvJev65HWP#mIH-w*KlYM%x(`mMg=38)f` zK=5h8=aENCae+78c|>*dbMA+hNGX#SBz?x#DEJKeGm>#IG}D=(5b&t|{W{FzaVvMI zeA?aCLmXTXqN5R7RQ%w(`St4Lbiwk-5JN-4g~q0V4bVUj;ce4WqjGAp@lDFB*3h-(-oE-)*$NivUqGZ<|A z@dolZDGP-he6l#|m}gxGS!PmDm^w*u!K$ijV)-vM5R0t5g~3jl5R?5}mhu>(`GPfNzn zfia9x$2D_!RW4XoN)=*CfgCh>ct;0lQ&k)2EYzZ)`9P%5yr3U0KZ1kFDQ}tAKiEZNxi`!w#GXha8lMLYD9+$|;lQTcEZ-O{7@{&#LBrb;Xsj9l<$}52Iz~ zxXV}v)@+hYc%gJ~iY}kh>H+Y+LM7~XvcUe}4H<;H zE{;mK3a)s$B|4$IScAJ0{|s!Rj`z4iF_SXZMt?+@UQgc4-L-Gpogd2$Hs|Pe;87DW znaiea$&wI5z>jr}3Q1}X;X7%B1&jO%2FLtkrIO^Du<-Xu^%mA0 zarHXEG1JZAZt7MC$4zAVbl-@D!lIl->)&JHW`D55i8qOV<$vTwgK~kh3d6JJMziE1 z7Ov~!jLM=uz@<%K^%1nt$g7@84jG0<_frLk288slt>7TogovVjKa~o%BlgY0gtbBs zqgm4qM8zXih6PyTZZsXoO{_%^#F?oPXWR-8 zHvkX0vZOK2oYS)vMcsxwZM2~&;O>)bA*?aux8YU_rZU4~(+P|sO_>%=Ni^Rvw|a`U zW@^Z7CfgJ^X&j@{&_dF{la>D6N|Vxy>~mz4MzRzGwiw}V5O=(ebbVVgH~EV&P#;XukH)=C&0Ssd%}@FQ|GbibsY^A)^@61Q%C*P!LZtlSu{NnKO!onQZsgua z@xmrDzUfE5@_9}2fib9O-lKk|{G91AV*5yGHrZw6{>X7L5;lx+1yju-X3c&JK{V}c zU|;jo-+cJ-<{62~^zN-OW*-|kp zFH9nFN$8NFRk5SRoa894O(I21cn@_1wFzdEp18t|#y0>GP` z52dr{w;te>wOYfZR^jM0F!<~l4?n1ps!bWmVD=)RtOgwLN$WyKU7|QlW2~|dxsw0+Y!|ADn|6*)mB4r+A`|JQE7p;%4z^ez|f2U^y5;0`Z0%d|qJ_ z%0jU$4h3Uiy^5M9P=lt=HLnD+up`73CWp~c85^%rJ4?kXutTYCJ7%j42paT$zb)nQTji&oT6oln{l+*D7&jQpLxgL`KIouh&UPOa4 zCPI8osDK4JhU{t|!8zZpjE+%26Jm-icOTrjWSi0kXsQhVzM}=Vb;5I>>p4}MOb70t zr00Ipa#SR_)h~-? z8cuWYs?PNlJ;>gufRp7{l?8nk!TB#&BhB&A8lEAO#>PgxHy4Q%7``6|2GF+D47rN+ zqp+x6St$RX&pss*4D(&xEm|!c^IiNcnj$Q-gSdM{n2sUg5KH(=d5wQ-s6c>=6+f8o zF~C@@x{?+>)TQo%a>?L}*CNf1TLeF5Y{5?}+IbYZ3)NI6DB=Ke1~ zIw5l$aQVD+!6&$+9By#=>y*JIcYj6u@Dk#e=MWQfck;%4NF;xR&N#wROq9>5J_l<2 z2=jFm#vywN+rI}Hi-#UC=SAO13LEIWXL%JN0?i%Mx@{ML>q&IlGxOm1q&fvOW{q-q zFgT4JY9?jP9vs0|H44Og95rgXc~D(a&i>MWvtCim!G|OGAAFrta3{C=Y_sYf>`yBOGKH8JMe?#9Bh6$?MF9@yiFgL}H4M=H#@RVh^IP!Zx(QMfB zJ#csuhH#fIl-`lpoQ^*1S-LlTd{x2}5GEBv2$K`tRN_S+#i~em7i{V{%~d!#{DdfO zP`S7+q^02`s1!dc4A7));#9qqvSk7(o>ZbAqPkM<2I$G9!Z*ps;>OTUyYNrA@K3j)FYzHi2;*Lq`kffS&Ck0}`0|DL`5p0HN10GRzPf=B%l;DNV3E`UiyVN1)eA+GhRB3NUaCqZSrN%@E>J#JVEgIJrk#lA0+x@oM7_@rfq88 zpNpe1!_E(v^xCN=S2GDvy@;Z}5un}MBkI~y?6fjbV-|9Ux zGPCyeof&olm}&?CHCH2>gnaWgZOelWdjTyL=K~f4V;tr=6M;n>>;k6|*PSTq-i4n$ zQ0ZNI>Dt8 zT;L4`3IFL}GWa8q-6JsSd|@5EV5BpA!?WE>X;w07mPk4j5D$6{|B;IXu~*e~P>cvP zk>>FbjR+l0!SoP1`*lO*c$=~S<)_Ro(zw5;i~IX-$PE^pJns+_R(3B-bI+k=a{aVSw_ zQUN7W3A-(5CbA@A_K&G9%nU#65C8kHR^csRXuf1Tk3T%sICVp(UOVzxq%#jC{5gUei$N7 z%Hut*-c$DpF&NU@)A;XBJbthX*??GS?wS&%zXnxUp#<}dD#Eymb)!);GsKL>@c?)UYOVTlzj+Cc1QfBCl^?ou&wtkOJpk(}syejLSqdd&3u zR%pmmN_ewQS8^!*o73d z_@e4yVKX#Y<(ZI*2~S29EjWHNxMZ3Wk(dVf^W>;G;M%Z<`j7FHr6!F1SU1E4Z$XUsKH!g)G6KoP;`I$p@E$OQ$a2I)|pvragEt|KY+P>7AV zwiHW~5DUA~1@W+E{}rQ;JlAk>C@#=d4?Zlpx_`fB@pAyh1fezvyURf-7sAupby_y_ z)!!zS+Y$0+rs5b5Q;lVKu=}-F;7R{F7LXn2=hL081@kW*1Cp zH-&5Aw3S(LNa%Yq##<9#K`S8+87_PjEi#SyW8QLxihwLZKnH{1G_)RJQX7t)lM8UC zAtggjSyw{zf}6j315sx~y3k2z8i^cg)++ngf&C*^+Uczg>8|~J`FmmX_u`RTos7HD zMUH71RiPf^puvs^OA}O&G288rj%%QVtB^Yz^uqEpqiRfmk~M8|Ii6uEHpGJ}2dz3! zzY`n2dX?TT_A-dhGAN*ee8A3{!&13(FvuFgL+T1@bXotlWgUlKC24QRnwqsrzqG>2 zXuN&$xF$-ECe=zey9l{$k7DK~b-Z1eAQJ{>4n;>wxU|3zqteA~oO`_ZMrfLt6~znz z{Eb62wm#WK^}7aB*KyhMcekMKj-TL?QpBlUVV6#X>>Indl1_Bt*RWC(dXc5SBWm|B zC3j4sr28qjSQ?1~30_q(wb<*hJz3S=VRwtAuHXs$Qb2xrkf2JK2!tyrX+;sC3LlDi zB^RSO9$eBA6Qc$m#KZEPLv1DkMkUHFvn#P~8Tx>}EApiV#bD7ns)u$C^tYnSuAD2k zPwh>bR0~$Hks^wPp zpmJ7`lN@GmUXy79S;(W-LPw0aH=z|cnrr#a+r*u>qg~4U*P+9MIy$x|CGh!fGl$s0g~!LkZkv zn1LB3@iiuQ)D8MrF!4Kp(tb0J0uiiStB7nXV1e2}rxEQzD+M%{F<5RgF19i)u(lQf z%f?|trSqy{OShR!zf&~3+}W8hS$%VD+zo2EN8i>>t-u;#b)StM5T_Mb!^R9s?lmLN z>Sj;orh#%^A1o89|kaU@}B- zkrz#g3<$fEvs+$oUQ0h^7fx7yrDyLDJvf84>TXU&K;yG+ekxr4;|`ed>ey!(ODz zH(9-W`6|DXhe&!0%<xt_MBf*?RSXZIndHqP<+WYNYS!)0VLffE3SE{7iiAV zr(!ApFPY_{Q&RlEsO2!D?l(%^5`OU2%D6%MC#g0uU+A3Son81REDuRvbh^QvJH7g#KMczEfT?{YP#HL`kfJBrPMlo zR}mxT1(C8wX!)(s4A0;>Nbkry#f=*R-i1l-LbT*L@2^Y>&>}bpyH|9)5G9|1I$4G@ zNNqKYTZ`^AzuR)ux0NO%4`soIB}>(Cl9M&3IvLkah>F)CySJplEo{Vp7NiC=5lz{< zE$ey;6}9T+9QKl7dCPxY>8oO4%4;LXG4^&4F7HKDl5Wgn(2#ppC&N6gZjq0=;#sEW zzY%M`;O*h^vqtjcN`o|53VM(Kury(gEf^amuKO0(?Vm9F8iT~RiSONDN=)Nj+12_w-K@KC%!h_eCNC0Hl)(8B>H zu*$e?cLV>>!9h<1eqC#k70|I_#h&bi`JDhJ(QY~?HT2$QO38?w*=AZE5AovQIk!u4 z=tWA^#&xP@8dj$xm%v%yYxg%1_mP?sEW}hs629%~V0P}X{D{=d6&`h-OWK{nT09mfr&5Yp&s$ySlZ2|bUj;37*4N8ZbAOjgTp~ug~J7hSX0l% z-b!3+?sob9aC2@x(BaKJc-Q3qGefF447qrWKWiz4%0C7=!Vx-#A6bB{w_@V{;}9cE zdM;)^upj(jLcd90#gR}oJ36<`zxV>VKSJxG$veWyJH%rvkwg+%pe9YoW2@$Z^=|00 z^X4KI><}N?RG>}F<*U?2DJ_^Q)@ly*>Tp?2ziby%`(oCW0VT^qMd}D)&EUyvsU( zI-OB!0~Kac-IK6H1Aw{~3poe7nV5Ra2u_y;HQLBJq-4rsc|iF(#*)h9EUZZMPrb5j z!JMZ&+`}_ZBy%n(+kxPu2Z$E3F@yl>Up!!xpk2x)&a3A4f}&?Z&8fvL^_y$A-T52{ zEaddLj385g9^zln;F?)=F@b3=@Q7ZcJYh6<6G{2QH0+AF?%(o*B}_nZfi{P|{*MvMKbIB*-*PXf%;H zLP_n+H=V)aIJgl&vhG%o1q<*ze~^9o0c=+TPxb}UT3KBK{GC3kJ;x@nR_=x zNm{U{H|WDhO6^}2$6eTk;rU+C3A$|fEaMPVz2b!t{6-*lv=Ll<^5=t|^;_3K-Kkhu zre!IB_p(papTX%8{)~|2J3?79>w!kVl#K$dE)b_|EQ3NgXxfEr43h{iUJV)1f8>Gp zwb?#e!6P1(WF0RfL2wP)jcn@$aCmiv4jeU5`o~M`ym99YZwK9Qs!wmQ(mm^wCT&jb z*cLTzY_itenT~@vSekc{cQQfPVcR2C;i1R1XOG~JR)mQ-c_M!@SmqUG`a@hb-7tA^ z0(CbN5Q)8`fm?nD^snDox+)B4)?h&^23!1$`JDOH6)p7~yL!%5vj)c@!+v171El3t zzD>%#-_8pacWy%@2_H`4Nz+65=GW|5&MsOv%ZE%{SllE1ZAI=cibv5`wVM$az6i0i ztqh%;eqJwy6^WZ+|QYt2htg>k{k zf_sSHfQsm_i6d=f4?Q76?os_mn@sgGj@G?o!HyWj-k1aTsD&4E>@*MXi&ohS7jH)lW=vgD7cpeF6zdad?Dd1h3i`DB)7gZdk9)j^(AV$Uou)Q5r7JoF zOZ_z^crxX?sAWY7WP)XLJ+m~0HJ&PkDJdc-uEzwm zeb|t`?F(?C3==oi632d z)$ah9$BRAUPw+OeUZm?e_k5!DkWfpG&9a@~P)mlc{F@;E^VUAcPj(NT9R!1O_r906 z9LwZ+vFqpX8 zAO*?@FrU>B7`#<0Y1qxN9rza7P_~NWnT!Wfoc6q1_5qw zS%_u5A%VB-E~`62ICu2LXE*)7K0%sL2nq>(Kv5p!=H-2WRi0*zO25FS=6eH~KW$JW zZ+4YGA=-omfN-7&_Ow4K+VsD{?3esQ^xl3uG=A|wOR#KOF>)GH-sTq!4u%>Ls9}O! zfvGTR9K)(Hp5l_(4&mN{ajfnl^=qTVIvg`uhPBf$DOeA8y$4FD?poBtcPQbybYp&- z7SxMIuzqC4`is4C%;_)xw66Jm{NZ?pamf!vGvpvJ61Ty-3h*h>1po71 z9z^!NM-Y}6Q?gj%qU?fgKxMfr1016$XJE+pCnYj96w`I!hC(D7N$TQAr|_1qqPxjw^B!Z92$ERh3p7WoVYm2G8RBR#uP+b1TwI$%xyaw^>InbKPkum*m2_l1*t z`k{9#jFahl-v3&t$H-+wgIPbz5s3Z%Li{@vy|x*TNpKz79JlKal?HCt*fPhf-N>Ze z992-ygvan#bR&{9?>t*)et6tJ1?-3AZ&z8=qSegZNX8n5!h`3L<$SCxMatTMnGthI z#umX)M?UR8HH;GgaL*AqMO#~m>74-JI+SKV3|*7U(3%naw(&No%;>B=vIBIFt+r+P zVTpnx-cY0}*i`@ zj+9hqbhH0(&phbQ01TB>kdfUv2;krjnnIPX?dv@zTRGouLNU9t<-+<=-+&=_<_9iy zvQ7^HNFG@|{}6nsk=XaPYEHc|%14C4*{_94Ix&!A1}%-^@?EzR z@I#dkm{eOv_k<6iG%Y^hY8i9I$-KecuxAIZMjni8z~Ak(uPx$k|8`W22z&~@aoj72 znwAIH)^GcPxrl&yKBD&fNAuD9EXBRz$LPu+C%a*8Q$Z(Cc|cby;ch^q_(n5pD~7y8 zPUI(r-^^Ir@|(jPdZ!Ay5oP%7ynSennT6~7GED*>kTJ#_>@w+x)sEoI?RcPsV*M71 zy<=av&`Y=M3L81|)wK38Tr3g@HCc&0VvOG8$~F9!hWN`zWT`rtJA_TAq1I3a*pXi= z^j`n6|G>EOCesKWBaE$`wm0$RvSJwWDtx~JU2fd*#^kpQ?g6x+D9_E^>@)ZSAn_Gk zl3gE^NSYo*vv|%VK8Kr7+@IN{rjK5X0u)>E_~t zxGdlkQ<|EF9YzUjP}Wm3NK6LENDmf4=`w>u8Y(h6!(>Rf{kM9IoB$gHR!85gRc$r?=;}WdlfA z(B9JZF%3)mDOvEyGqJ|*dl(0CK`pW@`ox_aoW#Uz<)7=k&@OYj#J}+OQ(lye zIEIn!u;!UGhPmz3v~@2~O^oKzh=9?B**=&s-`MaxeSY8_)NEp@7cpTYQ*Gg$%b}V& zHYFd=I;85qaF)kt#A@0!fwwXt;1Y$LSP_eRM+n)RcC>DMvOtIK-!n@$HCon8x+-4`PI{`)PT;ZE#(Bm9Oh__iJM$QSK}qJ_1#x>{QEZaACHeA```)SL~P6JjBX z-v&}zpQi8+S-Zf$Lxk}jUOQmWg2C&Q=j#Od(yqEZ_|(2if_g26k+pw&U|{6AN}>_~ zVCmoP84&kn(#`nk@?PoP@15y8 z=!aaF%D?G!O2`E}hf5#+VfE#@-L?NWSLZWsIL(%8-$ z;`(Xl=n&JHD#Xa#-N8R(S7rzZUp-$%#nak#i4J~_Rf<34L>W&35y5MJe(~k3fOE)= z?<75)p0|R#b=0|bF^cAB0tN&DyG>*)3jERjll`f2C*LF?30p9|3WWDB{25fV^VdFZ z$lQifu(C2N30{&>wh6SXqpa9jIyemOV!;X%$O@~{2yx*@C>@HJaCqMPg>dzTaQ4$G#J^s4;ma*FqR4v& zQ9L+G)k(#2^?dpoQ9bPtR6Y#38EaM!oA}C;pdCjbT1Q>T6E6Bd8C;A(@=-E}91}iP zZu+30Sh(BxgLB3$@0rq9=a%cMxN`5`;QlVZW-x?a>I9|_1`r>Ei7+FTXhG`15<2h` z);HK^p)$wG|Gc5R`{=7jP_h9OqU?d`)quzh3)=j+J4gzyZnCfCc3{Jh8X>n z%!P>OMIiQ!CGx}(q+0&#@t4kaAACkh1N+Q`k^Mgwo@M<6VpCWJ}Nv#{38!~f+=P40UOp1F5It0 zq^>u;!kf-7sN~E+7Uel&l99I#Bp&T4;WqJn~I`nn0@_Sp>pL69|;n22;;}e0$n)V z&>{T2U(IRj9{PmF{oemJJhk|y&TjSl;le6H?iNPuVWR+N$BpBZf*rwQ5&4Mxb=fPQ zjeY0J-jTcYN@;M!d5&vpuOtUVMz#O71q#4)H|&NiD;go9^lx z9aJ5yPdslE%&d%O{APm?YiBtS*mL1cYvGvOqZQ;+91}xk1RpxD?(VRsH+s5l3{YjTRi^{oZuRMB)Adg5SN5tB@4_OmxORB3ywIa zgi!2*EanC7Po7Md(lIswYsQgrgA3`H2gWd=5psnyYR~wD6tJ5Oo0X$t6z0smd7cgA z&S^1FG^2If^kDni=}iBz$c3=&{B;83>Ph#$>52Eg(mpIdsj{ZBZ&M`eCh#6<;n=v= zd}(tL2BpbJSBCu!rJ;C-^&PN^&JHl#$rq`2;Yqm=5L`kk-2{<{WqiU1h?)n7(4uxg z!Ry=ZD?vd9s?%s**xTt@>*?4vYd5=ArQBq{Uw385k_-3V*!Xw3@A$fN zz4*`k+i||mdcBMbiv`B4MDwiELZ#TVX3Ah7^PxJLMD3A1nq-Yjr=K}ofbE%*MK&`| z4U=yC#~gNXd|$FjavT9oKm8I8wolutIR=M*XU1fZdV6FW$0?!eWM$O=87bYWIf9_J zS(3>UmM9jZIpa#xR=Ywr^OWDpIZJo`+LK6g(Z1AIqPF?wL(kSBhO#rLyEs(>v$-$q zr#T%|V^qKDWQAuyzdz1!yx zL@xIy?fo_nklgRrpCiFr+a~G!`em#fqdK?t@$vWdQ}6kEHfPfe?vH@{?r8Augi<{S zXr74te9{eg_mSSk=+d;?U4YWy>y#0kk|f$kMReW6FW{Zen0j#cCY5@4XVNHM?`?W` z$J5GQ?{Ru~r_)S)xUP|A!*|a6B2a8$W|=8_AHq+D9(+6l7#N(kWHw*T=(`7!de4!1 zG5+2iA<*ARqn{w?9y0Oy#iu6%~|4IaS?M+(Ct32|Izf$P{6PZ~{#%P0d!* z;%&CHZ~xQMrb$?0rS9yZ=G<0XLH%PC8ERfyRngiI+!`!cHVWWp!NyKQsI@MKuYqLe zfaB-Tbk$c8`P^L(?O!yn5H|tSO~GJa2^EO}wqluq(?>jffiZ>amaVY043{wg^>gsT*sX3dNl6`WHQyeXP6ZuYISR1VleTxTjWZf=fYGqwAt z2;L;Y$d7mw2)>jmdRSlGqZO1obd5k9%3lbIEuJCMgk{MM>NoywXVK5RoxUz?|rE)L6t44IikkxR?l=qHT0Vow3jD4D8Cm;lzZ{8jPPVfg73LWR@z z*toE+sOPHXKxUGFvnZRMr4`E#O3nlDwAcZ>~e?Ktx{XJj!Ab3fT>F& z7kbV!?sadbmW6I-K|%nOn<+}IOmm<%&jutP9lqAds7qcWwdybh5>NJT| z{g8z-K(r9z=%-hn8=)-E@9j4AIL?%55|;LOHKC`=YnO>zSWsFTK_`<&f*At`M{~Ba zgi1a;9`Abs&QP7M;pJrt`E%OqD!N=z5XIi3Jv1a#6P*r{EwB!Eo%`ZQdufm_yLmG;}^deORENu5--mOO-Sy&Qqf}D`f5>5 zy{Y-6s?QBMF*8=kRa4bsDXj5)XA>gR)fq6D^?Hi0{tyEd53|={BvtfjV!{5!=9iPEoGS<$E9dpc*|_8N`vsU!CF}zA%QeSd(zfs zCgH)qq1SlWnF?APVqRP#eQ`%R31-=X@FWoKQg6twPo~2=v{jRTCj-@;lN_9)p2l;r zhot^3Migpss)ubr%^32NvRn?Mr&V6b!>18c;`+x($GX~bEzfG{LeOlMq14%sx}_H( zmTAM%hTTuMCJ3L1#3SVBtdhQ#uaZK`*{ONL9we$wRZU!5!GOaa7+h6TwiQ(x|FUKa z;-(}nxm{`~XPNl`h#;^K11V3gM4Ns(VOxXc3aaLna?3%ggmNxNGZEvX)?f=&Pk=UO zlYS51kijZ8&T3GPpS5;{YwKIj9u6UhQ*`C|f6!QiRGyDn1Rtwo~=wBlJ_H+bk@p6PQ zaNEabxZa(dbu7Z**fURiP15M1BlmFRseLiVsCA5R@7njh3()YP{MsJ|c}>A+bxN}X zTqFBGMaB({>fdqPxu?AjMTzXIth+`AJ#jt3?cqXM$}>vXuX5p19i9ZM|0RAQH_7*E zcl90?Z~#PM+!DKuzR13= zkPW==bnap_vI8u-_jT^@+P%7X6s&7&s^Hm>p*_^|HR|#DPgK{gsliJ3qK;?iw9^}_ zxv~$?cA~yLh7m|ZUl|PihD7u~U@PDmQ!Na!PyfUgw99f7%-n| z!}{yZ#*pi3mDA;sHngJLq{_fw+TYAd$Jc;#LYvfshGk61A5mv7-@Td9r46qCyf5>y zSmOF@t;d>&VQ@h6cSY^u7%g*7Pum^+zD{QH(Ynk^OMiMc%~m^dMdada!KtkSL*r#X zbDO>}{x4|V8lME1qgBHA#d)%#wg9ha3w}N2eXb@-BzCHX3o?~{jerR2ABJ`x ztg*CTL`6qTZ57c<*aF9mf57%>(%8dQrP(}kt01Coy4DfxGyCI2nvL`m#zR*KiobIM zZ3|)2LZguM6DCV~bkposV~*YaI(Pc%Gs#CgSPgcsL)sN<&@732)`PURH!XIrTds^^ z1}fuJ#XJ~uaAji7PV~e|7jpwUcWGn^vaMt7n*<1b>(Gk{$&TW!AEIx@u_8&ml}aBbIXEbOz}_TsWZi5|%yzVt<629YG(zv42Z9DX_DK z%3$NHJ#y>n`6!F=%T=ia7;lg+jdy@&8($0S8i)m8+$;>;GPgP%;x8EmZURxCrKqt@ zUfnvd!_gyTaYJ5hG!@o%D{M=fx0l5~HCDA*Ulgq!5X)z%bIXL$ya5R0}5_S{k4X>%j$q#Z#&$)R3lq6Z#Os5hbdi@IZTBHebc`8gc z`ch_RO^H}ZG?S6$smV#d`pJ2C3=b?$qP2!HOC7=s`$*e&G}x+%ae<*0!mOYwi-R*3 zxGt&N$L{AU^Nq)5CQTtReYGaPQWu_IqXN5Nt~Lo}usp?lRUWA6gDWj+lt}^VrKYe`R$*C-m9{S&L>}(%buTl1x~g<7 zW_N9-9g39Ov%fO-`;FG=0^}6B_SQ|cO|?XrEhzJ1n+2>){1HyG?7|YTGbGJrl%<_M z@n57i#?b{5(FJ49v9I7;mqkILp$;EeE*r6hgY0)e_Go5rDkY7HxiS{2$qF^udaC;R z%Yh?Zk50gUJ=E8_5*s|5P*37#9E-lnQk@b7o8_EE zNwkiyaXAU;IIxU)6A1-BcnOj>n-*3>f{wtSi-fLsPhyeR75|0^KRgWbI{qc%b z8_?JMSZoBtrxGn;CO~22ax)N-)}?YS<{tFG>{*5?vrRRb=njp4^y#*?v%4g>eWUoI zciyAZ!%)cevMb+lT~an$Fj(v@)o0-Fi})6?>2nU`%@5Ou3B>c=2#h)A(*f*Wdv80g zSa27K6mJUwflb~%#2qJPfxW44G0@kE%6;AyG4ad`i56CbLX{YV$YpT2sqN`B1`cu; z8Fo}WdekgEdh!m&nr{Fdl&%dYzQh~y7m>`%0y3*s2f~X;T8RNNEqHfXlM06L`^u8;(6oR2SFgiCjJL)F%11~VFhbPnX@posNc|2-DyFo|UQ4%S3s z3dgunmm3IMbl;$ds4F~mL<837QrE$0F`~T?^FhXlp~TSzH4#8)bt7K%?NXL|inv?M zY}(CqdcH7GV-R2LFmL~X1oH;-JVpfPWw&y#6??k z#G}^+V@+E8MBN4I@L!Cc16DC&H(HOccn#YWE@vNJcD{IgBq(h zLB;XRih5YVHC(i*%vyaCKRWNbJ$jDtU{u~`k zCL(eHT|;#E3XVgsH(#o^7^+v;{R8InmMwG_hdA*@G4gvz^AeTJONYt-B>Z1Fa$|q$ z-&MEF4@NHr-aq_UzB==>wbu$I>ad2WCAV9}x6hrM5=@E$A#B-t1>B&JL8ne{Nm`Ad z_(EEL=9nZg(@ANkQ0b?Tq{@-U%Q3do$=FDB7n~#FXQPPocHsX7stEb%@!k{TrH%=9 zoJL<4!n{S)ViI>41&@hVjB!)l&$`eGClxfQj^PHzg5>6&}=}DxasCsT{tENQz-! zKOGnyo8T8vd|s1vkkH(9F%OVGH);Y0duE^FrLrzFkEL_ic)t9jE~$h$1dh3nyq^#Q z3OE`f(LjvTmEv_`3uwl&h|DwUX#a0-qpO017o7^}-_^nG=V0gduXIA*#=bZ^P>zmOqT*VU)fc(5w$T zJ(X7t@7AQg7H+oe$96=ZM|+WC1%8giWo73+u2(9U$B{|#Y;v6!;Jn)a8VEU<1Ph2} zYSL3IK8MHc1NeUDEfMHlG8!v|gEaZ#lFs-h`y3%E51XJ?;tC<$aaMdo34cq;qADPf z@X4JEprd@zJD|7!2_#qd{0P+7fZ;Aj<=fDoqpBXv^Zj-36_x_v8Fg+-Jdv_v=%dgt z#5*)w7t$ZLyz`F6@F!IGHi?cj=UJE~Kl__TohcWPm$NZddV7<}iB_^0sp=pBYu|WE zSJw8^F>Y~8kQ1Mi+9*LiKA2Mp6JwiKzj~c|gQ)KoeACeG4>Jt)Twd$L*NJxU4PiJz z`6t*T>(4(Hpa*!M2YjFhAfN}L(8%6IIe$@|%h7b|uTZRgl>2Li@zQT0oSBoRy^kcy zI~iT#o&oZ^-yV%j6FRpPR#!pcub8SaPM4XWiqKs#0z6oO@kQxP z$xurDW?qzEGO@2F(JQhR)JfzX5+#C2H5ncp{i-)P3#!-|<>sFP@=rYng9tQ9dBQ+D zSO<8n3S-;Xlq|{zJ2Cj49Rh{#>axibj~kU~s(Pqs?1KBk7qBW9fvPn$+%{Wtau>1s z+URdKe$jIcO2tp26)QC6Oe)#KvPwM@)IKWom~Cf>tPeCNK>$ZW22 zMmGfAewh>v#+JlEWy=$g-&&?>&XDizOtL$ZNM#si1q8!P-6K0yXbkYh6?9(i?Lh~x zv9dbg87Kh0kDp(GQT^ycoq~+CoGX?RxU)?u{D6P5%TWe$w^;n@%99ZmZ8b*m1IlTt8JqKyH}zma+M_!yvm2DO^NxnX;9kJkhw-e% zq%i>hb`c(T&$-W~Qcjnb@yGt)yz_&;Uj(o;Z6p+4ks7%d{B6k!H$-51%3%r|VRltj zIXdhDqUlITbJBsp+0#8W!x5F+?HY7mPp)EVB{BM5r zuIP~uM>4#QAKR?skQrmi{JYnp5@jE&CLIf{7(!R|1CHp06={;mspvqIeiqT4UuNiD zH=41&%vIrF!!6rG(b9Wh$@>s4`>FqC)!p z`C!T;Szk=yD(-OgZ<63|qxffvb=jR*B->;X0HsgdH!0#Jgaji_S-7DuyfHnLcNaGfNtBuxRAV!;5=ebN0MX)<~BY8`P?helYIgBed(xYXLBB>TQH9Zos-QQ7Px z*=#b=PF$KG|Me2`?E=e-DHQ;tHdF5tsyxcRr0@%|)=jV~A6oY#E9}xDlkjZcnHPra zsxOmp-WjAXd4XBe6Q2>ZOvDFY2Db!HOh7c4b(!<%UGR8;v$EC-`ywBK>Y!R8(zs@;?2kRxz*u_r=<2=}WM|YysM{us}Bl zuonUB;=6J5HUin(FKsLO<8zRDNd&`;+%V@S;OxH$kx9e$v@n%CL-wbNHDJ=FV zk$u^zpSVCjc~#FIl>RaZ7WE)voJBc=^k8b7pX_RPFDOZHfid9LH*D(Q4%;H>pUK#- zi*5L`oDB#lsh+=LKA%)ILx(xQ!k0jY`Mhyx=V<0kk7_h74RU=jO7W@Q4@%;E>CZpZ zmgsH`*5Wr!hi>uzvrf1LJAglXM09#QGEJpX%+HHbdh;~Rq+!zfJBs@0Gc}Ln7`q*e z=7l-^W?enMI*hwe_!Ir zNo^ce6|umcB%p_5Qn|)dioF-iYSGb4`DIH!`PY1rD^!S8Pf~t0&9pp2D6}KH%zii$ zy?9Qg=F`P~GUBC37``ZLIr5=pa<P1Ybz|J@@l~A2N)jgk8}Yf|O{;A#!aE^hcrHP8;fYK2hH_ddfHl~^wIoVzhb+Y$ zwDig`34LUt>d+#YEB|`6B;$9eNw&4xyHwlIxYGi)Ng~N7{&*zxy0Yh{pn}4#3wbUs~r*%|Csb=Ip%}bISv0Tz!P5d$_^Rk&Yy# zI8O@SvN^w#xKeCL^=nI4W!-5XP0U7|%^g6+w_E~Vpt{7L6162LfvOFZr?%S&p1{?V z4Z!U^@qteJLhyK+jW6{NxPI%Mm-xmOdHQXs@d-ct_CmSr-^VI4$SX1`JlNMRj!e(Y z+cqFMvK;yeHQD)e=Ej{YUNNFR_Ueo%t?^(#{+ zT&8%rc)rn&9is`+<>OvBW5eRzJ+F=8T6X&sdT>lM(GfclPGBL%_L0fUxI7_fF-D(~ z*~_GI9s*5VfR-KHup%KUo@s9U=boCUUDq|7Ol)JqiEVpg+qP}nwrx*r+qP}~Vombpy6>mndcU{oxw^WmyQ;hTpL1%T zz4lpauR%|m*(*iZ)R`v5_5@~fMp42dz-GwCd%1Tn9`%Ijk))@Fwpnx5DpHF#R^h0b zZ0H82AY`;~1p_dzA+iVN&?pnBVVrz~{4i=1g9(yGgS^EgLE|y9#u58ST5O&@djGJ1 zmKn7JbtS|x6%}Q_ow@p@VkPdPiX@eRuT_Fdk$kT5e8kJCb#asjY*B#<-ekJHm`e;! ze>ldOHgcCILqF{uNNB)~mVi8ao+oU!-8_4u9D1Ano2X1cfPJKr1>9Ue=z4&9Ic*eaa-9LSk|D=X zSk*R}nEl7My`iw^93AIK+<&eL!%?qIif`esQL7^5PE=uB4xuQ82S<~Eux*1mM}>IA z1j2rSfFfO^QEjWJN3wxg@hWV&noF7Ws2M+9ZX|~&6*1V00XdiFbNB%bBcY<#)l=KS z>-v<}RZt-?)=mPoxA11D(SeP^8qcZGX5{s-_b4OYuVwc%uQQ}5<|o6fIf-s3pu}iV zhAnoXb55yq&H#x6@|2%F!x9JL%viE}j0fggmN)~_!}gmN+(gQCL4KG)M-pgM@l<~! z^>>bYyQKjv$wG8c9Wa{3GxGgmmZ+Co_T{HE`ZI*AH$-Ub%L{Lu&}JnX2wffg)?v`D zf~m9bQvK_b3LAy7d1RMvj#6~L3SHu6?%Hq<71`1Q+Anzl$O}K+C7ksW=qOUAwYrH* zm=;PJ7RtJ$O-bPfYHMhnnzC9+p}pXSBhcy|-8(7_ z^4WI*f)5ZH<;f#;1M(H1tn%5|C0hC8aZ;^F(x5%E%d887wts`OinTNC4G2p>r3)qF zOVn6Y#^e;_DvT&D=J;m259YHlEpVSRSyiif`$i`Vy-uNWs|PcR6v+3 zCFeKi%g&b_1&q7|xgJ|?F?W!L{)R3->8=O*2+=7D`YMY0o9hLc8#J2hXPt@Er3Wc2 z1e%v%I8Mr>nVRUuul?j-2nBDT%9y-Xvo_hMyl39DGBNB}1L>jn+~aLv!=r!K&t1ch z%>cPgOQ%w9j{v#~)+D*Lc^H`~c1Rq}r6L)sd&IX-@*E^+CW5cSl^+x#DYpxJ6cNh{~s?e37#X>v9H)7_6-bELGtp zEmKOt-1JQ}YqIrrma~a__4mi{Fg}T)&f8%4Rph?Cm zdeZ{|NBHG*$GYvR-lk(OEnC__ct<3c^hohy(}P-f_#8$m`$?^HHwy|{m7I3LITFuv zd(rff?As?OvQC~V?k2Kpm2ucz7vWT})j!^7(%wO!ez$DHFIEKBvJytIK`-v*{} zzRa5P+Em@nsLwq<=df`O-Li?0$c*(h&wplYIGG%8zvi9M7T%gfSry)$EJHa{yQ2B7Aa zyRALRcg;>+diCn24PHvU)vm4Gx`WqsNFd-!G?gq?XZm7@}J(@$pZG1&4qyHkN@ zY|yW6`s*KG8G&#ygoK^I-pe?gcNsyr#^ZhjT<+RXGu-eOyVG$z{bk?zAjz152&;UK z$K@7su>(@ggcz$sh{wel#!FON;f??~K5$$2LhfP7?YBH;=rqS0**I=+Tlv7{Wz8KR zJHDUiT~3f0-UTl2AkOmlEGl-hYudMW8J5MBd|liF$l~ICDFIp`ZYsqnu<0Z&7#I*` zDe&;6sBJqw>Feuxuc(K1dsY`- z`Z^`C-#vwJ@C}MyF{D_(B3_S02k-DvI6iQ(r)2F4Uny*u_y%x~F~#t+#R` ze~81Qf0BZWCztMPGpJQ`V(XM1W{>UBN?{11#0}7&{C0?aBOEcsETQ_m2mKPEF*or+ z@5}8G536c4ajtQ^_OEJ{g})miNC}onfjLt_Zr8vwQXdl|(3)DKGzSg2OY(k~vu z36NI0xQ_5EV(0g?<8yB;9m*m#xy|j|NVw3vJir3v`$8Po)*jnD#6O=y`CEM^gN{wF zt1c&9?P&D$F;|(09i3`OIl0a8q)j>5WZd<9ZM$35047F>UajM3ZN4if-Y4-`T>hZZ?ht^$0 z6r|jTUSzG5o}pf=3q)JJS7pDSfJP^p8c4))C~7oPPdPv>axd&Jc8-uB)faOtRR;yV zS_U&uArjA+KoV?bG$u+h8?gUrTx^2$Ji!M>VaX4^vVq_=*^!@zW-8>v(6zxzho8$j zj^B;>F<{PRZ80?H9dA5lu7Q-;>?8ZiQ-y=6Lg!Y!eQNc{?^;RsruH|^^ii~%1yQgX zNJPUO(-2KBfdx{rsxQqDu20JnbGkl+$SnGIGz&7E3PDD-yqaltjPx?*$0Sx{W|jS_ zW%LNqGAK^-bg#T6VT`7*+Zg3=ZuQtpsB*weRr$+!Mu=_I*-Kvr0jy<-So3!YF`eXN z*(%<03W=z?tzeWA!+4pyZnOf?RP%la+R`6V(=;4znb1DmIi_{K0<}ehzivc>RHMoQ zAW226QH=#?ZTcp(R3p}?HSH@`%5)l6qvESQ&THC`@ZCg7oe^!%Ru?U^!aeBKN>fAKagwQ%tmMcitM>V`ob&H>#^=Wclq4obKb|x5$F%5 z8+eAs8YAJ^W9@Bbw^XcwQj%{aUq1DUchh}7&pKLTAl92j-gGmihiYE7e{O%y6y5}Xfol1jx%$|*8!U!pq8uo*ckBi+vgrqqnld)SSLFkx%LUG(j_%GX{K ze4RnD!oW4OXGR0aBWGqaFBs4{zk2`KVvnACl&|yP_P=oiuuX;2+^!oYs=gKa7QB!` zi@#s!X@(E1e2($93^2ZoP7J)cEF-$r5#CW z2{YaBM>NqHWLZ3D)9aiJP#3bw6b=$6c89!_LSxhk%!hjLVtAqVB!&QzOGu7`bi_Ea2+3#;O$KhhKV zK5xR_6etAk0bynVtE_cIaU;bz_i7YejVzW40DUYI-$r(EVMxdIxhneRQi zVPKGZ*xJ`3i~!9(c(g=Nc21g1(?|1brv*hhC8sd&*!`sngQ3?0s<1kBtVDN6=;Areyh~(b5}#qm16Q(&4Y7V(sOynz-C%nd z{9r{HBwn_GK@l$;PhP>t&^YJ&0VDN^C2~UM`kX zJy18K5V|gDZ83s?%DBFGT~JlT(`5O952b+bR1-owFrRNu5u46*=VYSST)`b_ML08b zcyLj?t#3K6J1#*ph9 z%9-nXzjU(mtz+L*V7MAOmsPya3e2-t=j!X}V;Y9|!AVjY@|TF)y?%Gb;(o*A6@*q5 z3o0=NRTZ4GgOg}uDLCl#Jg74JXlHg^T`dQBNbu)-rahmTQ)Kw`$c;Z^5(FpiU^2qN zU100Ez8QCQ*sCMpd+*yE)E+64h&2595Sw6pFn6c}h3UWCV`A%;xo#>Tpmfdun;*<2 zXu|(Z3I0C^=J%7WgDIV%t&y>rzOy5pg}$Msqpb~{xh);Ye|X0KeEMy9`Jdx|=NXfK zzyII<^AEpR!C2qO*x|okm(fbridd?sKIrKD^&$tB8D_mfUZ@n)ew@1BiwK^~Ymho7CEX=*$FL@1S4Lt9ycQUG8q6%%5goK@h8HLz zZ>V&otky-$Sj1$LbA>yxE=gs~?ariH!-1sZUWiI&uPwE=?6>u=ADPqZmf6}ss|M1g zF6Nz7=1{p(^>5!b7oS|IBtA;J=giOAw^*fialkzne1UvuO=>Y_^Vb%|1`bs^I}LdAH?VS>@d`h44^twjH_x=g&1G$mLW`H#}lpLp4bXN)4Co`mC4 zMmT?ip>lwRuaW{3-8Gu<5>*4f5aC1ur+zH0Rl5MOaNl2d=?b5u0 z5+rc*0*RR}Q)~c@rzEp8it$i+hp>GQ^`jI1eRh&EBYpT!5PK<1%mHZ-{9Qp1`6z69 z27_OuQ#_NP^7MA1CDR3%LSueF@r4!hX#FI|+AAJ8&5{Omn$Pu_()HHZ=&ElHyD;Z{W@ zha*IPZqNVFNW^Q#_dCii62{<~r+7SU@hsT^AkWMSZ?g6*o`b48KBr%mqASAC#W*vq zx}f~cXem0@^_468N&CXhj-BRAhG(pr&PM^*F(qFY?1vmvG;n|C8p0}Ltcspmv11_%Ik^s@ZLw_C0PA?q(ERN49P?btn*Da4j9j^1+B13K4 zMb6E176x8O-vecoUk#WJKkcy{yw6UBdxK5_d*kCC|JK9rONG8;y&@NAJm{np9w((m zE{X+8h5EJ)h(+2ZGMQwd8$m5OdXCv1`LG;+4|4Jze@|k2O@97aem?%5rQ?_GMUX~P ze%v)Y;4fF@KW*rsih7F6>yvtDB5niU^E2f61;cCy}BBQL-lukG~ICnC!i~H`d6w5_5lk zuwTddHFrd5G~0pGI*85V4*92 z{`LJ&_yRYW>^27l0wRI@zr*1FE0du8m+&QMrthF{_^p!=b~MztGj{x+Af~Wpv+x_0 z2c-jQN&q85y?^aBr*yJAcBxN_I=9Wvq7{ zHrQh~G~?Z)w@VCj5iTU!IDMhU8N2Bj?tt#w{k7=gTRd|^PAdCzK6F0yjU-T>5&?74 zgC4nPHop5*WJECk&Fd7YVGBy@8m={gK_{UkXEZK<9%^ybrQETW74N95Nu{$)Rn!j)pLmAUc$}i__dfM-Pz4d;xI1O zWTdLXGa*mp10|0so`wBn?R4_KBU{?kSr3IXEjC`Gs@&CG?`EL*Gd#T=jJeS%sWw4U zKj+>hSQb%Mj~~q9$bR2!yLgl|SD|0;126;6U93*;ZqXy{XRZj$c>H0b~58U6oGK(c?Cfa0=(wl+@2 zZchK5dBrI^jws5gBR!d{(%8+#G+?h3z#3wT62HNO5H~{n{G0n&{lG}97B-wD+cjA= z^IqODUSL3d{l1+;529kY%ZTU$#sis7cVF^iVi3+x|GD`F9JH}z>TX1%dU0fSJ?Gq< zY_c2Imn|F&K@s zC{xB9)}d3tEDsvieUOM!(Z`47P5ToxraMeom&=E6+ZTuzrMe%7;h2B-{NCEO69~cW zCKte#vpf<7dZ8bPe9je`{8xg$*lbL%(Kn4`vI)6jUrO>6q#`A$woH*Nf#1VWa9oX( zy^8p$#F?fwU20WB2(Jl%B&?WVl^1F}NFv5XA{G4{3kT0w7)mmXLSZ5X$vzRCZb7*! z-t~mPB=Fi1iJDE9tsWs5@JzL&CR8X%l6nM1#`3#LcBPL(w-tWxp}(SS`t+o z$IF?6Tdr1WQPHL&km-AuFU{SUJ+(oS6gryzE4yO2eMICf9ZB&`F)Ft{M^0e_P4MVu zS+9+ws6-O4wgQ4^F78kI&e;g5bVFIJnX#|s^vX{wxv|q zDmo7>97vj?PLzkG-NZy-QpU}WOnwG1rZ_ePWSW2)Q417Ck=#z0^&3D%Cyqg3_^9=N zcmaeIC{mOZx=I8(c+&I=ODZgpQ--4K*IQ;5y`A_Kx}m}!*xu)(&JBA_D~O^lc=!7X z8FPB|5n@K&kY&Zy&WiT!YF+9|?bQS-6CL~dFu2@rqoNAgNe?)1=#YH%4K7Df*h%%< z5>@T@FMVcAVYc!8K>hSkpCGt^m zsXMitad{Bd*>P{;M%aWo*^XPA-I-!wDMS@CG$4%Dou=45KjJ9Y&97g6-Vdxa`(|dD zbu8tZxt8&yME+^+=%T_w5N>%o3R%|WBV1U&sDe>SYq3OXI-oX;Qwq3D2kySE9g2?4c4$QlZNZI%spxCuV}2R{fz!IaHW!VVIDFQ zF4pPZtr`X2A6+z?8?TlT=DXG&Z-j9+_nG#xBO3U_^O zZ}+l^E0&Wpw6?FW?L2DAJ-5&?4W9X+QvwI7x;2c#n|PN4VGXZ0{|6jLX&scS1{N1h zw8)*Sw#cKf((}?v*2tnH@Shi6i<$hG6(H%8rVHVDywFhIS!ecu*9ZS;M=ZyzFrrfG ziE_GKDU>WmUh5Mal4%A7E}1Npn5?PQ{a%V02P|mzg&BSD8l#M6M;YW3)bec7X{wkk z8POQ7iMD({CPh0poh_H?%0c(&MIEwf?3gTCCrum?yiUJNu`V4MDU_6-eh2@tD5}MSx#eS48(v#_{%3N1GHl6Xt zASvs{tbvb@rA%oSh}pe;!Sy+?0Pi4H`-a*|uR7OBvHw^R;zN~LTNz-r^ST zT|?QmC~L^v;zNEC_4yL6&VYUe@Al|``M8?94S~7^E8EK4?m&KW^?m(X%?166-1Yq; z+YIK-uS;x)q*KKRiSIYGZYaAbzO~w@@&*29rIUnc`;iO|1f+}fZ>bjbzpZpOcFs;h z#)h^I`cAh0gBFwHrDcCGAcpMp_Y(&Eda-{p=ncf4v1AWRi?iAkg2j+EHqV39oWH{Q zOd&%-_yqDzvUec>JrJ!GFU=-nx{)fq!LP9eqP5c!LU+c7V1@sAm&%w_G8AXc{0^(4 z2?r)Pl$hTdZ3>cq^QtFNbX@Ky`>r)HsLMYQWjr{0n}o*!Y#if`!-0awEkfy306DlRh9<%qgQ>Bh zBLiH>O)MKmP{f+78-`5y-@%J z3KC|5Hea7^Y#%3o2rrj9x|%|uRStKkjEL#=CD>&;?ax)CdkX5p-_4D%z3>r9Q?;21 zcM=wKB+0f#?c!!PrRzPb%rKk-8#24GR0DN9IjSQ20>WR&pmJmP$Xa{aU{VvsSZG>$+5 z>-gry^-9%XPl~40%7Dej<>p@*dE^$A3YQDZ>l(IA>lV6C%iGI7J6*nM?;9slq$puw zJ1djVR}CxMmepN4Jxw!XjyJp>$h{cs z?7Mu-U!5$a8M2S>h07gaP1jv`TKboKfC(OQcc?)p>u$e8C+lgSgRZ+2=d~NlXSWX_ zx#6AXCBC<%eQ!PHZK>%(1B_#3sTAX!wUI>)#yMbf`N{c$_RP#mV`ZH*jv~j%^2gj1 z`~oKZg@U&BcztlZ-`YQ&QUUUIJBpO~noa3MF*jE#itln5&O zccteDGir-J$m|i4%P?7wi$rP5$k9J76}&T}g*4q9=~VBkfvOP53L<3aIHz*V6y%e%_Y)9^uk<#-8fKCqhlWb^hJ`X+A7aqHHF(Wi*d=Mu>j&+9S7GX3P+1j!kY@for6Egfup&0y^S{qczWz7tb zB)-frpShf@G)gqx$gGVoJ0vA}vs7Zx@X&(EkRuMZtYNbr|I|E;(36Ti=pYmH)K<>A zX`2jWoqrjW(AZ>(yO_86u$H1Rk)bbacUk+8GUUQ9+S;=d=G=TYs8dMb9n;Zz*8Yaf zdAM%F7PSdwoRx~M0LDkEpuV~Iz+XF8w0QC$q|W=dq&V?x&4ze#S&0zo20nA~tUzYy zxWU2AnVo;9rQ_D1SL*}rtoW}TqGuJ za6*xupV24~Of%HaQXDfil7lT+b$SlenSGyj%<{O67QZmhpvVFuAr|v(-EU3dzM^|- zxhDc$)a@kmRzM4%`ufB=Z5@-IVP_U^SwAcKU-%}C7gl+ff{9AvA)iJH8JN_n4ksi7 zOt{Sgi%3^7@E}DJmAuCGMLxj>#`O4JS6G%IQdN{`4fQq*z4e*q4V_A?FHNn%5426) z^e$46U2g6D8<$QJMyKjU26mKqzhc-3{lGDg`-}a=c zGUZ&H>hs~uW~Hl)%&@%DF?LQbsxCASNHk;vu2HgSRTi<7?f|*1J<|sDsXviYtUq!k zmM)ByCapq541d1SlOPKhUm%uLNrWP1`qNxQmt;O!Ag(ofn{4xbZB#ZbDg(f?4!6HQiiy~q)CE0S_W zAgUQJeRoYy@&@P(`E;1EVlD z{=1F+iVxVEd^mB6A=ktg__3j18>W%JcR<@0aYJ{a0vlnl_U0?Bs_Q-F7tYfj>1OoI z0q{owuIKi#-BOdt>Zd8YBbUCG-{Mfc zK@3hK0BC)PZ9dePeR!n?WQ}=s;v_oBCjgFZusuoO-85_mst&k1@l$Tf9=92=`_8Yh zK16H>EeUaleG?^2~0+g4Ra#J?fjY*#ssiCEKgCQc=!0uC|Sqj zL9JIX&u{^gx{sjNuB=g1FV?_*_f3HO#@W3vfuiP7U7p)}x}W-=4kg>^hI<~Y6CmgvG%k6i^b)C)* zYh<~uu}W}ia}1F^lx~fPK$3kU`&Kn{8}uLu0zkv8L!Cm&zC(&v1E?LGa!sn2RovMr zDz2sx_?rr3O0wrrUQpg;H0HY^zNJ>-<{;rHgo;Q zccN|K#`X?_j#O?Xm)r{!PuAe8DAH* zx@#Saz^gwusWoJ}Bb?lh$ogz>m&}=WU0EZXP3u#`g0aFM2ns{kd6UQOSJ5LBhRUm8 z-omT22_O`F8=Qfs+709^oRgUU$)*aSr$JS#db*6q2|kz%Hs2KNP8qy5+FN-@AFV5W z#B&#&isOL_CG<)~7S*zZFu`z2DFS!-QiZCH$u=Up`cUDId&X{e8cX? zkyjx65gnF@@SgqbM#P6CJ8JPsGEPXH5vXMDXip=(uZ(FgUv0PqCtEZZw{m&P%>3F` zS$rn-LEw}9&&15v3X{yuNsML@DrZkOje{m#~H2GS{Z^X;Qr7| zB5ZTT{~b`joETYaP_Nj@C3&CCuuq8^aSVgK9e13lCXe4po8Pc6-}JXMrsE}eXUs)^ zAV=}E@>s$ZNUWu}{Es7{Ak7bRa zRf?B^*{^W%{M{;lAc97(;6)02c<`3A5|aF&=mw}vb{$J=A_cS}mFh*=a)i!@VufM} zZ-0m)(&{(AHwDT^(Iy^OmpbXB3O}!t>B%jolN?XeyOo_D9xyx9A@=4216ZC`Vp1v- zg-K%uj=~U zE{+vV9NPB#C)`RMT%G!e3FQ{<%hrLlk05*}4MDeM3QMuWl&X%Dbt={KCV{DjYP4$+ z)01-;nC4Of=ES+Y85N6%rm9vKcOAivpQV?J!^~NdU4!X*TlN)LPhThHs#dmhIkqPAvn0e&q3Nk1VofIQ zTF{kR2E->xUN3eQVdBFxJ5=k*83!qq@|#9pb%!c{wFx>6+$V4pB7CACrc$%eLftlu zO66*lv}#OdDqqaOB|w*`kjYsR<3SoZ7$qsd*dxh*z`A0H(Q4I;Gw-h{XU2Irua%GL zCkiGeZE4tF7}Hw9&XESE^WA8D7kFfOP?TtO>@IZXx_8BNw5z{6+Bjfh_SX7?x?rw` ztHM4Qr2222GR@Kr3$6ERB0H!}BH^&m2ONNl7#pIJ6~6TL(oABpQvn;YV+>h?pr>tg zr#P;++}X)3>CMW#;iVJM^7MYy(ysv?HXD)4(`6A~WcJ1Y?tD_#7x*o2M_ATxiq zdqN~=wBI!R{4pg}LtuobCAiAn2)-qCY8jRmK8m%TLr)sSzYZ*9{+@?IH>}Q8=MlCv zu|=$NOpFe)-B3`E${2EjN-tLNd5jk8Ldxmq`O%mAN^IeGhlSuYN z;dA*4^g88tBZJ>IQQG;)CG?n^7n&K+SY8W2ALjzmleUqK`}C%y4UKt&Mi|rE&Kq2K zvu5oT!}xT!6CuVp^Zl))w2oV5%Z#v59O2`?rbT=pStXbvs#QX%ik1FYM@y!}%WZ@5 zC{i9GdrrL)q%0p}#Z$CeD^P0Rb85hS^ncoJ)}IL%_ilTl=Gviu2=7*gM$y=BmvE zv1);?%~?c@v_zjNGtg%?adBgt+VF~XQMo2D(ku1rttV?6Wb%hrk_0chKX{v=aYEyh z8{=@?6Tg0vmS}47Pp?fq=O`RMN>gW*8`_;ZPbr7wt9t_D_b{z%#de6Qy%D1aC{jSV zflb1hOE=ZQ`B2=&lU6%U@hE*Dq9NI76Eu244{;xh1|;pNpHZ?T-+}l1vJyaWX3-h0 zcx7&DamMzR&TT!_=nakKBg6KZ%?qN(`fSMGPc$fY8dzBX?gVW(_`em?pVtV5Xkb7< zVc(7X{`b-x#lHkw8E0z)V+Zkn>ZbpVwaKd1QkpA2ec-#Fv9Lklhr9-#eo1Efq5L3# z5*OPK{>__(sYX!j#T*>TFbuT{yum!h%UP|I%xS(=V@KHDX1ZP@q5#8#&i4Lhx^8H+q3olrp6bhSH^1+iY_Dz zb2!Y4`*`pt_w}Gi)VbD({}5LkQ^c?y=L;(>K2kXs0ls`2r@3eqrlJEL+iu94{XRA6 zqwFs>>|u_-^% zD*}>w1@{iMsyOLgeM}tJor(g89R7 zevX8Ak)>Rvt;BN7^J8%diHYUp$)Ks$3v-~k;jnc8=1vR<^Zpcx8F{XLzP4;GgENYD zNg+cMPTrZ{L-YXo?SU~N>YE&L^Tlm(l>6fcU;E$132p+{7lmoV5lhE=BI}E!`-zFn z_@x`8ldnEML%pCT@+zU#6gzOBz#`{e(&C+lvsAFNDEniQ1j=S@z|!;}GncE48F*8& zG8q;`>4XYS763*8W*7EQTrj*y+00A}92rS!GWEYv?;I3Lv@FVS$Q0NJ?)DSGIQ_L1b zcOS?gTtkc&hSFTipw{G$CUv8x#KwYogb<}<%BjzCGwX7y9`;}=J!*pX{iA*g%;@OC`18msfyd2H7XNavIH-*0_vU%n zvI=2SBqr`JiIH?Ox+YQbXv6?wezyQbZfQi`;Hwv$j9WsNU8>c}UT7oWJ&D9OplZ8n zb>P+j^lr4dja2n669KY(tERlpsW$#<*B{N;jQ5;5)$GvPsWv-oXzL0TrTqlw{^Nb6mpUr{}+M1+q| zB+g^h$4x)+k5Zm%KJLyhCP((>79?kR-ZbQCDfjV+Fh|srP|8HYln@lxrB6K}PeRqx zc%AZcH9)*PlX?U@`CuD<6Q%VTx+OHk8luhso^F4psSUF8$JUC;fA8h&2;sE2%eujx z*u`>f3;pOB$fDGv*91rIt(orISdHePR)E?z;7S6k8m>{h^rl`F>C7LmoZBg&te7si z7VU6urFEdKUTR=O>GNChg?VF2rr-B$qKsZ(Xc3f{O!j&*ZiIf~&*o6F>xnXBJIpTQ zl`VhcEK3^j$pJrJuM_A9HO!LKXxW72-F(Iy>jT!_ zJPANMZ8p~Y)_4?EG3-8K8g^K+#PV-THLmeINs`~M>ei<9bn1l_FRe7Ogn+tLg78K< z;B`}aWAuOKI`UMq&b*G|~%BXaLQSM@&M z_%R7#Blt|qB)dYf)aVuIU<32!UEf@vKK8M-q0=7%R4$jXq#-~NY-KwfAT72O;>TAy zKD>9>J1sBak>c&qmJMFs-1x?{B)-ma!`PL(mmgEh&XjgEN7I6cb>a&D!dmzj{-8s; zvwLE*Csbln|FwH&37@_PzrNusOza~q^ofj{yoO;UmvN_K@&@ny?~M6hjK)uJ>|we! z`s?|LnzJM6Z5N+JvZcTejnU&g`N}Y24sj*VGXg3}Mal8Q_zbc?>P07OaI}#(-^ipkSj_7}9w=#H6w-#e5$5Y(%&(mEzy6qC@t8eRUY|lyUs6$D0>hnx zMxPQ}Jpi}A+13a6R-;TWwN=0(NYF@3jK)CJnGDcW$tKuN!vLu=|3fu~)rYBfq(BBpJZ2j6fO zN?PUB`f{aGjlxPb4v?l9cmZ@qSqOoJJRxg8O=lS@uTnUtn=sFZf#RpYuC8csyH}bs z?7cpki94^9PX3u7_{xy{Q(*)&o8h`0)RTnLXc}eB_E!@kF#8~DQbdV!OA~aKiVmK< zs?cYRI61^!YPWVp5Aag*?WRBz@su+=mHfb%bJD0~o*aCZ#9XvOvsYgXAuhrv#6Me@ z;Yx4ObKeBMA%uU+ll~2q{x?sOb$0qciBh&IoYTS*+E>?c?%@t|vAG#^3BFvfM1E6J ztlzickH#-V4H61D`Hk5U>tE6qnRk27qVj{Xh}m9Yv(ZZw@K$JCN{i*0`&l+NBOJ%+ znbYpa04uzi&9ya?XHPnF4bYM*p0D@qj+-ven~omO9d8c6Qr!WN#4QXA`o7M9G>)2F z_kt14jS@7Jn^UTy#a?I-Zf95r>BW< z5QkN&F;|)wJb0|5ZS2sHkf@K45Nmd`zUMj9zQPxOt+zDdSV;%51Tt8$%FaQ#_IJ?3 zCt}@k(TV}S0WyU#gemr_gRmGf=Z6c-SwK=usWZ+JAS#9*mv7!)YNUZPX93U|bHJ%H z3n++5b^1^nnc&o6I8bKtA&k>fJOMCMYbn$T{H8_~)5e5y75=+-D&bqkr5DEuHaW3{ z7u(SsBDsm93?HlDy~F|skPi%PkOZUdCTVisj>w=K6Vtr@V{W(df<@U0m$RNRl%QDm zrX*A0>K;6zc=b3m;xfbe1@3DnB*GQAx2yo1S=wGOuHDeu*V6A@Ub=pQCZ<6& zrA<7AuV0eQXj7InA*RsLdG#qbiW{R~klMS-VyeJ+oTSVICUqaUr`M>}OW&kd?AJ^` zkCO*4OOI1_W}}OJ`tZ6E@?-u`ERnBqe&=V>0lQ*kGgvw04$7Gojm`cvtFNmnfYW#3 z?T=V1J0?X;c-d8qi<4+M4@ZH=q6~(tbB+2bZC*oSp>_NJIDYK=utE6OJ zVz!v1q^jSA;`)bna-STz*e&G1(GL&yT6<%wHgqV6b^}JLWGP9hL^5QX?u2M3iXY2c)Cg4Els(#&cqm;Xh)^uLGD~S2 zl<1O7>-Qb1>Ij2es8V{ZhnmzZhu{*ZlLrvniEX(;-;9H+zJOg^+5(k7iG8&fJ(ek;(q#LjBwLyT=- z*0W9iOUU9&%aty$&J0dsHM?bL)q0j$Pq2fD z<3Uv7(h=sp%0TM}_kpOyM(|kLR;6b)_@M z>k;G=UV$bx@R$^rZOc z3eV^YpMZ&J&IOR4kv1}j2d)MH&1nyJhYc>=E!DAfda5=*R0Ra(7C-emdRk#alIWj6$i&vVYtC=uB~Z@>cgzqY;*x4JTIb_8#qkZVIJ z^zmJJ``17&0sJFh174kvg|Tvc5{P(2i?Jx@WRQ>g0^UJ#e6KWlIRfn^i#^0kwGJQ@_rqw?@xJ*X38Wurvb%sV6zYA8|sK z-Ad_8MhKYrT0HsjhaFnHPX>rP9JMrLt_g-&lTTVBEgbLxrwm^qTanLg#hX&dTz$PN zDc7?wxFRN-uRd5w~C-cch2=#)k{&q;9AHm0<^uZfJ71w(h>ePf~lY5T9?@Y%+qTHbkqI+HfMNaYOO{ElS!W_5~**RP_ zDyKFh!kyf~b64R7@4`4+3D8@pCHWT^A}w|p+8~Od;)@Y?(5m&g!v&+8*B1=o-FbW` zume|I$eYoQAsY_WcADMbuJ>lGhUV|8czGyRJfgwOqKZhz^BAcJ0vT~En-v!nl zm@}Z!g~N6NaNHD)_N^J6<_`m!L$4_QN{t$Eg(Puba{zyC8tS+0J%3n;cOor>zHFsi&I(MlM-QG3*5z4_;)? zZuMhWIl{{X(_Hblrqz`|22@V+KPpneJ17R(lo2f|pgLsK=}TV9r%(^uUMccSpMTdwO+fD@?YTTs=% z7m+42fiAN_`>kQK*)S;){W)k-7_t)CxxDc{=usH*q)g^+Fz63W_T^QyG2}to^uoz1 zu8C6=S5pa)K~AiW>^jVTp*b1if$>&zhCZl+@SoST5*Vt8Y%=MMU%ykC)v*{RT$AT$ zcFf6~=L#vL&x^&e&E|(2(i`t9$?iloHVZQ-6g@b1Oeil#62~{WkE5A3SY7y}yv0f| z-HWH(*G+yK@63)ASf!EFAlWm)?xUp+p%sR2gq~bYmUG!k# zQ!A^>NyxrIHwCi&9BgpEpyHfxs}dQ0Hs$dBn9An+;Rp`E=uL!0fh7n?)ZI)_&I|K5sPk1jwu26&~WH@XR{GmIgD$p-l5NWdzGSX6KhXpx^B(%+PS*N z=rDagYXGB`sYM2I;ja!T+yBXwatdo`8a=60vV2Nk7F{=&*T6KERz>kgWJ&%5&y2@p zxxv(vc^;R?zfp3%7(uT-Z*k0qjxn@K(MI3@(U+RHsfatK-y@)FRI_G{?r|CWYG~Ud z!8^ER+luaP`QkZk+aqI)H)7E$N4k9DB$jMLyAbVN>*mMs8Vv*HLt$jZ->WE6fzq%$ zQNGwHks1>wF;X%y68ajC?>@pBdkzeV@h3LSU2UAneffk5P+A~!x7-3l#LcpT&a^QN z-4c5YpL!;ZyZVQ5%9N@Be9ej0K381*{cCjA;L4;CS{$WUO!iC#L(WYx%x$L!o$;RY zxLbt%8^CrGK~0L!_?^QxfFrfSpfu>MMcxpB<*c(HnLf^l-_m$;QzScXJ^AiaX{y4V z1!h@AxigvJ?wWuu%tg4ZC%ukrXVJCXKp_~{%W^`?J!ZY2oc#4Up11X+=O2dQIPKyO z4g1$EiTdvt2JOG;#QrC@_&>y}eKP-uSHJy&ghBa#-DHCz*l-(m5|EK#hxP5Y(ZHeT zOSWqdSh_Rb?Sj0@4X=SEVMsTMn{w)Me&?9$?quu!$lR+9rLh2<1F!-=+MtuV2#hkS z2>Z@X>qwNmP{%La7~+prB9Emky5R@CC?X}!;hZj&gaeanrUqeJ9jW$5Gs1Rx=krP$ zS7NRhn^PEPMbxa<1N+^y?OvoGR=Rb13IwTDo3CaD1772?)QE@jx85+3!?% z?QLBAp5DVD9KcVmq@iHgOFbDskjiu9>&>pTwE= zq%5;S-d<8N|Hl32U8v0cbYl1`Sf%^7f>ow}^DY#PO|6apT4w&4LjF~)s{Y5CoB!&M zD}AeADvtQeko0d$4)jgNYhU z4<>gj&+~Qmsf!yV%f8!6(Xz6aKQzd|{yj7VkKRGmt#YU3|5m?Psgz2*CzH3QCxn2lY#3#(QhL!@WDS-?T$dY$?`QY#I|FwJfo7eN#;sI;a;CO zt5~{bRq&^LFw?q0iCp@3o_^XB?n2p}W3E!?XF4?@I&Q)8D60AsY6Fi7z(Z!L`kIqP z_Hacx-(o&RHj0W70U=F0*=}i677cz9Upg8eSOU%4y`TA`qupH9@sIZcW&Mh@iKZ1p zzj*WJ%1@ij6MpdOliPV&*bmNADo>l-rlwFih7~5<7zZt4C3(@w^1quyLj|( zt{2{rUvigLCn9{*7CrYZV=NTKMRyC6uu&DpolO#g2$fbM8`K>>^#Zpc#8uK-j8Yz) zO%&olhK-cc>_gh7I7xX?<^izDLTs-nw>EgvlCvt&G%lx0Sj`ptL4j!zP~igYBSVpa zXAxNL%j(pu>CrQDzM?vk6&?a>t&vkXD%sGgkNeVyU9&R!uY zoWt}b`<}RD5+C#fK}7|T?zph(K3*{qPym~SfDc_+VS)2Uin$Mb>Sb2JVbaHJyLxp_ zJv3*UJr=K0#g>tBb~xFk4fF?5CU>56tMs2O>YN-=7$q4icRDD7u+}w8xdK)*+72-T zMK~gk$Ba43DL%>Gk2RoXx9n|=7kNDP(hjjQ7jmaDkdH+>0utXr)hB5!vA;v^sVO_` z0*s&;#|Rla!*pO5;12A#2xdg#stn@6P ziuN!!5PB^jwdg3>B@D6Vgx%R+a1tuh&AH97W`fU(U6P}UO3pI5JNKUgfB(w9_5x8z z$oL9q+C2XXq8nZI=AJN{yB+2WX#UX!n#l_+Yp!-t3t&*Y8RpNf^j95Ue0vF{!q~41O^%#E~ zcEkXW#|zPvL_(y&`O`o!72gpI^fbm^M&5yLxveKRq7BcQF_Q%p-h{aE!j<`g_v~aD z*);AI33Mi!6~?f+0-(aCL0imdvjzPTFr@p*QxSG*Q9AXZ=lykVSE$pb8EA?5zsK>E zh_>zg-86RhJW|Zq(a&t;CNpMiGkf+HGvM*wHthEG*X^-bzr6U0cRI`Np-S0VaJSUO4yS_Vd(+~OR9chK!qDZNdmuyeR?uV?0tb~t0 z@1GF9l4@ePxT@)M;T2F?1J3$eVtSwj25pqlnEG2km#y`qpnAA~UD$%{?NdVuu?Kjd z=91v1Do=lMI$o>?C$q9tr0O_L1S?O9nQ6Lf)@gfRjmKlR-~% zmS_sMkmOO8O-h(8WsY>fK$D}^6xLrWNu~6gO($q$y}~DoRPTRmv|7H?FiWN@-or$n z+ft{WEkZrmIcw9kVjh7lG+VwSamORpZN=-D3`e*WY0Z|v5=zN>?+pM`9zc>AJLNJ3 zQ(`V)#Lh(wFiei74rNBZ|4kF%Z;5p0j-4Z|4Cz-0x*+CGj^!?0WCZAi2FT~s2R^_F zD&6HbDEm=(b(0A_@h`$^6kMiEE?`-p=!F8>q zcxuhuXFy=IH4w?=(}VqP576-U?Ng&~t1RQd@vBacdjv4CPocNqqJZc-MWEexAwR_z7LiRiD!h!?e9{s>U-=$@?Uf!#@>>p{l3t-3IRrMEm z3q?3t+&O(aCa(`NlR-gKaaA}shTe4r_{*Q$C%hSzj$UaeJ%gbjWzWd7$)CBCV8;$w zjP2v8TOq75uVBVc#al%iwRw-V^Dq_>syouE_Y+%g3nrhuB^u3OTyl&he+wpasv$fD z^C-Ps=u3JdNWyuJ(((Jco^B0l%PZm|LfMx0%of}5%iMkA#T83Gk!zd?-@@SWZ@}}D zpJ2O1VbI95Ozqlo*Zc78K5tTCJX>)0F$3-aLhteDNB4aHK=dw3>8I#lk1qY+g?j&g zvv_4C5hlj}9&}NpqHU*Sis{pRxt3#vrUnd?Xr*T^kzo~IjEF@`nKy-Ilq3KR8bon9 zb}jBOKb76;$*LV*R9d>aT)wK{7w$i4By!+nC!x@ncc9$Fc~Hux<8~8?uH(7%+PSl4 zHUHD(Jaw}B zM$pNJH#Cf1B^S}3cxH^gJKO-0l%us@^O+wA<+a22H$i9_qE76E1Z0VT8$;j%p%-l= zoEv2z6JaNf$#n3YvzOpu59MwqP7mp7%h1{lBs>0~Yk-?DA@`hZ%r)hqRYPuWG|Zk| zo0^k|^a>FnY2ae2x)jHezodXhM5aR(72$26cI_5#P>IG1*U(&bWkSR7q(hnI<|MDK z1GIMYLK1JP19Y{rz2{3zhGH=pD%r%fev4Tea+l!e+2dVv0klYXKXk?O2H3?fcY{?b zJcf{mLgs7NdXukG^~NJDQmpG#ZG}}2-G%_sXBS&Oqco0+RmtZ{&AcAkoPNn5&WyEC z+KVcG+g5IYI;oF9*7r($|Q@lhS|~s369jT zUw!os$r!j~`n`mdsm5o_&HW4U0I4+h4DJico1qjom;!CsX+Y$2xCkG|crrUPqeA^@ znr%Ka6-#SK#_~gSn&&d51c%0gwH3axqTupHln3;xdyPi7inu>thO5MOSaN?zmIH(3 zRZ|dQd!bfLco}5-od#%3KDGZyEv^3*Fy}00-%Bl*|H|Dbqz^$OJ~TVHhVHjG{`-VW zHngy+NVz^dm!b-hKg_E8Dj@bl{mq zvJi~odfaThkaEVWw|ZWgMsv}*lm;CcUIl$r#6FT%Up2vYG(k{~kR56oqz~2KJK(XU%q~&kv|V(kc)G07(X|wbNIX6+v@^u?X#;1enHogu5Hg@G8uevlosBgorAuD zVvMQnqJ6N9DTUzmN1*^svFOo8@%Un}#w|yK!u<|rd*=>%rOBQ(Y0)G1IC2)f6u-wBx!)bSq7&esec&L%rvQR5SYlp_l=9hDWm*xrSEDp!raA-VGHFy=h^0t&~xNoK)+!aRd;tqVRn0b0N{MvP{l#IBXt~J?#nf`AhL#McI_NCr6!XhCkBG8XcC2Un>GpK3f zK#G|N;ibgaCX%&8k;N+@?wh1t9087kW22uGJp^A@OH4(Y+3E{7bW~ewwLqI29`#hC zoe}X@uS^@zU>tGa0ipwmx-jrFdmWk#>KlHl>$S*niJ8+GfVSw!Woj5RJhGQ#ByevB zA4W|5I@L9(k^Q)1S-{tQkg6gE7*OvaSI)>RHVjj%A5mOjnF?#F^@-MoeAdS-Nk2S4 z6vFNjWDgL)?}55H221*Yj>L_q$`Ku{(BIh}-r`5<<26I;X*uf&I2Yt9q$)wkDT&G{ z2-+<{b>TkLGXmIKl z)pek?C$FBI*3G9zs%8xr3VMr`!xqF=fBNHb1bud%pgnt_@{vowu}^(qN~iJidhrb7 zTCq3F)j+7_7pq%Yk%SI|5rz)K_O15KneemHF4{l5H!0OD3O-ONeq!;V>8=o7-$pKh z1Ezdi&io{q=Jq{eL7p;Qyuo1XPVrX$cvQB_ggm(+gkH=8V-lB;kD<>zzNQ4n#v*n` zUnEv<5COfS1K$d?{q=^NjcID(rZ|CmXHRK>f>^=P`2*oR#minsyv9cp6d5v5Y*iTE z{iZ?lp>wM%g|;1B);8A&BV0^0Ji(Gyy=x70K}C3X8Oo?OEP&P4@{K)6yCyz4Uwr)F zGuB=t&#)n6j-k#hi+=1O&Hu^~31`q<0P0>KhvB~XJ zV>fB=miMtKFj2<}k8=iyHGsC@hL{XozMAXUO~9CuWDHS#{8(N|Q?6lEk7`<1OjFxj z*`3(djvK6|I83g1VE5Q?sy1*6xo`@13~+7~M{d{+@OPPgW^4=jb{TmOR|fIzaewCz z^C?c~Qaq_Td{-@N+J7OOQQ-(PK}giH-N~UE`dB)5OaLXfFP$TKYjjJNcP$BrFD~X} z3SJnf0ZGGJIwHm7mD`nJ`K-|t6ki>G=LhpCJ|KLf|5GGPB#?Pb|1A(s{wk#Zb&>Gz z!m$1p3GDy9AJL@>W0$Fn`X%GiP-C@WltF9l5+JE-#Y$-|2vu|zK*DTIPg*4X2Ho_h zV~s?UwL>4@+RP8!++7T4LK82pF^Cg{3Q}6W(Lb7klhdELw5mTeyk?Fwnkjk`vFH8! zU7}qs)qYau`rxl#k7wp)`#S{R>wv^pnEkjHSm?5}&(|WqJdA@r^kR{sIz7-L9-fsF z!bQJD16QHo0@XSO>q@x*TgkBi>J@CYlV|!EC1c*61qauMxVKc_crq5KY=Ys@T?X-$+Yfb(ZSrbnk@le9FHA; z7t7k~9HL<>@$?+L@1I{yR-Rl?8U74eY0(Y9RP78?;>NpJh+kZ-r@?_ESA|Ue!xu~x z6jQS<2A0t#PhUlg1E-yYwTcw(YQ{xW*t%}OPg^e^5wgTB%}oA20M)mNz*FB)U_4gr z#*P_IeGnjiM45069Kp(tp#U!Z!lr8cG%Xr@lDu0-)}yf0 zNW4@Lcn*#JBBBuH^W2dH`utUGvXz}Xt-L6#t}?HoiMkXI$?!Ktf*}{KNhHItj6#`e zFA!dQMygK7hFMrZ{@&EfhQYrtYB*O~GIr^5r6?U7HDbe74S6o#yXn!2eZ9nUIZ>{n zx&a;R1a;MbLPLVZHE4efu1&0BAhjNTAkbMO6MEHi;7({BgDc_lZuNRujAXGy7__1O zdZ~!*Tt{{8piNj1MpsW4>}x9rGm`S=B>U?Bsj=B&HyVZ(sbRkw zM$A6`W91dL#y-r?;x-75?vH<+AMRdh@wC&vICs(HHsH3=WSLS1W}dRUPmMkO@z2s% zI+ZTtal{$w;;!NKYd;jUPGfD*Z(iCxY?AM{WRso!w{}S|zv)xoWZ35rk9kgbMy+nO z8xk1UH3ibrX=^ddPkAnh`$l<_8nj7XS7qp885*8Gu#-T9J}KItVPH?V75RrtAcnrl zYq~{x6`hFvr=+V!MlQnKC{X5Ma{Ppq+hjbSxG%bq~2XBjKq+_e;vvSA3*uc=KG&C8L^(kM_cXyN22e6Ut^vD1Lv~OMl_S>654$7W#ziIfoOpoelm4`}Zu;)J+yIdV^94hrX;u|#G z$L`^UrFTI|^f;sQe?8f!0<(;sc&OTWP5fKwa8!TA;kx9%^Vp>RGfP@hp5<1@xD) z`I$D1a5&u)p)8O}T*3y>QZI+Im=%>$bFenl?DENz(LP(xPhNJIMgLK@GBU;PlVVW> zPha$ch2Ihqwt^Y8H#E1Ns-RG2f-x;lXGol7l8KH`IR#YU>_v|wr^Y`>A%7wa_l;9X z8G}xjyqwHl_>|ZCj<3WOWLvP!B2P7Xu`F2)XlO-M%!>co41a1511i5HZ@G`JeMvZB z%$^e|Q)S2=uhBM#ILz3}X5p$_@UUAqp{R{6#(-vyFWxsoP|7Hmjn-dxOaR6*Kzlj{Tg-+l&C*$=r_AjnhwUpSl>&tz zuvJ3C7cnpT1EnE02KDO`i;IrUHu*;hBt4x9dORHw1yD_z@XKxL^WBuEQ`qRj|PYe1Pt>`i0`(g4qDfZ%F~XPD>9 z0f4)AP4I)KA7Z4y&HpNe-rw}ksT*E_8<^}K%j`~JcHhG5j~Ow_ZkmT%)HW2|q@ve! z=6!edD0Cy*VIvTo#HrVIr#;fM0XEWbTk)Ud#t1see<`ZS9WLg8>k-6j_6KCm_{D2? z_EP{w9<8F>Ul36vF~cSW0~yfRTw*=w?ANWfjg^y@`X4v zrc6tTeLF|g0x5LK2)!ZfiL}W1ckORJgfhu`F>QYvGt;o`IFa*WW`!ITu`30!E0Wqs zeG~W!YNuSnGsA+XEPTIZ2^sJjHgAPaABXr*;Ly)ya=}a8?-|4mAHbjt7~}f)-_U+l z{z)<#R2V*jAX_zt0xhfCP~3+>pq|8BnPPpY1y?X*ZNeip;uHNUw^>3RCrMKO{Q=)e z5s72HR7#&;#|OEu_Bl#>gk{4A4oJ~rwAt~(ZYt-Yo#@EUbbXdWM=M1@H}yDQwA4dH zDHBrWiD2`C>P#DG=1EKQ0Lwzf>O_Eff{i*gze06_Gb4%Wgmk^mvt$UjSagYTK_^Yd zA>0}fUrLoj_-S_ErMvnhZ!gzK?`43OCUz=CjDX>v4^%XPf>K94fNTW4;l76rV`js6ERoDLXgzH3F{=- zW1efS2D#ZWh%A9L1K?jZHU{12-f0)$zhw@lLg7ar9+b0EO13{TJ>Ga0r?F2*g`Qy^ zRzEqOy^_lv8xHZYM(d2c?Yi;CwQEOhl*XP)kA{50E{9CokUWo$xz%vS-VB6(7oPMP zm=p6ky)EFWrGL%Vl_F%FZ@NYc|5nz#C()??N!v+G_WR&+(N*VN_n)#kl#sh%?{Din z`hS_O{_k0|nEz^`=jd+z{}e{c`|lnk;O=DXsAManZ*457Z)0m?ZulQ!a}KzDrA9l=@Pr{F0MjSJ3pzUrL1>E`;jCf`Vb_%Y${woeWG{F74@4 z)p`w`84QXEH6TiFwJQswcKyPB@?uKL^0&I?aqM}|@|;PV^m_ku#^meGjwT9QhJh8U zlBXIZh2t5gOjshIi}GH;PLLb5F`P*`%W>Gc&=${Ro*b2)lEEO+kZpLeip?ZZZ=zsyFrDCdQpDn0-;0_6Rj%c z*{*?x2o}w5v!?PC*c)^RZCT}QVxja4{=T?(m~etM#L^MDn9D#)NzEM3VU^dSHQA#Y z-MGn0z62IF!I|yr5?7|UwJo#$Qrz#_C{IqT%FJA_?6`dZD9c~Ucz{^lYTTjgd@Y^7 zy45rp$CJ@*HH#*)Dp)WJ6z9U} zbhWeqNm?Ff-X6o6^UYo;s6hS@EV}Xu4wAWCzAao|_GDUWGPS7uhG<7}gzspM?MUJF znush(rBtclsO*7;WCXbOrUzXRpDz)EFOOa$(Ip>^G^b6SqnF0J6Uv|5cVL?SA^K4? z)amA@z}e)_{j zJi-zFSGf3yZ86|M=$QTPX|cMoGGb`=8UipL*vJ}PO!2d5ON7`t-*1FyDKBCR{G(iI zB zl!-~Evy10t3F+%@RiiE%w>mm0pPy$@mwNI$)0JJLF44+uVV8SKI!7qIM4zLT+L%k9 zx7T%4+r-oW0`Y#k{KQT@xU|@f@!@Iy0{;i058v;&SAXa2Pk-HL|C-qT6CM43O?mzY zq5l$CO8N#?#^N?6w*NV^DpJ}|K;}o}K@KLtPT}Hj8xxjO1MHFIYbgPbTKGax>eNy- z(NJ57xv*s9?jFg0Kvqbp9|hp=Cg>Wi@j!(tmx6U?F7PmIEtr~kbbr3yqxQ118kqH` z28%>8NzqF&N-=Djq?)u2&=>3ht{Em7CmAN0Xy`Xh-Fk27{f8jqftQ+fAEAN!QDz;J zFRC>9zS2=~AcbVL{AO9DEiY>{Imi)Dw`KnP=?c8M;e1zN5Hq5AC%EkrvP+b_jaP?m z`Ltp^0uO>r2JMd!e(%kTa$0!E^kTFG10qlVl*}J0@JF_K%cL`R?><>qS>|!M_de2U z3>o$$nSds;qVwzko>Jf0aP$|52jA>{;;HtRNOk0CsU_HjO+9Y@LkIRPpK6{Spb5+< z-UsYVx#GAS(S}RjV}501UdV8yIGCK|x>f@_-rp?=kx#kunEej?kV3J?oEdHEvAYjt z(so}?U<)IqL!?3QyhwL!Z8~HupY>aVJ-rT|7MHEIvH;T_mljslURsoT-KnuaQj{&` ziT;rYuP;1W^st38E*B(JOZ6{9WwT^Ln>-_4)@Wz*ZJP?}e zWfM>V(G53fM;~%x2|sf|aaBF`q}r@t2jxfK5M7nscD-lWhdN*ioYN5)J*CJS$DriL zs;UpPC}?UAtVKddL1fsE`OPHfAlxti~w8=UBM)G3}kVfCfx|WYF;qqagI(` zPpo^eb@BkM>bJ@^5(o;EaUD?}%`%DtT1B}6+C}`hf$`F~fwjJIU3+M~nyykAc6sUh zuQv9LdIh#eCd2!9hP)>Xr66(ImBI9Kx`tk+ewqLS~PsnI~3GV?|FB zMlh0X=}C7CWV#39y=p*P5+m4AJ0tZY<-!Of%QK<0$Zbd}0(`z@er}6#hc@T@12Qq; z{=4VDAT#|NlJ~Dc#`gaMvj2jX29%f5($e>i>rQ1FiQs6glnHpSFjPYAU&iMv28<*E zOaV2TA54fDFUE+>$W$L%>RYAJ)VxmB3c|9i5#d9|Ur^d4+@VpWUDfn{zqZ`m+`R5{ zpXInSF@aG)^tJdty*17A@_UB!F5`yV1@>1^>q692|8+m;-tO>N)CA$C&D(LSJ~AHO zm@^^Ced@UB_{1VbF?1@{loFvLZ}Bj_@}LrfqEE3zDl|Q+5!K+7n$561^07&$pp;!` zn2iS07_AI)Ndsg8Zhm5qqFN%PqVZ;MWXOd(d8)?rNR{2(rG(A2bLaz(K@#>v&=w`u>&EDmMTy$L&cjwIy5*KZ zmfFk|xci?lWO9r!7@U29?mc1nxx-=bx;a7v8!ZY}4xt8Y>HHzWeVMv7N{y`isi;)7 z3&bnn=XI%vWH*goWNDK9tq4woG9_-(U5iNT^H5Rbj09k?h>PiJb?u$iMKwiD-IYZ| zZC!GLeBic-_%J2TWU-nsXQTaiC*!viAJ4ZkwU_;iAd&z+ZQ@W0zCx5!1Rd0g{$j$>j-dvywOk)cH|! z=^jlC>xkNAsrN=|dP?5Xf`$v}>2Ig|#p_EE$xAHvgIvJT#no!A-2A^L%Vk|!WNc-c z2R97T79S%Fr!*DD1|Jurr_Y+W=I@jY9fT{Hx+#*y$ksCqaj&=zwjMw?rOya^i%4TP1_HEaq*3BK4JhD zBp3Q8$`5nWf79$W1-ZBTF&fF|@2)|4u07@>i;sr~w4i*)N@~X zu7;I$&!FD^cZmwgM!8Y^VWzeR^krz66iG`QOD3_LyTs2aY%ks?t?KF3XZZY+ z#A@B&7O*^1>L5mqTX)fJG{T8AM=kcQ!yTFsvg&To(2SQ=TT_$eeQu@&hU-ZYON*Ja ziV_$<{VsV;6Y2#W(>j=%4HdoYJzYIQG=5c+*0|3mq*_9A8g7JiN^;MolRZ2(4lg)o zX`kWJ9-TkPYh$ z-tud_y9gY`tA+Fq&Yy~hUdjwn(lla7ktNx%r|~pbHKuEYbvF^qY!4t=GVrHsTL@)D ztK~a;2)1|d%yHfrVYG*CCtl{_UiNPf_*XYI`D5Qlx)@Sw&U&I}CqByb*R4TPbMjD8 zrbfku*ZZi+So!7I@TSHDxkvFu zqu@_S5HDmeuk#|&jQ0*+!D+aRqnX2DB%O+}y$L7Ps7E_wbtGENGMB;j5Z=CDM6sL} z!Tst3^!p7m;et%;5$Qsr_usJ+n+VD;QPrqYS=Men))%ypq z1s``G+BoWFhmVI?`Z{{TQ2Wla|FbTtEC3I7*Z#P3E8x427_Uz7@^M$(z6^qISeDx$ zrFD|n<*%v!UGZ9H?{6Ci%~kjKI*Geugz(v8kk>v5!ZkwH?e@3ZNWji+iDg|(ua1iVvIQAX2@-XSxFy!OBl)0BIX|M>4@AgSkX{(%*aR_F*lB{fDgUTufO<%!)|a zoGh8+h3)%OpjK}7^@KQ*CE~5OWa9%G{e#+lf6qGaPC>@%O(zEH!g?w$Jgfk!Mz?Kk zWsZ<=DpeJZBOIzEE%m180V-!`QNa2>3MZQoUnSZ*#*iv=`G?hV5VlL<{GCjBmo)yG zSbJw@R*}LV0@9WGBtsQKQnwp^p(8ka9%&OK3JPb3JcR@^bG@$w(H~xcgEG_b4j?EQ0 zCh1|B+>8r*o}quvh!4#aMaFLcufC%4{@LxoWfWWb%Rk%&P3dCpd`SeEBd7|Bn^`b9 zxV;ZHI9kG-ornGq7H2PNOO1%DLOb-`el1Kp&0}Cym!gq%$H6yB@#kqTY~gOiDYW-v zX5GCu7B)H!h@X+sIuE6aI@U*&myJSV;o|CxWyv!;RLe3A5l@#=evc~N@Ra}pp{06F zegJ{mGc^Co4e-F?EXx@^r{iacSN{Z@+fJRkD)J>Q$tv}lJcg+R@}Lm`h&gbicq2# z{t|Wk!gT!7aIWc}QGeK;_LehoK2z{@((u-zN7R&vGdBu^2jt`ksJ&|ns{L-Dmjiov;!KfmH44>Q@)6Fk-mGRNY^!lx!I3A=XgA}+g7ey&|zpw zW4>YBI-wROP5JU@Ttln6Xj(?yK4J4Wbm`%f`8Y4LJ^8>HEYGLaimp9v>?dk8&=`Xc z#1(EGVhgC)p;2^aG*?`m%@{g)x}54!^x53-9|@kMQTHr7AgQ&}9ddMMBZGVO0M$+I zVNNe~%(&iw*YGhzxGF=ah%`|W4EMmtJtX#b`ZLPFH~V!vp9|EU+PaZ;Pljm3Spj+Q zLtunG{Rh}()$9z3%%%g1sK>p>PmCEJ@XSVg2fnE8obJTgImD_$a%)KWKdgSxEn`ac zNs3{tPHkny^jIs*$9=AGsa8}E<6>3luv?aY&jdIe|1UW^CHWOXH?!_h&t-iDuNwiz z4G$g8rb-0GY5bptz?mc>Sgdh=syfMDA7dZ zU8*@Af^=*4d{KA!CDHrximM)P_remdw+9$3B!IEEA5WVIunVa(1B5nyvN)sud4t@l zy9^Nzun7%WsfW1O`v#q-Tk0KG%QjRhmt#Wni6U|2V<238 z0-9tGDvE7s^Hj-MgjGpqL+Zh-#Im=RVBO5HAfRd-P3>Y<+CF{fJ#EcQlBR4ulM~NE zcSN|xUk0vQaL@cUO7M5(b9kZ2T^^>nkk(6ba;3p|wXZngV|LJBM|q`qh=MN{>?(Tv zwLh@h_Sp*2f0HP>M{ShiJvDFH7h9&LmnxTA?y}Y5dt+b4F zeL+Ck3*^I}<(QT{9&i+Gw3!XFC00D?gLIp( ze=WQwhb>s0bD5na^?{7at3CCiLV>>1S8*2ps#wHi$>FVA_Qp;gT*G+d)a{7 zyzI2(1Tj_ZU4z}Vf@WWz_>UV4Y!Fj~yXqIc%j&0_lDYYerU!qEJi4*<#^ZW$FP^4GzGH3B|5TTtR7mWQbpbVz%**k#YMX zu+1bgJ1K8XAhvYI<`Wb9rQ+gA^Acn8JKnWenL+@ zx`mP_{oyz<%&ofpfIFO=pcDJUx2sOmV^NU=*C`LWbkl)iT0h+gqDor9G8NfSfM`=Q zuw-LW;J&+B2@63nOTM~h0PXsp)A?nhqN)LaHBa>->#oKX5zG|n;KDCQRkZXKbu*oi z8--^Il&4MsCMnEpKNCs~DQ0S^AS31;(Y9>;{g(5j{*7s}nqNag7?MSaG5acEqsimK(RisPO zUb^Bu=ya52X>We<9zKT;<&yxm<$dWMd=WobtwE-oRXQ;~4 z;rwi;d6G#B##D>O<7bSHqTP|UoPA46_Kx27kS&!DD>OB z^(vBMpF?wq-36No3Ay?Nrh#o76fZc@p^?u;Zkv=e@<5QKJjATV5>AxIXxoia8nNp= z{t>`A5B+5o0{;U1K#@0)&Xo>|IS)p~R!S0RVAaDwa#x77=L-GuqFnN!@j|m>*$lu1 zd&6b=$F$Z;OgZ`3AT7TZ4J4E*E|DR5y`D}6A@iJZv$@3-#rf)=pa2LYc=wT}q_{s1 zky)yLf4C{zE{VuS?!nj;_cEus@DIl16EpchJ+%15D8LmK^F%>z92w1o5UaxL+6=M8dfESW3i33ysx8Li9_sCcINx$Zb>wo@DbI8?aI$Mj^B0XD@t;ntEi%oV)7 z<2xLndh7TQ_hllG5Q&q4Uu)~+#C@#;s1Q{0)<%JvV$46{rF7FH9ND-!K1E%=O^geH z35H7vvEuT6lSsefurKu*B~iL7=0Pa)M&MY7p_tVvbi4bx_6K2<*+)$715*BKgkAO> zYA8e%(jR@ctjj{1?-%8E#razsip+15Wn%FU;GV)7l9(szB4UoiI-e?7kptbus0&Ny zLBG!K)B*EVA9f1MY}vvc0(7BedH+(|!gX4`BD_Rn?g%I<2&h@OHC52aqhTv|L4;^T zRA%rQ1H7Qg0y_#@Os8*%+C=b?$bPO6`mizyY&!gbiIG?KHY#=(1m%!VwNdy6e3m5E zp&+%)UYi{09k(Hga5)q~aJi1^O<0moH6>#fmK;)FQRNW7W5#n}yqi5s%a8o>xW9hLkT*t9=%Epd zg3A#EU=WWG(va)dbHgzmo|VQY$P-J-lM|~^mKa85`aL<2X&llxjWWe1H`EEL7}R72 zSRQI^l2q7*WQGjXW4%mZ;Uq-dHfs5!A1QRw%=B40V17|v-07}~u^d^%k*|abwCMyM zfy-0TA)?+3$Wt0hChH;#VfenZE)e@)Yh{@7oc3=+B+UiqL_ybX_93X*-fhL!i2RXuK(Y zdTdVd0S7*!eaZVKmPo_|mI_=4sj93S6>XW4>o)Y(yk9a^;P{N#Ctfu`^%Nk?NtDc( zlMn%t99lo3!IR=zy=0chyd56b zByUvCi0}@{bsxCAtJ9QidfwT6`bXOF`#6+2zHoTA4jwQ{PRa!xOO%f(863t~frn#f z3^gF4-W*3Ms&VT!2TghJGR`6PoK#ux$pA^YYw2L2O37F#3Ln^W+}tGnjA zlKZ(0o-=SmN=yJ!>U1ldtlZ`)lX&fjBo>5}6Ob#veB2FV3{tAg=6i%fq=Hg;Inc(d zi9b!PCX7Ny(2fB2Y3Ai1_Oeq<0?G)VVHKq5LZnLuIYM&wJDp%U7Ea6m&H+N=NJc6p z#h`gJ2<)DbCb0u4Ddj-R9ZY3{x=!VqKVdV1wGBb@NVzrg_+|WJ49%t&?tZ}tfokQ+Px2hs*m{MI9-ItpIoz8gfQoOq_|jbg9^~QNBL>WOsMM7N|JS#kh^FCrdyU-0iI?M%!xw!Q1X5+5sgyy8i0(b zfQC-@vdG!WT}R_Vxd{-mKkvK0Psru1WW=gSb0uDyu5kT>Zv43h=>!=+9{MGm>LZB)0uRwt zPO3BdI`2-Gb&4WQp{MKCmNx$PNJ23BRDx(-I%?+l5lf}TxuyDQEk4Jgs~CT`B=kKu z<;aU1k!~;OA0m#Cn*yzF=6zd$t=iLb#NxrZ5h1>!uH6@Kl?GLeG*W=}Bfk_`2~UF3 zrV|zzFV|6pOU{??Om}YycGy@NDVokhO4@sI&P}u!SD$#Gj@HfrL z#2#|vPmtqzttPK232Ba)uMl8B%KdNRKNwMrV4UR0FjLs8^a$T1^k7@R0ozKl`^BN( zbPMKR8^G*>mK-*+O4SNrg?xKVo zfg}xG`AI?#i^-D$Iu@Wf6QcS;^h;e-jc!!Hq|@0dHo8lNCt*k6xF`7sZt)L8I3qRR z-QgEK2B$X+72qt5u22~|5x;9uF}g8M_e$sbozB_>mo5{k(eFLn3pSaKaZ3;-wqrQG zt@iqOJ-%gp%wBLZ!OvE`RfO(0^Vz3`xSA9bWmupirQA}}$$LsYl4N;|dNYvL+4GbQv(tQHl=}*&u{Pb% z$V8%!s!h|3=J}dW72(cgnn%-Omg`2Fo`v>LnF_Z}bF`QWdn{=!X}7bFZ|78YE2W+@kRy;# zb$R;*IT{)>GR|Hh7$hpj|3TV223Oj4Tce$%)3I&awrx8rwmLRCwr$(CZQJhH9VaKx z^S*UX?Q{0~d}r5QwQAi}>&N|T%pNmFU zlA~8!l0*LSefu5gG(%?1AQJAhe`lg$a|1cPDxR8TDhVxha z@1!H;Us1({C$lr>Nw*tF)aW$Cs4BV>rB*3Mqyr}h^YNh~=RYH+8 zS&3k zi}a&yy-N2%Rho0Fj=tVk$x~xh?(Ms4asDXrkx8nf2d^Q>=y*W0j%^{0CiB>)P?4rs zFLVgn-+0jKL~)7|UQk*djxdSxG;ZS6;Rzj!xkVmxU9<9!~RjMz5{ z=l6UqMq3okN|7O#ALi7_N;EAF#{Jofea+KDy8% z#Wm^BHb4O+!uX(s`J?XqoX<{i_V;T7@Y?FBNs)eYZCAeaPJRvt!E_1o8lFb)+!UG03JyU z5i{^3k@k})CFykQ*y7RgjJOoAY%L=BLlU1O7AwC*RUuN{0+^L%gtrcw6rE-mb?%jK z-m|El-@vqXe!|a;Y{wXy1{_S2Bh-SEaQYWit3`&yw1Km~rz zhssGcoHQJNEzBO#Dv~_U~q*I+Sa| zVygEv-{%A$Q>u1L1U<1Y0>a+G5Apnf8i#1bj<+(!9fk?9_wXQa1(2Vn!o;>aLQ! zQJUfY3><`;5h8i`(_}`Di?q z;z=?S=>lLb>Hr((COUmIq}i<&>3ekKy|BLSKyqkTALyR z(}V_OT7-$sn{!p}tk0};<j_ymRYKQ9>h#V z4K-FyW?s;&rxzXz2Ie&ljo)gb_|469)EYWSId~ku$fR?zvHdhpo@F7c%alpi)Z$8K zWp1)Mx3b=HRT%!Eaaz!~L6P|!UmFxZZy7%-%^4pC+Y}A$NVbnNd)ZQHYh%f{sJ0$| z-uRj?bg~AR&DuOM%46kWlwV)KlPTni!^#J7R$`8o9&pdQS<&HYRO~&)jwm|+4zhQ4 z9$oahZr!e?X&4%jDM^pIjuAeU)u92oHPxUxQ8T$V+eYQC(!h!K$1&e2W zMVNNT0vgoFX4C%URPfAs{Cx1+U(}l;E9{lcsu@AP>&!F0Wfu{tYB?|1JGGGkvdX=Q3!JYw+m}Ro0ZH5D zjH8*Nrb5}Q_l5Zm{(f#JEVWKf!20SWRI?|SoM^Lbqje`~Z(E?SLqeZ$j)@TyP|)BE z9G{hNL47D;3R62k4x>zk#T>{%;X$7|=13fGJv$&y8^f4w$n4q)!*gTx^12=`REq22 zC7n|A_Wq|*l)Cv^^jmjtI*?-?-7lFI;$LUNVft#{v}O?a+mY48YcXViv}r}Kq0L8? zmqAv-q)?{#0N|ju7)_wp`m;5FFybE|D+F`FwxNA>d>;BY{)63)3< ziMjd5bZ!5z&Hnv_*MZXWx#t4psq^;XhYYtP0QD2>+M@%h2mS+pf4lM82dE=B9>^0E z1PEA0V+@=;nbEkfALvju>)Uz0;Bs zzB8UVU;loUTgx!+1iT2eRk@JHE;e0&$4h>#aLOl+dJvO=cne`G6E(3Uj>FU}rgfFU zV^M#AzLlO?P8iR4-{Ru#y}bL(Eq7N$~aFUTZTr>ngI zrCpY|sTJXkh^*X%8E-MG9-Ht{t4T9%5uO|BVk0HxDDbuziwX8(42(YHrrq~Z40;@# z3?7=UAjVqP%6dMT*(~qYoq_w!>fpV&lV|%=Y}zhY&a#xLFqwI1ZZFj&ab%gQWzGU_NY zN?GEXG^SArmmg38>4Hmbq$j8D?YO3pyQeSxt1q`!UV&L`XuMe{fCco!WfEHfT-5pO25YYZky!mx^()K6eq#sfk9xF!wZz4nG5)4bK~=zZa?G3{<-ApsgX<1Nsb^ zg7d@S8>v$NE4%jHkiKly@7W8odr2Tu=$FRKAZ)z#n#j;@R7&tpY+qa-mK~0t z9HdXdL7yEm_C#f8j3rQao>TSg^0N6mR?47|J?)k-2V8Xh^*VQFc#YQZYK#y=xl76i zW<@z+p&WrNcwnre!<7;_XMllZXRthBm?`_36rAA^!9>~uA0F!X_H0;ltH%{QgOA>N z`@$dVpTm@TC823Rr&a+I%x-9)b z$R6du>rz7GQiBOaCU`}rTK>ttRSQkD7`io=5V{0OLO#@f6OFu49(30;*xWzhIJ%)GeXPlWLR^^N|YL^ z!mY|5d2!r;1FxmiHrEPrY3^O+9WE>n7v{TEV zL7{6zEB3SS!et+~Pf9#lI1&L=>1w!wHh%WNBpRkLDEv2=NmZ$@IvnUd|@V zOa+f>{h`OOO>Ph|>jONg9x#Kf10KNp8RH!6cuZ!ltpiR_Qt~+!s@hr!cuG{fO4Q!f zOPviP!;p$VRtgY1AjxJ+f6NwF2`d`MC8a!z>yN_~E$? zDdje@*j6*sJq>Mc=gy6Qymx0y>#ukNjY&=JD0w3-t`t(9HXQ18V_?1TlZdFcAg(tRZ7@NZp zWIw4FDDZgeE;r(UttFJjFhS?@Es^#XL&FjpigMgfbvf*H7ei!6R0_267EG?I?-s~5 zj9MGpG2J71S&QI|-H#yrESliFA{l3wr-vA4IQ0b{*SHSJ;ce1g-rrrHIPW;4@FJDD zc54s)3>TRAnm|hH2*4XP_`oX$ z`@BX(fY+=l=#DNGfJr{tGb%=2izy^Bl6KGxqCSDnE2YXib^gLxf5tJPv`qr!8GXF) zI6B66!0|xDT!MEO;qLqWnvhnBuNUR?d)_I@z~Xp|;ybolxtcg|_YTy((?*eZq+A)B zZSo5YuJX^lyHgtOs;wb~2M_M@t={Ivc2}Lw;Ox?P*M51|ary+~7UfX=vYK60g#P>_ z4DZfQkI-K~{LWz~_w5wdiXph6e%3xzA4n^qj$SZX-9ey|h6K-Lwn*)pf%2Bq=@D*L z0#VNKVCF!%QR2-Mix%GQIZl^UpvgS(Y(S z&88TlRv$X&CZrxi&_}qO?#sTqI!}AFm62Gq@ajve;&hprWQO@M8OQWW<$s9+a5{># zIXW&Excf%!fP9(5QF;r_VHOd1jc%H|q8^~QWQr+euW`CRc?o-gt#SZengtGBXr)Ka z;d^tP;3^I#I^oG~d6an`%VOasI;l(2#2KL|sx;nMI8g@*C}&CR(7aT)NRrD%&WE(g z|KXjFS|3rU-t%I$uWfw}NvoT}vb4}ZuWv^=TiaR%idCL}A5&Gy5 zFu^T{SlD>`yG%UQL7>u6B0PNgj{`9ut11`3-mo&M%3zblZG{>Y9V3$2iKasoNixDI z!jh?P$UVbYJ3!J9wWuLu}=+Y5_f4R2x9qbLJs{k5W*1P(AX~j z`Y<{tuesJ(W@U1KFyTTwZKWKnKrwWp`E;Q7QAmBJSwQXbNb7K!Z#?y$z;3_jCT=58 ze*XnySk3XXPJ$~tD}ofl*ccaR6+t21Ny;wl?rTLcZ;i3_i!ILXBed!xdo&K@kSKQeUqIHc}hN}Ku5 zoLVaQ&tTZ?$?@Gmklc+I)7-Cqk4~FI{W)82<13MSd9A$%w`j)cowMFoXLWc+pGrJp zs7QGR8WU(1cS;zt-D02OV{LtvyITmJ?TuIy%(>jTbRjSkRAen(7Mj6#p7eK85|$7cAb1e-(uyhg5F0e8)*Sdvho(9V!4!P z?$28k-e5E?wJ5P*v6aJNW~<;aUMj3df}EoEx8g+HcsbEIXn@Z}i#>~?`BCqXG)l~8 zMhm-Bbd50Rbh#SBw%+RRO_0ln*E0coQrIl+dwSLbDvn=n2&*Xt`*b{mqrrnyLXWI) zT^GcdUr^|tmv^N&;gZV69c^0Vi&@VicFMIEe`EP#C6`NjYUr-WJf9h|7PdbXZu^PZ z3fRz{-TkpAIaEZzByF-^tW~OpAL_rlD|*wi&Q6X^#g8FzhnB~W_Oq+_pwtF?@FE(% zz&<)o_U)dR#1+cFR51F3Pdl)|2mIGibFd*UF%kT?Z;`nF#PkvU(@^tYyEy;Wvr-th znde95*_S@&hL+i6?$BJD3$_yLtD*G+MN}*xrw$_o3b!z*7%(>|Z}K02>kR@GR~Dy! z`o;@sXF5bVBMh$bWe9f3ah%00x&dyfR$c~ZMq$FEbnAa_>i{RTCLrU}>F)c2WXoU4#vL5(Y2pkOYD?C zPHQgQ%RAC%p9LqxGuwHtP+(5~C^K&^bC#l%{$NtpjxJh%b0|5^H%CStMjV;zt}do# zV3wT|K^2`g;E)2ewbCiDVzM{r_thx~W$M3X?=v)1Sx|`yb&0{L6fQH(Bv~Xh7UB;mMvDm6d8Mi`}h znYcV_acN=;JL~|2qHdsyi(_lc-AaJw#TfeTR?dkJNoUzHV=@nE?QZ z+lJ<^sCDe7yBeqxEM-nN=I;?tvpb7Vj=Hd(zL86|3l8o5hTU{zwH}1+bo=@TL&YG; zppyXK^PLl6Tqtlk{AM)a-lwjfuuaa`p9NTBCC5#}`S_<7?mC@BIef$^{H-X$A0I}x z2hp$x3gToYmMe++Vo|^!vTzS}d?6Gf7MOQ(D@t7cZY|BhL$1 zb&(f~+4G`J$ws2A^PbU;e|9H8Pnd#nv4Xvcs1_30 zRT6*9@Cm;1Ymf(LaCS=CsfeiZ;{Q;Rw45?Enu=N87FgbrE0%O$T4YWX=Ey86$Ozm6 zNV&<0_j{yJ{H%TXgEv7lxFNovR20fGcu-cxYUEB+*sRp1vN&C{G2?s$b1{Lgt^^XE z)LL~((`M)oY@^4-vLdQlI<}p|$5fx@?7Kl`cHG^mpSmYw-24Fb7vA8UwP10-Xwj$t z9o`uKg*UHQfaSbA`tTs5VgvAf%{7;x6 z$U{;Q2T&>RppL_J{cTy!+CPnMQoR>=*eobKZEf9^5aAlpM zjW;2@vNaYaC8%i;{mF#Q`X3Nl~KC}f_WM>2Cov#hleSm_Iz zTA6UaV^BAg!|=gDa`6+X&rew};>_bQZb@1mgN=@dBK6?4pFrLe_B!e2;muBZHasrd zkFy-MC$@dMKfjgqj}!R&tEjUdT*vj7Q=d~~`$~WI3pbtt6SmMq{p^MCWmCY8oc>Pf zyszn{>Mb{j^J%~xu{UMTA3cv8a~0=IUb7XlckMaX4H=BLs1hw37Fkf}F2fShA`5re zf))Aw59VmiezRF!IVsVnW}}U$#Cder{ky{=oSbYZ29jPP*VMvUnSxpm`T_^G!;Vvb zukeF7V9oa~6fw~nXdKqj9OlSnF}2!UmzKqBq6ONu1a0VRf5nK=D)5R(hqKs)b5G<} z-9KFnmCCKcenekH?{Rk>d;ymjJmKoKM>hT=TcjI~zP2|jfOSRnIAbbqi{*geI%G!8 zfYE3Dp{yH!V+}e;D~>6}W;9LUBPYvu7 zDp#1t^tii>6IHRKFFWzlux3*^lb`e~PD|aJVT#_!rY~B#AtrJN^D||LQ!+Ya8{sN? zl`5L*Tj*utM8f2elX-kN2><-+=yB>|-g^B4Q{?{+OtSw5lOjM4NdTE=e$ytm>6bW^ zS-2F+i*JKKB;CpjiVUlH8oV^pp*cmmvt4^)ljZ%U@Mjvq2V@9B0mmh7)rOIJCA_uOYF=l z2>JQw=RNMWC)sXySVT=j95VppyOD}BewWd7!SlP>ziJ;2uiJ)$F4!g-TS=>cvAtK% zY^m&s#?6t(S7HFEz z22k0U-#pC17!HMv6A;3ZY_PF!VI%b#7vEnV=Uy1{3KP7c_mxI|Xb1H=rJa#5P7zEV zLmt&efNC2Z{s}>-uMo=RC@3LQNFyVJoSaWAngMp;JPS9%ZEfo(Zzo)vEiKDMXOtx1 zDa)c1F3Hvd*c%B(y+*95!z$UORs~sItnjE_uIaXZnnn%qlNtcD2Vm< znXV zT7|ay>N-*bQ8&zJmM$i3QE3*c^irypAR<>NTb4dpddR+ZUYy{~IJ^`dH+W^GCa~s9G`-HyX+yes~D_@nhE_me1nq_wcq}POV>T!59j)%pAm$2 zbG=XQjX3CFx3IH{K6U-*w&g<*lwFsBX6PEqrW-=^CHZ^HgzG)kKhE9J*I&+^vA@e* z?nx7+yW^DAi7*KI(KXsn=jIwdP0M&flJrWI)j8SErJx<9PZ~sJM{LI$=92F!CuqbR zuSPA^*XIi|Mo>sq{kye_`KNVUjh^`UNf>}$1!D5>I9*9A#mG^xmUK=uNxZ-tqA@=> z!Bb!}_xEatg{0YiEf2jj|K!R5arBy4Q5bXVWLnj#7I6bH75{xTMl8JZ;WC_A8>e~- zw$h}&F?DsFBT@c=7_!oS;|laT5++82MGw6L0Anvh9#VA~h{R!r@t$^RqcOe#dOn~= zId!ZdfRiMB(Q0xg@eQ_4Owh8_C=X>0O-;{8jGg|hn8m|j<>zXUQQ@=YQE+);U?I#G zt=BGW0)iKjz^*~q6YhCmSp1Nr*))&%Jsdh@yI3~WLbP_VBA|%}baRPx5n*y}j3 zW)%o9s&xr_6Tub4nMavtE_#g;|6K)r#4Qu85y%jmh@jL6>82$pm$QCMQDd_~&t%~| z(~p|DR97}t-=dPDD3eRWdD?eeXG=b^ei>z3F-ZL|73)(>TD<0waMD0kNYP4~lcY)I zvI$w13rxw#2IhK!Fg7RsK|aX70^x|eT(QM4&YB4QTt-RJ1a3H_Y(2JCCgCrrnXl20 zWE7b`+HlGua|q5gO0ZpqM!E@#^APWL)DmZ>)-Gcmce)Q>nU~fmlg~*Y#*S$fST^VQ zoaRQBUF@01jWGjTcIjMca-mohcIM9L)-I{78N@bn&hB>Yt-`O7nekIQbX<*a0ge$^ zE@|1^pK-+wjIAh+2%?$f^|-W9bH4sm|1^dK@kgRWB30=&-V(w3!aerQ!tt18RV(p_ z4wcn5_l8nyH%Y6Bt2(;6;u}j-tg55XG9&gc#nh}@(mlk>2bSv?7Euv^z_!}Vt;Qm8 z)0ZF=u4)-Y-B-h;vdExRBfIWJK~i?HA-F@btC6vmiplH1L?F!KH@Ngu4<9=u8XY-Bm(QZ7}PCF9m`Ex9+%zIh7c z<-oD=Mqs;f#j!rvi?MWXOif2gO|}I=@j-BjU6~e~=>kO+RN1~p2L%C#6>hFmA1mU* zvohE2Mo}mP+Xuv{A%yJoKt3aHj}wO6E_&#CGll*^J#HeyCF1B4%*evhR6vz1Scdby z5Qc95vN3mn07kH#@Q`YOF?Vl0Z&u`WuNZy)Q)R^allstir);?mD+G#NavIYph?3s%1n>-Mj_I|OH&Tyfr z?e3*M$zt0lV4fPuBnT|5l19yCSY!J_wh5&aD#f^MO?8sI_1p#<`P!f~0u|pyNaFya zs#wd)@gqsdq0&wn>E_FmO70u-{kbWu@>hR0YA2aVA#&Gy0CBO`knVStg*^de>ievI;=KLtG zLE7#EaUBY_Y5w~1H_vNq%5@`X!mv+m1PUNLHj8Y`;{*^pMiF{397>zc^nF-w4uW%; z*8El($)sHy>_98*WUWQZ?2Q9tqIFKF%RGPU5RT%Kl6A+BaRs$zk5+MwjJtP|Y-1xg z-MTlHSo6;$^=Fq_iy=h1q!>lyr7{`yXI|gOu#f7ZE*<_k@)_zwLIAdve?z(Jg9o$V zwQiSr?IXUzOZbNOTJz|-;_>}Y(6@6Ql$Buab1(^5uh~F2B8TQO0l+7X% z%oDC_bcrgv)&2Ac{_G+6=8Tt8#ZZmF4aPYFz0CvdP?n;8(DtAK8z>C~6`zaCLshAz@5WDC**mTL0j zpLaLI+#efOZ&c&Y>mbi$Ci}XoQ$AAo-G49?KDApz4il&HJNWnsS3<##cL$t+WD{bt z!AxE7j|+xZY1l1K1T`P>syW{Tn_dGJ+yx!c4^Ip0C=-8xEXqy#-{tblx@%3D-x~U6 zpj!2|W_9KAXM%Z=Al`Aqw6-O6%u~~Ge?r$OCt#J ziFZr&L|H%|&bM2_!I7M{4!r0oXz{^s!J8>GDIq44^4Wq=<(8%D$@UX@*=!HmraP$M z5n5}Xw;@AJZOkhu&@;L!>TJ-o3hMA@N$f`y%p9L5+NUVp0M_8(bUm5*kOWC#|Iy3l@0{$fd`!{U#Ms{0#_->XS)#I~+!q((J#|SXLdvGU1zBRX&)7p{ML-}t z87Bg*B_4q%O%beczIIrlau4@}^#p;b`_t>6X`$ai=;5cTQi{5oY3{DS;nSP&=Hz(DD@_1 zRb(Niwa0&wL_-qoEwRTHQ|eimroWhB{X%H)e4vzZ+xM1;)Q#z zeLHZ{KJ#2*MhNVpOPPfZ&gRWmupd8LiVT?& zB%8(qE447u`Vgoz!4gf_o##=qc5iVm3QsOMvdT|_&J;S8t5g3}5uLUT#Dyhc6t%Iv zGqlPd3mbMFaUtpsLPAphh%rdHoW(>*whJV1TC)q<_0gD$$;n4&XIQX9eaF|}mIj4u zm8pvedqa;QhZM9b}T)sPF%2Mi1%_|QiztG@yWr1KK?B`iZb6# zEQof2D-vY(=ZAiPS;jby?;$J#r*I4R9a3!b@6WK`@x3bud)p37d@)ZE#P9e?yaLbs zF#6E*Op)k3EPffk!X*4M2#ZZl()z)TMYVRAb#fF6%NP)Q=`W|%W2ENAsd@|f7ce6k z(I&kDZa-3}kHGGDZOb_@zeT$UYuYyG3)Akhnv)s_^j*p7(=>-dgR0+NPe?~Zc}I_vH)k-#27Pyz-ebKyV3Lis*}n~ z$!M;=>Lj@TBG~f(yH0X)G`IR6)k!@6sp9(kO@dA)UjeCTZ0KfaW&EXA_9bNYufP7E z;;B&CQVCHX*;_~NaPP}2vR_M8`4@?LDut2uKoDUHP@&z+PQ`kd<=I@#j!}0J-c0bo zSW(f?wAU#bOQws6*qAvcz+`GyJNr1}ar6D=Y~1CW(g-^N{?uRsRI}Z1R1VHOZHrxW zI0hIuE#%fQMm_9PYnB6kk5gY1v5+oDvX1&>vMSSfcz7!#2P2mZ$-Jhn8m1IiHS!OJ z>N82Aa*3c^bm;m(_k7g&Gr9zrQsV(ulIKE&Wy8v%vO(DKv9JyzOG%=IO^RN4SJf%H zLsf@CD{}%}PsfN8u6t9dK`Zx@6-%ZCwt(qd=s)r-0QD&q^rNh7kZx10IZe+HBX;{N z-X`iqh8C!@Dr7A!OXQd(=GzsSUvr%O^S1g*Ye@!a1->{J#q$!V28uFzSDXeE+R`oRbH z?Yb(M?xJQ^HFT8V#1xk}JuCF1t`EMKW^AoVW?>j+1v#mlRt8m2mw8fkUA{@c5*vK; zC#1c7BqHAfI=XNjp?46KM=%r*Z3$yWBS64?5`Jn0?-8R@c(jG~t5|f}JAxCFh1Str zS3V%Uf%~L`3p$A(Ht$Ldoww0s1M)*>zrYkOE2VfrZaFa|Eb#M${MFE%52D>a?gHi- z^z`CNnt|R&k1jgWCYZ)o#Y&y6$MfrgM*}*a*kd9k{dU;4G@cJ8{N&<6AjDgA8tA)@ z-U%f-83k_9E~CIT`$a18&saYc)+~ff^wnS<&KCr$$7tMrlW3sZ8`#xHMBJCAB`UqC|!>GuYX%mTDhn4Kc( zenXcC_5kjS{ks3=Y}b6qn|Ho~lIXt#<+Gs4U+QH4_ve2UN`DPP|9?VB1@P}s(io5d zLRvUahpZ8%di8@Q$*?0d>&r-?wb)bzXeFBfk-dVxr_hG+78ebT7nOS}%yU$mDay|O z*2(C9_RMnlrNfEGhnrF z78eTZ1>E#;_xdcI*+{a7w0IjmiR3HgW1`rD`pGt>X3AnaL4IJbL%cjjO_NuTwpO>c_CDLyi%_t3v zDq4Ad-I~#S$zQj5Jr}}uBD(YQO_$V#R4~i-NsOaj{GwqjLe0lc%LWCk8Pl_BGEwiK zBK0OT!xqwz1J3%4Td0B_X*O;z|JGrKr zP7y{hoztV)dcm8WV<_1t7tga8NX=LD3YQ#V9ESEP@12gK8DoM3pv~C_(2Ujlk&9Fg zKxwZKl>6;A7Hly=QB9eJXQ~Ot2!{;5y*s9Ik|E1Ow;#dx`iCAwos2_K70u=lAbv`T z>KPn!B{nnFuiKpw^TW?>P6^ucvdQ8F(0ggVwSFRNC$MdUPy;4n9|qpCB3 z{p`TL`9_)elX5kn(;lvDJ02oQJq(vLhGZ0haqdtzw|EK28Sxju=!qiQZ+;zb+%M3Dm=Lc0r_pe~-TiYK+P$=zNH0Jn(YFgW zi7s?LlW-KfWBS+g_5lx#IVxq6P&|oc-GTClFx=J6E?9{nb^&HQ!)6?Y4O!T=8<;i` zAI$36!vfx1%7r_OFZTZ3f3t(C1S|S~Z5Al~V}Sifv#S5*uKE|VSE#bBgr$P~!MbW> zt_~?tn+BYuT1G%Y{GH~oIEH4y3{w*EnqZ1P{X#Lx28k@)ae(a;Wf;S20Yi&3>b8W* z>s0sPX>(H=(T@|xtMxdm{n2xqW4rV5yu90o3zR;16JE3ivyXfUnV41|Jv#_~sLju9 z*D8b#gTaiT?Qx)ng4HUNfN0|tl2<84<+?Rsd@WaJni&pu!u{mQQpqo^QgyP;u71nrmEr7m_Tc7W4Y;WP1KyPzP+(gV`bXTyX$tVW`l;R}WYE$}WfN&jmxHHQBU#(cLM42uxhO{ZOneEjt!10QLZDHzXF*B; zKkhz!(Gnq$?~!?)Yf!1dHbEn`F+pXTYZ`rT+7|X`2M~dUQ`YWJNjX%BFcchQ#VuPA z5E#UvF8Q*+3L})HM6D$z_)~-;j*cKKp;gT*Yoit=oll^@>-X@8w7SmeH!aMxGp`*g zlf1nLxJUE8^rL8eAu2Chw{g+0hCB(<=bTceOhjBk^Z5f%cX&5==*pwEsnLk8IeA4G zROx_%xSGA2#X>;~yi>4~F#~&wOb*#6?!>u_H5=X|i`k>w<$4GCIF8|fvBmU+Jw!wM z{bLy1D9SuaVy+N8V@Rf|1ot~{53)6S^R+(I2Nx-^fend{o*v5w)xnLU_YocRFcO{J z$@kp1Xz)SC99sh4puTsHkD;c%GeW2W`dYx&2$Acf;faiY70g#`4VRF+ zkci_ASx+>~x$$Rrqd`MT#?DW(+ z2k{97?Q8+jM(_w2Dc?$BEf5?*?uN=~MV|`S@%VZVNmk<(Qe(mtTKm1?i(&qR0IBj0z#{YtS+w`>Q^Yh2J3Vf6@cuzx zccW>%MXYZqHw`F+GJcQ9HhR9}_NCwFeMU1zi9L5S9&gZnFRm+Xs=K4bNmqw@p{)!_ z9`?rjo%oO=rP>-v#w5z^8}i%hSOK_`T2+v~dtI+7A>lVFLe)~x$abL&cV zI#&u!YbZhpNW6>qKW9qW=R$aES7%b$YiJ&yW$(*bU#ba44GnM_^^a?o)eqHYyw8in zR{&sJ9NM56zxF^Q!4N{MUpRhftCIHif|m&PEr??DSbYkfDou}&t#SulqzB%uAHOoZ z0jk^Zw>cr$@$%aPuZM>xuuW zDmHh;mlqU8sill9b8Jm?Y|E0^p$JSKk3#wCvTL7lRHga;!DSm4&pBn&-+%M<0f8<@ zLw|Hc-NvAA0y-^pRd{ZKTzLOv!bpse$3_;T)oPf4$WDzl^K@iYwJ!gdan%}9g@{RX z=~AMIqM(M*d!%J}Bz&lH0dVBHF}8+Wj$KEp6qGrh0$Dx|>4bZJlBXws7M@NKI3rG& zJZiS+*i_THNGk4AoLF~G3o7R@t^@j$Zg&pjlRvhl7fv3b480dFYEEjbb=(VjVTw=H55Pu8&z4g(&#?nImm^ zZ9Gw7PW7G9WRAH`d6&(^WMY9myf@GH&E&~eGiIJ+dc{c#If?VUG{U?MY(!^`kFMos+;#UlKxexHocFD5}1;IhV&$Ry?SJ&Y4Rl9Q7*3!!3JxLkOG zoxeou4xSh_XBv!OgD|1tS{zrlzp6_no115nh__YT?=&YeH$l3e9-e_HBN+{Z%JPo+7e5wF%J?zHV&)5m*;HKo>C=UO3(RW*!YTxP&=nQpKP=vqD5x`!q@ z%#BBuA)b!|-WFy|&WuxJiTmEdMe~3oo*H~70qaZ}Cz~1+G}kKKcivp^aVl9}4)DVs za^4^`Du&-GrCBD^x9W}5-}p5hTnl3j^hO_ncBA->tlt%*I-nNiLf;Y64W&BphR87x z0m&Y+Iyg3Ak@h}#Hmr$$t0x-7l_{cG_@3;^{2L$CKJ!$KRO3xSY}z^cM4^@C+BsJo zy{Q$|WJWbLHtZ?}70by}?hLk6t)!x8-ROkTTxz9En|zwOx{N4mdOGXys5vH6`uD+g z!6|#r1{RVzCe&&4lOl%FdHSthj?jK>^k#kfi0`DpDRBGTTQG)-BOWb1`c8*59q{s0 zn+!4aruMA4=|c^Dk!ow9XClT~EZkiE!m7!PeYMJC6Zdrn^>dcvk1#_)ucGc?f9{e zNR=3DYWwifdS->zoNC#vpW9IMhF+vTLOe`}-897AmA)>zm%He50@Q#Q22TWZNJxc; zxw2ZOR|H53os#5o@vL<`DONyB$%V=c_B|)9EY*dmxJqHNuk(H}h%D2TpjRbF;1s6v zxM{#H&AFx<4T*F0%%t^Gh7r-p+Rkrg96i&;sNPIKiEjqGjyo1CthqRlINEA@OpnVb z7i{K!b*7zzgMMqWnlsO=lZS&Ns9iL=Ehjcc2Fa_fr-sBd)h6kHugo7P#vN$ z;(Q9$ey3~%R$i7v2_j-t7sw}e6{oMfw+f)98<=xH77gF3Qoykk-;y`WjC0zW(pr?1ho7IKNTWy!g9 zRPs8>$N(oXjILLTEVadrI^M~VFBPmK-;v4Qvqi5=l((HhsL{ocq7J$Qkg(unL;q#7 zMeNjUc}+2_*NuK3Wf4zjs8rfo*qc8bjAqC#(tKzI%Q6ct0W@!sg!U9I!D3?mNS=PI zb9-gTc}3T^bY*a6s((-m)3P$fxq|37+5D^06rrimxW{wLeR=hki+OnW*0H%|#a;F=<=kwQQnn|#O)ME? zU^$8li>Qw9I_Sbx_pe2(32~WzY|N9jMV4jTS@LjF+M^m1TuYzJCJFwrwu^={Z@#2h zUYKW}D$MDcCfS+A_SSMnk&#NS)lX>beo#e!C9YQ8x0MBG_43 zPP$6ofu1L~cGQ0C6yA#2i!L>_3kkAc1Z!)>AT7Yr`>z)=0l#A@gA z8Mb43fuCZgAjpttQ6Dr4*G<93$?e?Bl}EvpZ^!E-FO4t`67S^|jf7@Hq_a3Gs1|Pt zI^Sg!S_3xhA$F-`TO(R>II-os#(@rx?|+8(JZaPC+tfR9=)GZ1q$1*X?`LkK0o}Co zzj5*ytms+O{Xq0C|2~2@1}ves(Yi4?!XcMj{4j^Tlx*;f#C1NMee0Pj-7$AcitW^0 zgn&U}xA_5V<{92RweE_$Y;&{ttkW~J^kegwyY#LW5A)PBf8A->p;w-H>3OIfGduVb z8EMce`{lqBNP(+N{8P~7W9;?~>-5Hjc^{8@#;5M?b8z`;+cTcegu=%U0Ey{@b~D09 z65nxgSc#?ncHzD@43OK4BCD&rZzm}yC{95-taDyPo{Lq~c}loasx#r#;5z71uH-~e zzpu>&7Qs-m8M=JALZceju88?;%Ltd_%tqzhP~jBFKfcc!^KeW(jy|rV;|W@jT6_?6!I zApKK{NAZs--e0uKU)-g`zjC`sRqHRiR21*6_qOzLm{tf4;C6l_{4{E2JZ6}LZzQWh zq|7ye0pCESY*^VwgC=cOI;A9@7Z{`Rq5^9zDx+9b^NF0vQ$sO~4L%kuGM8?rxu zen+d~nA``?XEJps=E>ru;TXe zaW)d}#2myD)nWbYgrf>5a=R%DIBGWp+?Du*Xk^Owql0Vs&=6;8u|2;ak^Cux=&1_} z{18CNK*KoKqBBCA8gS21ud%~h!<8CHdqU{JC?uMvJ`BlJK#Ix0Lev!T_5G#vJbDYXNCPF0cR z0K4@uz@WTs@>I;uEnmoe$P8g0HS zH{D@oNu#+WFaNs1V({;P?7A4__5wMYSPZP=NTVYMS#Lv^M(h2g6N}ZLUYyVbEuZeg zC1(BM5@*xf)qqwq3a9boa&9BoLt2?N{J<@I)S*zIOTmHPzsoQamx`s z>0SyLjRWQYgk5>_nwaI9AC?@-6+S}yNx^BjHd}2Mu}e)Wh8G^p8AJP!S+ll3zJ3>N zQIC-`mTiI14)@}Ef|j6f#YiBu(!dK|{lot} zT6Nq4`mkn~mxXZd1Sx=prEc|0LDG*fMS>~qfCXAXR(M_4)WmqAYNe9F*Uo>BV;tM0 z2Gdarpn$L0uq<+fST4H~9!tkX)$FG6*=tNWIAayd5s%^~V*)SQm&isXclfBd#nA&M z{fl(+JV|tMO1$!s;xU#PaOiESc9Q}csji8ds;Iu0;+<$hyz;cEKIqrTPZb3;cQ`_z3Key8fFD z;aRGnCv-v$;z}*@oLYE?fbpK9xF5kS3tl|jse=Ath7W; zo=QD$&`2}H-VBJ)vud<`ds~5DF3d(1IukbT12;s!`iEKUQ^+pYxZB6q&exb@@=g6l z&~D|n*NfxrFfE<%k=40?U7X0}pFoktgaRz6xws?x6+T*%3%fKRDf9-WO0!ebOE+u% zLy+}y7OCR-GSX9t+DG zGJM=CltE=qHYK&?bv#U=+N8B;sOy0_=%hYnXW;WCob=0?mX#tcls8P#7g}c1WZmm( zBJs&a^oV4;#>8Y^odGnaWU@Kf4zxsmcLM=ZE;n ze)Y&$44WuS;vt_Xql=M0ebbxQM07t2Q2>*mcLhTke!Uh>@ojM{Kd#{1Y-X$qqT8AH zZMZrY)!{IztkdLCr)%w$jY0PAyE3;l?tC&V5#-5dkzku(`HEjwULq0oPzj?_*D1Yn zM_F@j19^7(bFB3*R-ez#v&qcSRuLzC0A(3#pHCa+Wt7yPg%q2=c!wpzl}0V2v%egd zqh2%u4!kR*mc_?koU8ZxRYvn_49(Q)&DiP}%Io6jZh(1{#GZlDg`;mgIL1BN27Z11 z#EUqxxIrx0HIeQ8+5UMpplvq2wH+-pf9rL8sQqaF`OD$5jl*d8+G}b7kHgEacitV2 z%s%5w`wNN49giYUUpbk8MwM{deL5U06J^aowsE)PcmUJ^2yIZoTRO7`g&|ljGHJiW zUWGfzYL}arD7zneckj9KnVFYNx94b3%3Z-5Lk}V8x!fJ4CfveX#yjWTMLM$O8umuZ zTj@RR*6SI-bF-un39q`!MDx4As`dI=99C@!S?RF*R_pc9wTEad!5QceJo|{%%K#TDY4SE7=^udjaj;U$WI0c)Wg`aNN>^}7XA(FVlQ{UYhJagU!hNH z{46fd5)K0;IeJ1Ebq8+hp*88XNv0;;{*@J4I2P)id{f{@{~u!UfA7tS{_j_pv?=4i z*Ot?NTU^Roc33L#pQb({zVr zi}x*Ri-F11?MbT4+CjQW{fwP^8!~RZ z3Jy*f+6>%4put$|)HxAh#7B3TP6{}P{8nsn?A!sjX&4-R5@BP86Fxhed77}@Z#{(l zL)K>7h%iFVxw&o1-g_=Z@uxSsKYe_}uu%{3RxAK%G&?LDdy6PpGKgy9a1UTCPIwzs z)OM=EWsYR}6~jevFy=K!Vr;e5Xe^cj<)ZAYjIrQ2e&HmJ5O+Rdp8gi#S6I3WliohO z)4T<%d0SktoPqiGxg(O5J{I!F5q;%e8!$8*Oh+UG$pXX?GU#32c{qAjYzCO^4pZN; z{}>EqMS<-$tEvk#M9LQzMDa)C)az7$wZjtAj|R>#oF(pRF50!-N9vKG48mzaXS$iJ-Usi(;M7Oi(%ehL>?n@Wi)AE-9$mhzwJHbBL(Pc zQz;JXF@Ns4mgQ=^#e{&Txr>cYaJ9Bhzf+g--4nCv!47Czu zO7P9%cPfcy%KWio41c!@VfKq)4r9w0222gp7kd@G(kI`8nHrf#xhHYV*>iwZ@6aT( zAFV@jZPm-{dBv(ipA65aT@kI2e}zgLgcscknZJzHl!b{iw!YsR8ROaK4pBJ1p9ORP zWlfh<@))f-9qxk`lLuHx<_VvmZ?k_{UF!^`u=@t4;l!?abMYSCaBgXQ(uJ8IGu)H? zE55z3+bpfWW1Hz8TZ8=n`}mf%v;Ti1J4;bU4vPWar-4`lf?_LK5EytD9^P;eMcykH zgeDTGEc^$XnNeWS_dGP(-><*WWW>MTfqa3=UyaJAY*j&Kv7u7g9-VQr1kt&}YXs*Lha{v*Lx#lL3q%sdWo_9E*M1Q;^PpKEItx1|43LUv&GoW*kSbop zRytn}C#aff|4$g{){QM5w*Kj9olMF?RG#_77v1 z{04X82KhaN5BB-*Veg4AW97u}{T<{V_jl(1_5c4*s*s{)BZsYm&eI_6wrrxGT9rJ9 zT9~5Q7G+&#M`L3V0HUa7E>#qQ>YxtB*_uVr(9j%nQ}HTMzd%%D->+r(+j5{${ZHw3V&FKGDRJYWYV35Sl}9JL1?^dJ!5ZRU ziTS@5vw^DAry`JL4tud(=U^#D>BW@~x0NOe4K^3H9(iPDD-|mpO_f`JB?r&b0e&^+ zX&QTro&@a}E|P+VvznUocd{OP*@O8trmG)}rku?L%Hns3m}oMc$LNQYB}s_+C9w1M zp~TGhxLGOqafz|NIr{&WNVWi+-y)lpwBgpHf@+8RLIBtW@jNv( z=0$-{vx_)Kmm+J|B4n^?7qug;?hE#|lI(NsN!}siquXg-K)Qjvf@`c6hhmZCdykQt)LE- zC-&MRvDimr&%e=_Gib!uvma&&5kljr%uX!r8bD!!43>`icFjp>xgPH}oqrr(nW&ANQevWl zIu?}lW8+_j8MomAsjZ!JoacPzqmg;~Tg!pTV$Y`2v%D14q`0n7REYmUO&h zc>NOrc)1LdgUfO-(cAFDKH-ksCy68w&2VCnoc_4gojr8r;A1Zayd)jrM7##E!3exL zQfArtFOa*&7OVc51Qr;4mqVEbfmuV)oc{PLGm69or?FX%fEt+xI@?akJDrTFfO!mqeu9S_it3UBKV8@!=EMJaf4Ig)^WC)Rrq_v@0tOb5q7hiF_(I~QEoQS7NvNhNUnjJY^y6eQcheo|Y zH~NmE^tP(9bm0JcD*Jpou!fI7$igXSQ$+)n(4wkB>cKM*aYcTJJLo;V`kEKJ%88?? zb^F-VBtYj|SV8^|&RkjPK`9W6o z88sni@vt@B_;7}{J#j=G0Ixs6Qk%n^R%6HBc1EQ307K^C^h<43Ctv{77TTT zlys&Vq!)elBwhr)TSmK4aF|Hq%nTiA=pRx;cEv?Iib-7)Zdpu6TwD#^pT2Lv`WR

8N0%(^J`W)eJeY_C!xAfs+FdIb=Y*)7#S~XBFj6bO8@Appu zdzJvLS?Rbp$d_mWwS=TkU>n6zbG9RoQtf?n(F& zbij@&#(SN6h`{J9Zs=yd!Hvw7e%PAUYOF+BfT7OPM5HMep)Dy&izz$I2P6gic`guK`ad`i=6X%SQ_7$=+!mH>{@e7Fx7qOUx>0jJPj)^G9Dy1t?2j=b2L z?C~?ns~)|BOO!ml%X5c~PGV=KL3(7Xif+B~Z(322(0aC1@<~eAvCj|QXdw|eblZ_q zG$TXbTa-xgU*#|gjgkyRYgxy`D?m!JJ8y(+F!PuM(Cfrp5#%101t>%^xeDbk#L^*^ z#}`tWJ#ylB@XEY`H-7nd1ld^iPlj;S+ zcUzbe)VTv3L#q{U$vj8lk`YJuAp>iYzSVVwPqx6Q@uShp5K2ao3WXKtep~i5noH~d zx^ou)-G(}HmjI{(C^987$9&=BwUj{ki3pPq(n_<5`oj)6aEdOAfS_Zy#_-mt zjZ<1RtBe z$`{WI41!H=3#A1SkETHCtkL=_<@l0%*OX)A0rNPUde`VJ`#2Ic61ACn*Wj%UfJ`IX z&?EhTi+Z}&JM};VaHQTfeCq?itL2`)1sR9a@Ey1{0yI$5)xQTHlu+{-c|;tT0CF1M z0}oQEYic{jZm9rz4ey}`EPy2qU#x+x>Q0+yx_Y4x=N1qo~;=JfXd`pL(8`pWCZ>((p!$ePbejY*$;0On^fQ^Nd&n$&@ONQ*dF^Xm| z5ira;bPVTi&JvTWW!GRJ$!+4E4cYI8y1S&Zb53Ig9hJUVGuyUek6=Fk3q)}>N75^3 zBn5c>NSt)pEYgMRHFQFl9x5Dj;#mBR$l`vv>kr;$wbJCiO^;eJ19t4-JJj@jJ7Umb zZQiV9h?XXf+cJb$1b>RhPIL;WwEq)QXy-VSS<3|OfZbnbp8XV2vWE@42|O^KeZ90H6qh}M9%bgBm)?x_b4 zoU@2px-0HpI7SSiqb|uC59Xja%T1dwSU};$9ux$ghB-){FrW&=V8EoHiMEp~QA|4q zO9g3H43@zwTA}QK^LXbkPFs;rL#6wLpokQ?3N- zSTt)>4sT{Omp2PB`LBgPm`lC6I9Z%`)+2*H-#9Sm$Snat%b9b)r)5@5op;EQYuo_P zu6}9I8!b0i;>_7sMRd;rc+-eIWghY|T4x*b8UF2-X_BcI?X<;CcaP6gI1dR(x~H!W z((uJ65PqSm7QGX}%%^O0G3Lvbhx?1iTb)GD1NRco)KPsMWl8GFjy{6@m_F)MKmIsJ zL==0LF&c~DK}<6&_95!Mzc*p;nA?PV@y(iXX3EwqgZK)kJe!JFRr~shk~O4+(22wu z7MXWsaL8Sr`{E3mjS5y^0j(oJtf>|dX*8k{<~CuCJS}|S5~no#6GaY@YVceHxd8g7 z4BSviW7V@>V7AS3+&!$tS|5%oeU)#Zr13f;5a7_dny~#3lw~n$54v`!+nRp$P?%r< zZOZI;fGz_xbFAj^QU$T|N*Q&VGoZvp9)2 zi>V+%l$hp9&E`s)IY#8|;}@s>my7Rr+6#`RQ)o^iGvn%O>_uW=T6yKhc5WdQZs1i= z@~75x*eqn=i?Qf$hOqTjP}N09AE5DR^Wj@L8mkyV`zkGjkSQ(tGBd2GhllT4Y`;3_|AYU#Q)nj&%fWZ)B#1)qskO z>Ja~c19r&hyU#cYnwK7C3kUHDi0=Av+%I__Ml{nxJ`-hf-^ssKBE0p@k`_PMhBmo1 z+ukPfz=@Wl6S4h%8xLr=)UX0iPN*d5BE zIY6(4h(2OJU+w=^FG-)PkM*TnBk8}2$mJ(nb0+>$LI9CWFT z9Ulew3Iu#w3!n7l;1hVVMY=$m(3X)%k(sB!@I`H*fp*ZMr#nf2+S}g1!fP9N4eH?2 zxpzDEwv0n}1#hLMK=aCP2a2JX7&LXPQ`v7;KppvHchOIJ7>%`7Cd}3Vf4oxfGO`M3 zTbev$J^S2Y@BQmyaSXaEWQ#AyNISM{%rC2BRZsr&E4}3%PwnQ^WOJ+M%}aN)m9h2A zc$?4v`G`7@i#Mo-E@9`Z@2Y!xc4==+>s`^~&sPuNi_#{|H;PXjj>5(wep{14#gar) z>)fK*o1qVY#6;byt6Pf*t(vtLNOocna>qI{K3U{gCA!l=H=A12rz@<7aEF)Y1{oOI z9l<*HSQYj4?*u3&DZecn0thGt`=44gjQ^hrko>oQhRJ`+eo_Du&d4grp>`qhvTnGL zN&NgKlK2*(qQT){^o2?0hEnmtxw-m9Z$<5ivMQD3u>-&;*!H;gJ;30ZDH@?p+_=*Y zdxC7X>#YuZLorxvxM;XnRh|-LbTy^+j<;?L6<*zLTRtteojIRxk6u8nz_f$-zr^z8 z;il&noQS8BI{0r1N2Q4Ak~#!$DMzh{#UymeJc9OR5?jP$6FOvWe~q>iUnO9ZdF1T> zNQ9H%CFBseWf&zR&PntZz2z81Bi2jw7P(~^l}J<~E|HiL-nRZZWg(xvb^<)ih=fDV<-E4zS^#E}@eQT4SjsD*S?X*R2v{J(GM7qXkZ$Rs zpC7okY-S86tWZ!@9eFvg<$5uwpB}=91vObZ_p;pXJ<|}{M@x=x3u0f+8C$?w{xCc{ zzc{kk8iAG-S~J-x9+`@*vpPL3*;N>l(Nz37Wd(1s*QQnL;8VH5{3mPTEVkbvt84~) z5n^e`UxMsBX0b$|bORk>Zwx&)=c#n3(euU-S4~eu-fISBelun2MnESB1-RMzrKep=kSOxVBf3N!v!Ut*^E;Te@(g5=VnokQ8ay)rOssBl6g z$Ja+)Zr_E8su}H~xa1BH6j!n^D`{8-KIc6m5{wjJSE~p^CNa&F4Ll?-QlwOCW81c| z2sEq?038&>c(k?$lxJQ_J7=U!Ic;RKt7-(>ErF8_t{<$1rrAXIfO>C57T+KK(bcr9 zK^`l`5M=_-Qfk{HrTCeR5d$GsMra>fXwvrXUm@@=Dg14)9@Gbbf(PEnUZZwMnK)_A zc6Csy#rV5$C1Xi1#4YK-bavR$*o-E|_4Zl|^uf%gg*s&Rc>DtLgtl&Nyyj3(-7>fx zIQy=jw~shDtZZz|x9eySG0*%q?|eYLMicA$lGJqF$RG|YJ&6)0qSK@f>is7&8Z~Df z&~opv&k9S~L5Pi05U&VGqe*vuj?GVsg)s>F6E33OF?{Gzgac1!Kdbxm7%tp{6gA;X ze3=ES*ftKLz0LorR>RG`AFQS+!`A3ScfzQ$#h|~I&!5Jb($-g|ad$lpX8PGK2aL&L zt?V_D1)HS~Mp%T=tOs54Fxq>lc)V5O z9Ua%;njG8s`lpC}_#wNr6E~!sfnRsJT?JT_5MpWX7=A&%+{ztC{{MRrJ+ z_jhV*f7*7s!O6?EO38b=Mynpi4D%q~+5D6!NJsvZK#&cAFnhgx)}YA!DcfPI&5vRP ztiq2}9R_0l>nA`4%vM-m2m*c!1$dp1gxXP2)6j^&UR2?E2z0+od&&pt&|C}XlC^cC zf2SP_UPC#ylI3Rz4u5A1g9jE@@>=+$(1jksn;Ydv-Bm8i3!C)4nWNz&|IbHCbhjNp zirDi3KWqI{bJG!zm6~WUubkCxMO~ThIX}0Vca__Bz#JY|^>u1JgVI!J)CxH{#&WHQ zXc4;Us1-Woh$)8V#elZe-=~GMG@6EAltwFP$i~E(UwL& z#e|#!wzycVvL`rE$NHv=(^>SYllJl|yYLr5(p(6WL+~6}Dl|>ApiFi&_$M{VkIuZw zq2rJ(7YRA4$MdMU(@Hg##wxD_HQaj?8mg0)o`uMvrzMOk6K^Wdro}7qgf!gO6^EOi z8wXxFk`KTZmJm7gx`XSluS<0I=9Cc6mgG^h2^Jh^lAOM@zCWCAx#*bo;6)BC*BD6R zmuY3Zj0cQ&G`#KL&5ICaX6zE)#P~2h0}lt<^nk*6MrWcmsMN*@NU8tY%B$Np(5q#I zRGlzekl}6m2#WR_Mlgahgyg>P;Q66-I0aPO=&C;JKiu9MxC2Z@+r< z`PSvT^5NAbnhuR?`O1Ps*faSDj$Qt9C2zD4>o4gm!yFFIV5?M{lUsjkf~rlXpzR*1_1E=AN^tUtU6?Z5&qRylzAbW+S+NNS|W zzco^4U^L;M9M=>TU_r+104Hg5W@ma8xf zT9ew<+NBCq_O>fb(`U=St9xKMMr@(P@BuA4iH{e8400h}y0J*?kBL@h)~BXfBug-n zydtn&nLcFjiTdkfUZ5ZYbB?Ll-8L%~0egQyQ5vKPhCQa*2|%3-zY59_nW72E1OmV- zLdt#{Z7uip?8hJFBgT4&ut7vzubPL@W%g)h-xZ7FJJZH*RI1(6c=aXNSbMlcdzwHp zcSOLkbOeyXPMRYedt^x)rNXdm$nw~7-28c znjsrc}RiTNi+F86bg-~gNzEux>m*8}T?p~m2BnOigR98WC; z)#_J(&$^CiG((T>MmQ{Y;7p9m-{Ub(L%9BVyHPi8;6jgjEKFzS9)2vI$)cp?I9L3} zU-U@B*x+g1!Cz#E6F`-x-GYC@T#2+bv-#8Fz5<`UrE{{>qF2PkD|rGqzaW~>O!jsD zo=xZ8TjyT#o_gNH64zjobSvzz73vv2%rr!~W6fk6v?kJJFrx z0$yKvDY7empIwZY4}=}#1)&WUv2vh{2t{1j9+`dM zS4Szrwan!{kV}gHlWEKrJli7irw+3<2iq6p;(#W{2Cpn~ZL}u4bW2}EdoQyGr5jao zJ(Z-+xC_J;V+wJ?b~{q$kAV4eKMTP(BAd$(n#wGr+!5@sRgPs2hb*TPSpAk)E7F|m zAdPFOn_BZYE<6@d`wjH!H7RuVS1LL%wPYMQn-Bi>8!-;LYFBPAb};5N9Wb5D^8_la z_$AKaiII60av+O=ufncJ8cAMC@38ipTggRv&bq6uxo}pPoJXFiIy76E-U$R@h(1!% zd$9aDW4bs77s~k3uS&fKCNT?*M9;nIf`tJ`5X3VyFY(Cygd@NtswZW>%H>E2w??ZX zUBJ*UL_Fsb%t^U3sAs?oAP`Ov3^aAvg56*jED*l`i{P|R;nS|Tg+Mx?CalVSqDTN^mDzQN%f1^F`2tRv@b1lU$V0W2E- z={-T5%p!*Kpe@TD6(~fg^{e)eAAp7^bmFTlibT!}Ic5r7rI`%WM!1WO4mTQRx~476 z?vh+Mnq%z6h37J`_k=*+3ynPlnHV~XxnsS5WhM@l!#;xF^oIKH3jBYbU8VfT>RZ{w z-T6Oy690+JDh*iYe_82WvN5F@qbI^M2FF9nzd$1iGLOh5{1ifDPX8GUgqUnB4#vow zmdAtyx~fw8rJ|sALHYcn5p${NKujE-eiu)@NqJ-AQ@qL6ZLO*K(Qa+S$@S^4&*q!Y z-K6ozW9`xT&c5$c`&Q@G+vbta=2MrO``I*ED3Eq2pGPf_mlHkSTj9!;!JW*B4;A?I zwg%kmO=ibu74x*zo!cCC{NdW1x0ot+@?m@jE?^Tu<1r9i%t3kxjJtFo7krSNb~1|b zAQ+46;6RyGH}NPQi_S|va-Q)C#X{G`C@;E$bn>kJ5SDGqogTKN5F;_60k_qF~6 z8Xrg}ZG+^OHb#VK5@g4TmSTC~*PEH*O?hGjwQCleUz^CxB#T3ay*4sC?ty)ds-bKm zfe~Hm;(6|c98rr43+6=|z0ZYG&pX8BwbIx=6-oSH&fG$Wu*%v%RTf;@Tp+{V7&mWXNS+siX8 z3VzXHh*o_Om!X?9khbL0xauo7(IIWf>n3NXm{=weRJN}(vqYO%Hq(_+wisP=ATw&N z1c91UGJV{N)<*1eDTNUgl@7)6tW=0lE)kov1C;1efBs@D>E=HO?#ko^pS!ON#VD84 z12$8iR^4$X|22}zWg|5yW9bO65P8X(6&Dm<8cG5~159F%9?9lGa-f)M53((DOJ_6| z(yh-IB}@|@G5^`97k|1{j7+R#;3%XgeJJDoi*X72NFFVRIg2IjtVRoISKlSyT4G>j zW-diI0pz*|-rp>bcQG%$12`*VM2=uG*36G6L~97tY7QpUsej|V2{_%)>A^XVd6b}M z_YBfPi4?U@JMk9d7J#YGN8L7pu+$OdMhOcRYD%cCpnX4V*YCn`esS>1)VGmzjtbE< zAXq_&bu)t+i+pspP?t!~a4Dg0bdjQ;OW|PPLXde~*g%Vb{sjYLpw_=AOg++t%M@Zl zri6NszS}yuX2vv)W-kz@n=ip-E>OzeGyyyceeH?SE(cJ`e?WlYr);zAw_i{4ht| zD@dnVI}vp-cLs1Fu)g2bd}%{E>wKo*b=}M9Xhq_?%LkU~d^Ssapj$p4oJM#sq{?5H zEZ!O{)+6W7J{yhx3c0)WNJTS9c&vFAcK)1;3cE3(dkkOiOK3eGMD<>Yk?VX$@x2%% zBHUp(cidy5^9|bayy2>QczXUplO>0+^&uDp( z6qYKv_f0-rJdB7mj0swMa%FRDP%=zNdK6y=qf5>F3b9-c+m{^Sq!T{d!SBP|LQq`z zn8a6|S8e^wNA(v&WkStVC=RtWi$tTOLJB-538msC$YtU?`8VhY@3HX1umV&WOcFi$ zCxAXRt|aLe0$j)IPF)jCHpIgiB+a4gX%dsXYhFYQ5louLZ;glukvR%B8B`M_G+R+W zXjc~#b%Uy`l_5nBUMdrOv^^5@Wvn==S_r6xbF9*xx824kN@Q``xepT0E`m`pzOyQ_ z2FN45qBpg>I7sQInx-x`jkEMBH&V(E?doANrwbSLURRPWfW!JW6CFJSiamA^0y!Vp zut8^TicP@Z?&YCo6prPo7;n%DcE%~~&;|7$$D0q#8N*nM`ICsgRM?)XCfnrLW;>8D zJu7h(-cDHodYgr7$nwM6i4~1 zrNodTN;q?;{dOOy^o>Tz$vQ~or?5eo2F11+j;C`6yh(x6lbU#<%mV2aoYc(UvzfnY zq<@mi_+=D#2Vp$p`nbn3+|rKT;jX;~4`|C4fy zuwFqCf3k-+vxqmhh&Q_kXMX0f`buE)5l-(XjrTWE$2b zU#J;_p2(rVx266NGsS=Pe0-2~-s&NLZdrKK)W3|S6A~Ggle2iiSdLtv)mo z*X=NaV8;7_PFC~sK7PWkZJIc&H-ecVTr8wMr0&B?D?HiG`@jnrPh^Q;gyh65ejyUH(1w zCfmggsBFG_)jc>vK)`GqnoI%JK>yT-v$+7|#T~AsEHa$c6I@>n+B!|OE^${i?Mloj zFrS-({9K&3RlxX;oNVU}vE&lqnG1}ePUP4F%n9c%lT?9h(&;6Wcga_q@QU{ch%{#i z4b@Zy*^DEyAr#DhG<_|r{Ob;ms!@8D%qSodSUMs6uv#&`O21W*1*zWTe#24Gn#8nJ zRk>W{cg^B9=R)X$CC*|Q)@=3SUPbv2w=&q}BF;KFmz`Xwou6+dD(FXlO?4mgF*hq9 zcLbsZqn#&q^OPdk3uYoVoD&Q2(R{k2d*{T!Du;fp7aBR^Opj(%DZ6aCPO4_mRaD+@ zBk?h(cf*uO6CbH#Bmkum`hBy zvSlEP&*2N_r-VBdu6VV$aYC=kmP^X8YPTTkGL=}9f+1m8f=OaMH+N=%7HkN8yqV+( zcjRHFss#kuO#M3CPE?_|0M4e7-^zOo`s<4hdJ2Iwq3}#$osP-R51Uv^m#>*M1CU{D zS`*`kwe7!XoSd%bhp;fWsw&7Fa657LV@?Z}q@#DuYgpzW26JP0)Gm6X&s*1{-ubQM ziCw%|bPP*?Sj9@AiI3i8f4B8D$-D}F^q z@%`xZbP>Nfkx!m3DMU%yy6zzQ1LhC~Ao!HJxZ;Yjw{vj+krhztCSTGOSFzBpUbHEc z;hB^0X5?H3=RV34S5um^E&D)lse-p7@Swz<&)ZDI8cDbPYe)~!W6=LZzQY6^A$B3S zt56Yt%@q7ok!+81%9+K$eU@%8#;&^vf$^`;OC{_XC}dSEWvjz-5tL$&j&B&Qodcx2eL|) zuh@rEzL~PmXxj&lU1775Jo_AjZG!#)J9KH!(D6|ADNJt28(geip30?Ei}0t~T^52( zBO&h!Sce?go24+Ed`7=6$Q$yA5`MnoGb<1$V_ayghU4>Lbl|E?g;X0c9ZH&$^c8gI z7KLzbBW$P`!f3W3qjH64sDhs=L&97!sEiSV)T$FL%?zQbF@*|pTB0;v$5BFa>)P|$ zqbJpknbj4BMwHq^%)|%m$+t za9kMHt=D^#(&58dj$66U@D`40%6b1(Ej#>N-JI+n7`H%3s>UgQL{q*n8FljD6Gc;g z`DjdCTs-EQ#lC6orw$~>`$cs4GXm8JHcvas+6d>vhsYHD?BwW?`Nz@Pk!Q-mp0#JQ z5Egp^TVhyc#&rLvB;Di{Hy@nIGY@Cr7VOK%wB|d77)khA;m=am(aHSWL1T8Igokwd zExkF0X_L)Ou{US4V=cv&XKhpYR}ZG@YYru?l0xr48^sP51aTVZE%5$Y5}!E4U$Ti` zR=@SvLnVf?qG#Iams+u+VrmMeTG7U%-)1e(`!xHhNiC(NY%ZG^{Gz}~XncfzB!^ku zu&o9mslzm$Y1&X8p0p=LZQ(UMeK2&lR{EGZD(9R@y5gatzkQpa z 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

&R7;REBZd0NaNVcN6Eoy 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

?@Ib4$R$ZbA6MIsF(ZEk4Ii=sfRBa)&Yo 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�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 TY(h;@!?}i$7z!3V8^-w`q)kqw literal 0 HcmV?d00001 diff --git a/DepFiles/unittest/junit-4.8.2.jar b/DepFiles/unittest/junit-4.8.2.jar deleted file mode 100644 index 5b4bb849af9583fec1ea0a0ccc0d571ef49aa8ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 237344 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 + - - - + + diff --git a/pom.xml b/pom.xml index 01d43877..6738b3ae 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 1.2.1 + 2.0.0 jar Esri Geometry API for Java @@ -98,8 +98,7 @@ 1.6 - 20140107 - 1.9.13 + 2.6.5 4.12 @@ -110,14 +109,10 @@ - org.json - json - ${json.version} - - - org.codehaus.jackson - jackson-core-asl + com.fasterxml.jackson.core + jackson-core ${jackson.version} + false junit diff --git a/src/main/java/com/esri/core/geometry/GeometryEngine.java b/src/main/java/com/esri/core/geometry/GeometryEngine.java index 7bed73ea..1339538c 100644 --- a/src/main/java/com/esri/core/geometry/GeometryEngine.java +++ b/src/main/java/com/esri/core/geometry/GeometryEngine.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -29,9 +29,7 @@ import java.nio.ByteOrder; import java.util.ArrayList; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.json.JSONException; +import com.fasterxml.jackson.core.JsonParser; /** * Provides services that operate on geometry instances. The methods of GeometryEngine class call corresponding OperatorXXX classes. @@ -57,10 +55,27 @@ public class GeometryEngine { * spatial reference. */ public static MapGeometry jsonToGeometry(JsonParser json) { - MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); + MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, new JsonParserReader(json)); return geom; } + /** + * Imports the MapGeometry from its JSON representation. M and Z values are + * not imported from JSON representation. + * + * See OperatorImportFromJson. + * + * @param json + * The JSON representation of the geometry (with spatial + * reference). + * @return The MapGeometry instance containing the imported geometry and its + * spatial reference. + */ + public static MapGeometry jsonToGeometry(JsonReader json) { + MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); + return geom; + } + /** * Imports the MapGeometry from its JSON representation. M and Z values are * not imported from JSON representation. @@ -75,7 +90,7 @@ public static MapGeometry jsonToGeometry(JsonParser json) { * @throws IOException * @throws JsonParseException */ - public static MapGeometry jsonToGeometry(String json) throws JsonParseException, IOException { + public static MapGeometry jsonToGeometry(String json) { MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); return geom; } @@ -126,43 +141,60 @@ public static String geometryToGeoJson(Geometry geometry) { return exporter.execute(geometry); } - /** - * Exports the specified geometry instance to its GeoJSON representation. - * - *See OperatorExportToGeoJson. - * - * @see GeometryEngine#geometryToGeoJson(SpatialReference spatialReference, - * Geometry geometry) - * - * @param wkid - * The spatial reference Well Known ID to be used for the GeoJSON representation. - * @param geometry - * The geometry to be exported to GeoJSON. - * @return The GeoJSON representation of the specified geometry. - */ - public static String geometryToGeoJson(int wkid, Geometry geometry) { - return GeometryEngine.geometryToGeoJson( - wkid > 0 ? SpatialReference.create(wkid) : null, geometry); - } + /** + * Imports the MapGeometry from its JSON representation. M and Z values are + * not imported from JSON representation. + * + * See OperatorImportFromJson. + * + * @param json + * The JSON representation of the geometry (with spatial + * reference). + * @return The MapGeometry instance containing the imported geometry and its + * spatial reference. + * @throws IOException + * @throws JsonParseException + */ + public static MapGeometry geoJsonToGeometry(String json, int importFlags, Geometry.Type type) { + MapGeometry geom = OperatorImportFromGeoJson.local().execute(importFlags, type, json, null); + return geom; + } - /** - * Exports the specified geometry instance to it's JSON representation. - * - *See OperatorImportFromGeoJson. - * - * @param spatialReference - * The spatial reference of associated object. - * @param geometry - * The geometry. - * @return The GeoJSON representation of the specified geometry. - */ - public static String geometryToGeoJson(SpatialReference spatialReference, - Geometry geometry) { - OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory - .getOperator(Operator.Type.ExportToGeoJson); + /** + * Exports the specified geometry instance to its GeoJSON representation. + * + * See OperatorExportToGeoJson. + * + * @see GeometryEngine#geometryToGeoJson(SpatialReference spatialReference, + * Geometry geometry) + * + * @param wkid + * The spatial reference Well Known ID to be used for the GeoJSON + * representation. + * @param geometry + * The geometry to be exported to GeoJSON. + * @return The GeoJSON representation of the specified geometry. + */ + public static String geometryToGeoJson(int wkid, Geometry geometry) { + return GeometryEngine.geometryToGeoJson(wkid > 0 ? SpatialReference.create(wkid) : null, geometry); + } - return exporter.execute(spatialReference, geometry); - } + /** + * Exports the specified geometry instance to it's JSON representation. + * + * See OperatorImportFromGeoJson. + * + * @param spatialReference + * The spatial reference of associated object. + * @param geometry + * The geometry. + * @return The GeoJSON representation of the specified geometry. + */ + public static String geometryToGeoJson(SpatialReference spatialReference, Geometry geometry) { + OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory.getOperator(Operator.Type.ExportToGeoJson); + + return exporter.execute(spatialReference, geometry); + } /** * Imports geometry from the ESRI shape file format. @@ -230,26 +262,6 @@ public static Geometry geometryFromWkt(String wkt, int importFlags, return op.execute(importFlags, geometryType, wkt, null); } - /** - * Imports a geometry from a geoJson string. - * - * See OperatorImportFromGeoJson. - * - * @param geoJson The string containing the geometry in geoJson format. - * @param importFlags Use the {@link GeoJsonImportFlags} interface. - * @param geometryType The required type of the Geometry to be imported. Use Geometry.Type.Unknown if the geometry type needs to be determined from the geoJson context. - * @return The geometry. - * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the geoJson contains a geometry that cannot be converted to the given geometryType. - * @throws IllegalArgument exception if an error is found while parsing the geoJson string. - */ - @Deprecated - public static MapGeometry geometryFromGeoJson(String geoJson, - int importFlags, Geometry.Type geometryType) throws JSONException { - OperatorImportFromGeoJson op = (OperatorImportFromGeoJson) factory - .getOperator(Operator.Type.ImportFromGeoJson); - return op.execute(importFlags, geometryType, geoJson, null); - } - /** * Exports a geometry to a string in WKT format. * diff --git a/src/main/java/com/esri/core/geometry/JSONArrayEnumerator.java b/src/main/java/com/esri/core/geometry/JSONArrayEnumerator.java deleted file mode 100644 index 1350f623..00000000 --- a/src/main/java/com/esri/core/geometry/JSONArrayEnumerator.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - Copyright 1995-2015 Esri - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - - email: contracts@esri.com - */ -package com.esri.core.geometry; - -import java.util.ArrayList; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONArray; -import org.json.JSONObject; - -final class JSONArrayEnumerator { - - private JSONArray m_jsonArray; - private boolean m_bStarted; - private int m_currentIndex; - - JSONArrayEnumerator(JSONArray jsonArray) { - m_bStarted = false; - m_currentIndex = -1; - m_jsonArray = jsonArray; - } - - Object getCurrentObject() { - if (!m_bStarted) { - throw new GeometryException("invalid call"); - } - - if (m_currentIndex == m_jsonArray.length()) { - throw new GeometryException("invalid call"); - } - - return m_jsonArray.opt(m_currentIndex); - } - - boolean next() { - if (!m_bStarted) { - m_currentIndex = 0; - m_bStarted = true; - } else if (m_currentIndex != m_jsonArray.length()) { - m_currentIndex++; - } - - return m_currentIndex != m_jsonArray.length(); - } -} - diff --git a/src/main/java/com/esri/core/geometry/JSONObjectEnumerator.java b/src/main/java/com/esri/core/geometry/JSONObjectEnumerator.java deleted file mode 100644 index 2b4e25b4..00000000 --- a/src/main/java/com/esri/core/geometry/JSONObjectEnumerator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - Copyright 1995-2015 Esri - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - - email: contracts@esri.com - */ -package com.esri.core.geometry; - -import org.json.JSONObject; - -import java.util.Iterator; - -final class JSONObjectEnumerator { - - private JSONObject m_jsonObject; - private int m_troolean; - private Iterator m_keys_iter; - private String m_current_key; - - JSONObjectEnumerator(JSONObject jsonObject) { - m_troolean = 0; - m_jsonObject = jsonObject; - } - - String getCurrentKey() { - if (m_troolean != 1) { - throw new GeometryException("invalid call"); - } - - return m_current_key; - } - - Object getCurrentObject() { - if (m_troolean != 1) { - throw new GeometryException("invalid call"); - } - - return m_jsonObject.opt(m_current_key); - } - - boolean next() { - if (m_troolean == 0) { - if (m_jsonObject.length() > 0) { - m_keys_iter = m_jsonObject.keys(); - m_troolean = 1;//started - } - else { - m_troolean = -1;//stopped - } - } - - if (m_troolean == 1) {//still exploring - if (m_keys_iter.hasNext()) { - m_current_key = (String)m_keys_iter.next(); - } - else { - m_troolean = -1; //done - } - } - - return m_troolean == 1; - } -} diff --git a/src/main/java/com/esri/core/geometry/JSONUtils.java b/src/main/java/com/esri/core/geometry/JSONUtils.java index 71feb32a..14bcf142 100644 --- a/src/main/java/com/esri/core/geometry/JSONUtils.java +++ b/src/main/java/com/esri/core/geometry/JSONUtils.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,26 +23,21 @@ */ package com.esri.core.geometry; -import java.io.IOException; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonToken; - final class JSONUtils { static boolean isObjectStart(JsonReader parser) throws Exception { - return parser.currentToken() == null ? parser.nextToken() == JsonToken.START_OBJECT - : parser.currentToken() == JsonToken.START_OBJECT; + return parser.currentToken() == null ? parser.nextToken() == JsonReader.Token.START_OBJECT + : parser.currentToken() == JsonReader.Token.START_OBJECT; } - static double readDouble(JsonReader parser) throws JsonParseException, - IOException, Exception { - if (parser.currentToken() == JsonToken.VALUE_NUMBER_FLOAT) + static double readDouble(JsonReader parser) { + if (parser.currentToken() == JsonReader.Token.VALUE_NUMBER_FLOAT) return parser.currentDoubleValue(); - else if (parser.currentToken() == JsonToken.VALUE_NUMBER_INT) + else if (parser.currentToken() == JsonReader.Token.VALUE_NUMBER_INT) return parser.currentIntValue(); - else if (parser.currentToken() == JsonToken.VALUE_NULL) + else if (parser.currentToken() == JsonReader.Token.VALUE_NULL) return NumberUtils.NaN(); - else if (parser.currentToken() == JsonToken.VALUE_STRING) + else if (parser.currentToken() == JsonReader.Token.VALUE_STRING) if (parser.currentString().equals("NaN")) return NumberUtils.NaN(); diff --git a/src/main/java/com/esri/core/geometry/JsonGeometryException.java b/src/main/java/com/esri/core/geometry/JsonGeometryException.java index a5552901..7402e0de 100644 --- a/src/main/java/com/esri/core/geometry/JsonGeometryException.java +++ b/src/main/java/com/esri/core/geometry/JsonGeometryException.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,13 +21,15 @@ email: contracts@esri.com */ + package com.esri.core.geometry; /** * A runtime exception raised when a JSON related exception occurs. */ public class JsonGeometryException extends GeometryException { - + private static final long serialVersionUID = 1L; + /** * Constructs a Json Geometry Exception with the given error string/message. * @@ -37,4 +39,16 @@ public class JsonGeometryException extends GeometryException { public JsonGeometryException(String str) { super(str); } + + /** + * Constructs a Json Geometry Exception with the given another exception. + * + * @param ex + * - The exception to copy the message from. + */ + public JsonGeometryException(Exception ex) { + super(ex.getMessage()); + } + } + diff --git a/src/main/java/com/esri/core/geometry/JsonParserReader.java b/src/main/java/com/esri/core/geometry/JsonParserReader.java index bf382dd9..90427c63 100644 --- a/src/main/java/com/esri/core/geometry/JsonParserReader.java +++ b/src/main/java/com/esri/core/geometry/JsonParserReader.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,56 +21,151 @@ email: contracts@esri.com */ -package com.esri.core.geometry; - -import java.util.ArrayList; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONException; -import org.codehaus.jackson.JsonParseException; +package com.esri.core.geometry; -import java.io.IOException; +import com.fasterxml.jackson.core.*; -final class JsonParserReader extends JsonReader { +/** + * A throw in JsonReader built around the Jackson JsonParser. + * + */ +public class JsonParserReader implements JsonReader { private JsonParser m_jsonParser; - JsonParserReader(JsonParser jsonParser) { + public JsonParserReader(JsonParser jsonParser) { m_jsonParser = jsonParser; } + + /** + * Creates a JsonReader for the string. + * The nextToken is called by this method. + */ + public static JsonReader createFromString(String str) { + try { + JsonFactory factory = new JsonFactory(); + JsonParser jsonParser = factory.createParser(str); + + jsonParser.nextToken(); + return new JsonParserReader(jsonParser); + } + catch (Exception ex) { + throw new JsonGeometryException(ex.getMessage()); + } + } + + /** + * Creates a JsonReader for the string. + * The nextToken is not called by this method. + */ + public static JsonReader createFromStringNNT(String str) { + try { + JsonFactory factory = new JsonFactory(); + JsonParser jsonParser = factory.createParser(str); + + return new JsonParserReader(jsonParser); + } + catch (Exception ex) { + throw new JsonGeometryException(ex.getMessage()); + } + } + + private static Token mapToken(JsonToken token) { + if (token == JsonToken.END_ARRAY) + return Token.END_ARRAY; + if (token == JsonToken.END_OBJECT) + return Token.END_OBJECT; + if (token == JsonToken.FIELD_NAME) + return Token.FIELD_NAME; + if (token == JsonToken.START_ARRAY) + return Token.START_ARRAY; + if (token == JsonToken.START_OBJECT) + return Token.START_OBJECT; + if (token == JsonToken.VALUE_FALSE) + return Token.VALUE_FALSE; + if (token == JsonToken.VALUE_NULL) + return Token.VALUE_NULL; + if (token == JsonToken.VALUE_NUMBER_FLOAT) + return Token.VALUE_NUMBER_FLOAT; + if (token == JsonToken.VALUE_NUMBER_INT) + return Token.VALUE_NUMBER_INT; + if (token == JsonToken.VALUE_STRING) + return Token.VALUE_STRING; + if (token == JsonToken.VALUE_TRUE) + return Token.VALUE_TRUE; + if (token == null) + return null; + + throw new JsonGeometryException("unexpected token"); + } @Override - JsonToken nextToken() throws JSONException, JsonParseException, IOException { - JsonToken token = m_jsonParser.nextToken(); - return token; + public Token nextToken() throws JsonGeometryException { + try { + JsonToken token = m_jsonParser.nextToken(); + return mapToken(token); + } catch (Exception ex) { + throw new JsonGeometryException(ex); + } } @Override - JsonToken currentToken() throws JSONException, JsonParseException, IOException { - return m_jsonParser.getCurrentToken(); + public Token currentToken() throws JsonGeometryException { + try { + return mapToken(m_jsonParser.getCurrentToken()); + } catch (Exception ex) { + throw new JsonGeometryException(ex); + } } @Override - void skipChildren() throws JSONException, JsonParseException, IOException { - m_jsonParser.skipChildren(); + public void skipChildren() throws JsonGeometryException { + try { + m_jsonParser.skipChildren(); + } catch (Exception ex) { + throw new JsonGeometryException(ex); + } + } @Override - String currentString() throws JSONException, JsonParseException, IOException { - return m_jsonParser.getText(); + public String currentString() throws JsonGeometryException { + try { + return m_jsonParser.getText(); + } catch (Exception ex) { + throw new JsonGeometryException(ex); + } + } @Override - double currentDoubleValue() throws JSONException, JsonParseException, IOException { - return m_jsonParser.getValueAsDouble(); + public double currentDoubleValue() throws JsonGeometryException { + try { + return m_jsonParser.getValueAsDouble(); + } catch (Exception ex) { + throw new JsonGeometryException(ex); + } + } @Override - int currentIntValue() throws JSONException, JsonParseException, IOException { - return m_jsonParser.getValueAsInt(); + public int currentIntValue() throws JsonGeometryException { + try { + return m_jsonParser.getValueAsInt(); + } catch (Exception ex) { + throw new JsonGeometryException(ex); + } + } + + @Override + public boolean currentBooleanValue() { + Token t = currentToken(); + if (t == Token.VALUE_TRUE) + return true; + else if (t == Token.VALUE_FALSE) + return false; + throw new JsonGeometryException("Not a boolean"); } } diff --git a/src/main/java/com/esri/core/geometry/JsonReader.java b/src/main/java/com/esri/core/geometry/JsonReader.java index b1f69d95..541143e3 100644 --- a/src/main/java/com/esri/core/geometry/JsonReader.java +++ b/src/main/java/com/esri/core/geometry/JsonReader.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,29 +23,38 @@ */ package com.esri.core.geometry; -import java.util.ArrayList; - -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONException; -import org.codehaus.jackson.JsonParseException; - -import java.io.IOException; - -abstract class JsonReader { - - abstract JsonToken nextToken() throws JSONException, JsonParseException, IOException; - - abstract JsonToken currentToken() throws JSONException, JsonParseException, IOException; - - abstract void skipChildren() throws JSONException, JsonParseException, IOException; - - abstract String currentString() throws JSONException, JsonParseException, IOException; - - abstract double currentDoubleValue() throws JSONException, JsonParseException, IOException; - - abstract int currentIntValue() throws JSONException, JsonParseException, IOException; +/** + * An abstract reader for Json. + * + * See JsonParserReader for a concrete implementation around JsonParser. + */ +abstract public interface JsonReader { + public static enum Token { + END_ARRAY, + END_OBJECT, + FIELD_NAME, + START_ARRAY, + START_OBJECT, + VALUE_FALSE, + VALUE_NULL, + VALUE_NUMBER_FLOAT, + VALUE_NUMBER_INT, + VALUE_STRING, + VALUE_TRUE + } + + abstract public Token nextToken() throws JsonGeometryException; + + abstract public Token currentToken() throws JsonGeometryException; + + abstract public void skipChildren() throws JsonGeometryException; + + abstract public String currentString() throws JsonGeometryException; + + abstract public double currentDoubleValue() throws JsonGeometryException; + + abstract public int currentIntValue() throws JsonGeometryException; + + abstract public boolean currentBooleanValue() throws JsonGeometryException; } diff --git a/src/main/java/com/esri/core/geometry/JsonParserCursor.java b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java similarity index 68% rename from src/main/java/com/esri/core/geometry/JsonParserCursor.java rename to src/main/java/com/esri/core/geometry/JsonReaderCursor.java index 1a1f14f3..94f72a30 100644 --- a/src/main/java/com/esri/core/geometry/JsonParserCursor.java +++ b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,20 +21,34 @@ email: contracts@esri.com */ -package com.esri.core.geometry; +/* + COPYRIGHT 1995-2017 ESRI -import org.codehaus.jackson.JsonParser; + TRADE SECRETS: ESRI PROPRIETARY AND CONFIDENTIAL + Unpublished material - all rights reserved under the + Copyright Laws of the United States. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + +package com.esri.core.geometry; /** - * An abstract JsonParser Cursor class. + * An abstract JsonReader Cursor class. */ -abstract class JsonParserCursor { +abstract class JsonReaderCursor { /** - * Moves the cursor to the next JsonParser. Returns null when reached the + * Moves the cursor to the next JsonReader. Returns null when reached the * end. */ - public abstract JsonParser next(); + public abstract JsonReader next(); /** * Returns the ID of the current geometry. The ID is propagated across the diff --git a/src/main/java/com/esri/core/geometry/JsonValueReader.java b/src/main/java/com/esri/core/geometry/JsonValueReader.java deleted file mode 100644 index 91028624..00000000 --- a/src/main/java/com/esri/core/geometry/JsonValueReader.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - Copyright 1995-2015 Esri - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - - email: contracts@esri.com - */ -package com.esri.core.geometry; - -import java.util.ArrayList; - -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONException; -import org.codehaus.jackson.JsonParseException; - -import java.io.IOException; - - -final class JsonValueReader extends JsonReader { - - private Object m_object; - private JsonToken m_currentToken; - private ArrayList m_parentStack; - private ArrayList m_objIters; - private ArrayList m_arrIters; - - JsonValueReader(Object object) { - m_object = object; - - boolean bJSONObject = (m_object instanceof JSONObject); - boolean bJSONArray = (m_object instanceof JSONArray); - - if (!bJSONObject && !bJSONArray) { - throw new IllegalArgumentException(); - } - - m_parentStack = new ArrayList(0); - m_objIters = new ArrayList(0); - m_arrIters = new ArrayList(0); - - m_parentStack.ensureCapacity(4); - m_objIters.ensureCapacity(4); - m_arrIters.ensureCapacity(4); - - if (bJSONObject) { - JSONObjectEnumerator objIter = new JSONObjectEnumerator((JSONObject) m_object); - m_parentStack.add(JsonToken.START_OBJECT); - m_objIters.add(objIter); - m_currentToken = JsonToken.START_OBJECT; - } else { - JSONArrayEnumerator arrIter = new JSONArrayEnumerator((JSONArray) m_object); - m_parentStack.add(JsonToken.START_ARRAY); - m_arrIters.add(arrIter); - m_currentToken = JsonToken.START_ARRAY; - } - } - - private void setCurrentToken_(Object obj) { - if (obj instanceof String) { - m_currentToken = JsonToken.VALUE_STRING; - } else if (obj instanceof Double || obj instanceof Float) { - m_currentToken = JsonToken.VALUE_NUMBER_FLOAT; - } else if (obj instanceof Integer || obj instanceof Long || obj instanceof Short) { - m_currentToken = JsonToken.VALUE_NUMBER_INT; - } else if (obj instanceof Boolean) { - Boolean bObj = (Boolean) obj; - boolean b = bObj.booleanValue(); - if (b) { - m_currentToken = JsonToken.VALUE_TRUE; - } else { - m_currentToken = JsonToken.VALUE_FALSE; - } - } else if (obj instanceof JSONObject) { - m_currentToken = JsonToken.START_OBJECT; - } else if (obj instanceof JSONArray) { - m_currentToken = JsonToken.START_ARRAY; - } else { - m_currentToken = JsonToken.VALUE_NULL; - } - } - - Object currentObject_() { - assert (!m_parentStack.isEmpty()); - - JsonToken parentType = m_parentStack.get(m_parentStack.size() - 1); - - if (parentType == JsonToken.START_OBJECT) { - JSONObjectEnumerator objIter = m_objIters.get(m_objIters.size() - 1); - return objIter.getCurrentObject(); - } - - JSONArrayEnumerator arrIter = m_arrIters.get(m_arrIters.size() - 1); - return arrIter.getCurrentObject(); - } - - @Override - JsonToken nextToken() throws JSONException, JsonParseException { - if (m_parentStack.isEmpty()) { - m_currentToken = JsonToken.NOT_AVAILABLE; - return m_currentToken; - } - - JsonToken parentType = m_parentStack.get(m_parentStack.size() - 1); - - if (parentType == JsonToken.START_OBJECT) { - JSONObjectEnumerator iterator = m_objIters.get(m_objIters.size() - 1); - - if (m_currentToken == JsonToken.FIELD_NAME) { - Object nextJSONValue = iterator.getCurrentObject(); - - if (nextJSONValue instanceof JSONObject) { - m_parentStack.add(JsonToken.START_OBJECT); - m_objIters.add(new JSONObjectEnumerator((JSONObject) nextJSONValue)); - m_currentToken = JsonToken.START_OBJECT; - } else if (nextJSONValue instanceof JSONArray) { - m_parentStack.add(JsonToken.START_ARRAY); - m_arrIters.add(new JSONArrayEnumerator((JSONArray) nextJSONValue)); - m_currentToken = JsonToken.START_ARRAY; - } else { - setCurrentToken_(nextJSONValue); - } - } else { - if (iterator.next()) { - m_currentToken = JsonToken.FIELD_NAME; - } else { - m_objIters.remove(m_objIters.size() - 1); - m_parentStack.remove(m_parentStack.size() - 1); - m_currentToken = JsonToken.END_OBJECT; - } - } - } else { - assert (parentType == JsonToken.START_ARRAY); - JSONArrayEnumerator iterator = m_arrIters.get(m_arrIters.size() - 1); - if (iterator.next()) { - Object nextJSONValue = iterator.getCurrentObject(); - - if (nextJSONValue instanceof JSONObject) { - m_parentStack.add(JsonToken.START_OBJECT); - m_objIters.add(new JSONObjectEnumerator((JSONObject) nextJSONValue)); - m_currentToken = JsonToken.START_OBJECT; - } else if (nextJSONValue instanceof JSONArray) { - m_parentStack.add(JsonToken.START_ARRAY); - m_arrIters.add(new JSONArrayEnumerator((JSONArray) nextJSONValue)); - m_currentToken = JsonToken.START_ARRAY; - } else { - setCurrentToken_(nextJSONValue); - } - } else { - m_arrIters.remove(m_arrIters.size() - 1); - m_parentStack.remove(m_parentStack.size() - 1); - m_currentToken = JsonToken.END_ARRAY; - } - } - - return m_currentToken; - } - - @Override - JsonToken currentToken() throws JSONException, JsonParseException, IOException { - return m_currentToken; - } - - @Override - void skipChildren() throws JSONException, JsonParseException, IOException { - assert (!m_parentStack.isEmpty()); - - if (m_currentToken != JsonToken.START_OBJECT && m_currentToken != JsonToken.START_ARRAY) { - return; - } - - JsonToken parentType = m_parentStack.get(m_parentStack.size() - 1); - - if (parentType == JsonToken.START_OBJECT) { - m_objIters.remove(m_objIters.size() - 1); - m_parentStack.remove(m_parentStack.size() - 1); - m_currentToken = JsonToken.END_OBJECT; - } else { - m_arrIters.remove(m_arrIters.size() - 1); - m_parentStack.remove(m_parentStack.size() - 1); - m_currentToken = JsonToken.END_ARRAY; - } - } - - @Override - String currentString() throws JSONException, JsonParseException, IOException { - if (m_currentToken == JsonToken.FIELD_NAME) { - return m_objIters.get(m_objIters.size() - 1).getCurrentKey(); - } - - if (m_currentToken != JsonToken.VALUE_STRING) { - throw new GeometryException("invalid call"); - } - - return ((String) currentObject_()).toString(); - } - - @Override - double currentDoubleValue() throws JSONException, JsonParseException, IOException { - if (m_currentToken != JsonToken.VALUE_NUMBER_FLOAT && m_currentToken != JsonToken.VALUE_NUMBER_INT) { - throw new GeometryException("invalid call"); - } - - return ((Number) currentObject_()).doubleValue(); - } - - @Override - int currentIntValue() throws JSONException, JsonParseException, IOException { - if (m_currentToken != JsonToken.VALUE_NUMBER_INT) { - throw new GeometryException("invalid call"); - } - - return ((Number) currentObject_()).intValue(); - } -} diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java index f6d606bb..dce85615 100644 --- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java @@ -25,7 +25,7 @@ package com.esri.core.geometry; -import java.util.ArrayList; +import com.esri.core.geometry.MultiVertexGeometryImpl.DirtyFlags; final class MultiPathImpl extends MultiVertexGeometryImpl { @@ -2561,30 +2561,34 @@ public boolean _buildQuadTreeAccelerator(GeometryAccelerationDegree d) { return true; } - boolean _buildQuadTreeForPathsAccelerator(GeometryAccelerationDegree degree) { - if (m_accelerators == null) { - m_accelerators = new GeometryAccelerators(); - } + boolean _buildQuadTreeForPathsAccelerator(GeometryAccelerationDegree degree) { + if (m_accelerators == null) { + m_accelerators = new GeometryAccelerators(); + } - //TODO: when less than two envelopes - no need to this. + // TODO: when less than two envelopes - no need to this. - if (m_accelerators.getQuadTreeForPaths() != null) - return true; + if (m_accelerators.getQuadTreeForPaths() != null) + return true; - m_accelerators._setQuadTreeForPaths(null); - QuadTreeImpl quad_tree_impl = InternalUtils.buildQuadTreeForPaths(this); - m_accelerators._setQuadTreeForPaths(quad_tree_impl); + m_accelerators._setQuadTreeForPaths(null); + QuadTreeImpl quad_tree_impl = InternalUtils.buildQuadTreeForPaths(this); + m_accelerators._setQuadTreeForPaths(quad_tree_impl); - return true; - } + return true; + } - void setFillRule(int rule) { - assert(m_bPolygon); - m_fill_rule = rule; - } - int getFillRule() { - return m_fill_rule; - } + void setFillRule(int rule) { + assert (m_bPolygon); + m_fill_rule = rule; + } + int getFillRule() { + return m_fill_rule; + } + void clearDirtyOGCFlags() { + _setDirtyFlag(DirtyFlags.DirtyOGCFlags, false); + } } + diff --git a/src/main/java/com/esri/core/geometry/Operator.java b/src/main/java/com/esri/core/geometry/Operator.java index ffceb73f..9dcd804d 100644 --- a/src/main/java/com/esri/core/geometry/Operator.java +++ b/src/main/java/com/esri/core/geometry/Operator.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -36,7 +36,6 @@ public enum Type { Project, ExportToJson, ImportFromJson, - @Deprecated ImportMapGeometryFromJson, ExportToESRIShape, ImportFromESRIShape, Union, Difference, diff --git a/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java b/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java index 160bcffd..727b4a69 100644 --- a/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -38,10 +38,6 @@ import java.nio.channels.FileChannel; import java.util.HashMap; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; - /** *An abstract class that represent the basic OperatorFactory interface. */ @@ -58,8 +54,6 @@ public class OperatorFactoryLocal extends OperatorFactory { new OperatorExportToJsonLocal()); st_supportedOperators.put(Type.ImportFromJson, new OperatorImportFromJsonLocal()); - st_supportedOperators.put(Type.ImportMapGeometryFromJson, - new OperatorImportFromJsonLocal()); st_supportedOperators.put(Type.ExportToESRIShape, new OperatorExportToESRIShapeLocal()); st_supportedOperators.put(Type.ImportFromESRIShape, @@ -202,14 +196,7 @@ public static MapGeometry loadGeometryFromJSONFileDbg(String file_name) { } catch (Exception ex) { } - JsonFactory jf = new JsonFactory(); - JsonParser jp = null; - try { - jp = jf.createJsonParser(jsonString); - jp.nextToken(); - } catch (Exception ex) { - } - MapGeometry mapGeom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jp); + MapGeometry mapGeom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jsonString); return mapGeom; } diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java index 88cb4653..87de2d4a 100644 --- a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java +++ b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,11 +23,6 @@ */ package com.esri.core.geometry; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; - public abstract class OperatorImportFromGeoJson extends Operator { @Override @@ -43,7 +38,7 @@ public Type getType() { * @return Returns the imported MapGeometry. * @throws JsonGeometryException */ - public abstract MapGeometry execute(int importFlags, Geometry.Type type, JSONObject jsonObject, ProgressTracker progressTracker) throws JSONException; + public abstract MapGeometry execute(int importFlags, Geometry.Type type, JsonReader jsonReader, ProgressTracker progressTracker); /** * Deprecated, use version without import_flags. @@ -57,7 +52,7 @@ public Type getType() { * @throws JSONException * */ - public abstract MapGeometry execute(int import_flags, Geometry.Type type, String geoJsonString, ProgressTracker progress_tracker) throws JSONException; + public abstract MapGeometry execute(int import_flags, Geometry.Type type, String geoJsonString, ProgressTracker progress_tracker); /** * @@ -68,7 +63,7 @@ public Type getType() { * @return Returns the imported MapOGCStructure. * @throws JSONException */ - public abstract MapOGCStructure executeOGC(int import_flags, String geoJsonString, ProgressTracker progress_tracker) throws JSONException; + public abstract MapOGCStructure executeOGC(int import_flags, String geoJsonString, ProgressTracker progress_tracker); public static OperatorImportFromGeoJson local() { return (OperatorImportFromGeoJson) OperatorFactoryLocal.getInstance().getOperator(Type.ImportFromGeoJson); diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java index e04952a4..78e9c8b1 100644 --- a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java @@ -24,57 +24,48 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Semantics; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.IOException; import java.util.ArrayList; class OperatorImportFromGeoJsonLocal extends OperatorImportFromGeoJson { + static enum GeoJsonType { + Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection; + static GeoJsonType fromGeoJsonValue(int v) { + return GeoJsonType.values()[v - 1]; + } + + public int geogsjonvalue() { + return ordinal() + 1; + } + }; + + static interface GeoJsonValues { + public final static int Point = GeoJsonType.Point.geogsjonvalue(); + public final static int LineString = GeoJsonType.LineString.geogsjonvalue(); + public final static int Polygon = GeoJsonType.Polygon.geogsjonvalue(); + public final static int MultiPoint = GeoJsonType.MultiPoint.geogsjonvalue(); + public final static int MultiLineString = GeoJsonType.MultiLineString.geogsjonvalue(); + public final static int MultiPolygon = GeoJsonType.MultiPolygon.geogsjonvalue(); + public final static int GeometryCollection = GeoJsonType.GeometryCollection.geogsjonvalue(); + }; @Override - public MapGeometry execute(int importFlags, Geometry.Type type, String geoJsonString, - ProgressTracker progressTracker) throws JSONException { - try { - JsonFactory factory = new JsonFactory(); - JsonParser jsonParser = factory.createJsonParser(geoJsonString); - - jsonParser.nextToken(); - - MapGeometry map_geometry = OperatorImportFromGeoJsonHelper.importFromGeoJson(importFlags, type, - new JsonParserReader(jsonParser), progressTracker, false); - return map_geometry; - - } catch (JSONException jsonException) { - throw jsonException; - } catch (JsonParseException jsonParseException) { - throw new JSONException(jsonParseException.getMessage()); - } catch (IOException ioException) { - throw new JSONException(ioException.getMessage()); - } + public MapGeometry execute(int importFlags, Geometry.Type type, + String geoJsonString, ProgressTracker progressTracker) + throws JsonGeometryException { + MapGeometry map_geometry = OperatorImportFromGeoJsonHelper + .importFromGeoJson(importFlags, type, JsonParserReader.createFromString(geoJsonString), progressTracker, false); + return map_geometry; } @Override - public MapGeometry execute(int importFlags, Geometry.Type type, JSONObject jsonObject, - ProgressTracker progressTracker) throws JSONException { - if (jsonObject == null) + public MapGeometry execute(int importFlags, Geometry.Type type, + JsonReader jsonReader, ProgressTracker progressTracker) + throws JsonGeometryException { + if (jsonReader == null) return null; - try { - return OperatorImportFromGeoJsonHelper.importFromGeoJson(importFlags, type, new JsonValueReader(jsonObject), - progressTracker, false); - } catch (JSONException jsonException) { - throw jsonException; - } catch (JsonParseException jsonParseException) { - throw new JSONException(jsonParseException.getMessage()); - } catch (IOException ioException) { - throw new JSONException(ioException.getMessage()); - } + return OperatorImportFromGeoJsonHelper.importFromGeoJson(importFlags, + type, jsonReader, progressTracker, false); } static final class OperatorImportFromGeoJsonHelper { @@ -91,6 +82,8 @@ static final class OperatorImportFromGeoJsonHelper { private boolean m_b_has_ms_known; private int m_num_embeddings; + int m_ogcType; + OperatorImportFromGeoJsonHelper() { m_position = null; m_zs = null; @@ -103,45 +96,129 @@ static final class OperatorImportFromGeoJsonHelper { m_b_has_zs_known = false; m_b_has_ms_known = false; m_num_embeddings = 0; + m_ogcType = 0; } - static MapGeometry importFromGeoJson(int importFlags, Geometry.Type type, JsonReader json_iterator, + static MapGeometry importFromGeoJson(int importFlags, + Geometry.Type type, JsonReader json_iterator, ProgressTracker progress_tracker, boolean skip_coordinates) - throws JSONException, JsonParseException, IOException { - assert(json_iterator.currentToken() == JsonToken.START_OBJECT); + throws JsonGeometryException { + OperatorImportFromGeoJsonHelper geo_json_helper = new OperatorImportFromGeoJsonHelper(); + MapOGCStructure ms = geo_json_helper.importFromGeoJsonImpl( + importFlags, type, json_iterator, progress_tracker, + skip_coordinates, 0); + + if (geo_json_helper.m_ogcType == GeoJsonValues.GeometryCollection && !skip_coordinates) + throw new JsonGeometryException("parsing error"); + + return new MapGeometry(ms.m_ogcStructure.m_geometry, + ms.m_spatialReference); + } + static MapOGCStructure importFromGeoJson(int importFlags, + Geometry.Type type, JsonReader json_iterator, + ProgressTracker progress_tracker, boolean skip_coordinates, + int recursion) throws JsonGeometryException { OperatorImportFromGeoJsonHelper geo_json_helper = new OperatorImportFromGeoJsonHelper(); + MapOGCStructure ms = geo_json_helper.importFromGeoJsonImpl( + importFlags, type, json_iterator, progress_tracker, + skip_coordinates, recursion); + + if (geo_json_helper.m_ogcType == GeoJsonValues.GeometryCollection && !skip_coordinates) + throw new JsonGeometryException("parsing error"); + + return ms; + } + MapOGCStructure importFromGeoJsonImpl(int importFlags, + Geometry.Type type, JsonReader json_iterator, + ProgressTracker progress_tracker, boolean skip_coordinates, + int recursion) throws JsonGeometryException { + OperatorImportFromGeoJsonHelper geo_json_helper = this; boolean b_type_found = false; boolean b_coordinates_found = false; boolean b_crs_found = false; boolean b_crsURN_found = false; - String geo_json_type = null; + boolean b_geometry_collection = false; + boolean b_geometries_found = false; + GeoJsonType geo_json_type = null; Geometry geometry = null; SpatialReference spatial_reference = null; - JsonToken current_token; + JsonReader.Token current_token; String field_name = null; + MapOGCStructure ms = new MapOGCStructure(); - while ((current_token = json_iterator.nextToken()) != JsonToken.END_OBJECT) { + while ((current_token = json_iterator.nextToken()) != JsonReader.Token.END_OBJECT) { field_name = json_iterator.currentString(); if (field_name.equals("type")) { if (b_type_found) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_type_found = true; current_token = json_iterator.nextToken(); - if (current_token != JsonToken.VALUE_STRING) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.VALUE_STRING) { + throw new JsonGeometryException("parsing error"); } - geo_json_type = json_iterator.currentString(); + String s = json_iterator.currentString(); + try { + geo_json_type = GeoJsonType.valueOf(s); + } catch (Exception ex) { + throw new JsonGeometryException(s); + } + + if (geo_json_type == GeoJsonType.GeometryCollection) { + if (type != Geometry.Type.Unknown) + throw new JsonGeometryException("parsing error"); + + b_geometry_collection = true; + } + } else if (field_name.equals("geometries")) { + b_geometries_found = true; + if (type != Geometry.Type.Unknown) + throw new JsonGeometryException("parsing error"); + + if (recursion > 10) { + throw new JsonGeometryException("deep geojson"); + } + + if (skip_coordinates) { + json_iterator.skipChildren(); + } else { + current_token = json_iterator.nextToken(); + + ms.m_ogcStructure = new OGCStructure(); + ms.m_ogcStructure.m_type = GeoJsonValues.GeometryCollection; + ms.m_ogcStructure.m_structures = new ArrayList( + 0); + + if (current_token == JsonReader.Token.START_ARRAY) { + current_token = json_iterator.nextToken(); + while (current_token != JsonReader.Token.END_ARRAY) { + MapOGCStructure child = importFromGeoJson( + importFlags + | GeoJsonImportFlags.geoJsonImportSkipCRS, + type, json_iterator, + progress_tracker, false, + recursion + 1); + ms.m_ogcStructure.m_structures + .add(child.m_ogcStructure); + + current_token = json_iterator.nextToken(); + } + } + else if (current_token != JsonReader.Token.VALUE_NULL) { + throw new JsonGeometryException("parsing error"); + } + } } else if (field_name.equals("coordinates")) { + if (b_coordinates_found) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_coordinates_found = true; @@ -152,36 +229,38 @@ static MapGeometry importFromGeoJson(int importFlags, Geometry.Type type, JsonRe } else {// According to the spec, the value of the // coordinates must be an array. However, I do an // extra check for null too. - if (current_token != JsonToken.VALUE_NULL) { - if (current_token != JsonToken.START_ARRAY) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.VALUE_NULL) { + if (current_token != JsonReader.Token.START_ARRAY) { + throw new JsonGeometryException("parsing error"); } - geo_json_helper.import_coordinates_(json_iterator, progress_tracker); + geo_json_helper.import_coordinates_(json_iterator, + progress_tracker); } } } else if (field_name.equals("crs")) { if (b_crs_found || b_crsURN_found) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_crs_found = true; current_token = json_iterator.nextToken(); if ((importFlags & GeoJsonImportFlags.geoJsonImportSkipCRS) == 0) - spatial_reference = importSpatialReferenceFromCrs(json_iterator, progress_tracker); + spatial_reference = importSpatialReferenceFromCrs( + json_iterator, progress_tracker); else json_iterator.skipChildren(); } else if (field_name.equals("crsURN")) { if (b_crs_found || b_crsURN_found) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_crsURN_found = true; current_token = json_iterator.nextToken(); - spatial_reference = importSpatialReferenceFromCrsUrn_(json_iterator, - progress_tracker); + spatial_reference = importSpatialReferenceFromCrsUrn_( + json_iterator, progress_tracker); } else { json_iterator.nextToken(); json_iterator.skipChildren(); @@ -190,14 +269,27 @@ static MapGeometry importFromGeoJson(int importFlags, Geometry.Type type, JsonRe // According to the spec, a GeoJSON object must have both a type and // a coordinates array - if (!b_type_found || (!b_coordinates_found && !skip_coordinates)) { - throw new IllegalArgumentException("invalid argument"); + if (!b_type_found || (!b_geometry_collection && !b_coordinates_found && !skip_coordinates)) { + throw new JsonGeometryException("parsing error"); + } + + if ((!b_geometry_collection && b_geometries_found) || (b_geometry_collection && !b_geometries_found)) { + throw new JsonGeometryException("parsing error");//found "geometries" but did not see "GeometryCollection" } + - if (!skip_coordinates) - geometry = geo_json_helper.createGeometry_(geo_json_type, type.value()); + if (!skip_coordinates && !b_geometry_collection) { + geometry = geo_json_helper.createGeometry_(geo_json_type, + type.value()); + + ms.m_ogcStructure = new OGCStructure(); + ms.m_ogcStructure.m_type = m_ogcType; + ms.m_ogcStructure.m_geometry = geometry; + } - if (!b_crs_found && !b_crsURN_found && ((importFlags & GeoJsonImportFlags.geoJsonImportSkipCRS) == 0) + if (!b_crs_found + && !b_crsURN_found + && ((importFlags & GeoJsonImportFlags.geoJsonImportSkipCRS) == 0) && ((importFlags & GeoJsonImportFlags.geoJsonImportNoWGS84Default) == 0)) { spatial_reference = SpatialReference.create(4326); // the spec // gives a @@ -207,12 +299,8 @@ static MapGeometry importFromGeoJson(int importFlags, Geometry.Type type, JsonRe // is given } - MapGeometry map_geometry = new MapGeometry(geometry, spatial_reference); - - assert(geo_json_helper.m_paths == null || (geo_json_helper.m_path_flags != null - && geo_json_helper.m_paths.size() == geo_json_helper.m_path_flags.size())); - - return map_geometry; + ms.m_spatialReference = spatial_reference; + return ms; } // We have to import the coordinates in the most general way possible to @@ -225,86 +313,88 @@ static MapGeometry importFromGeoJson(int importFlags, Geometry.Type type, JsonRe // coordinates // into the attribute stream(s), and will later assign them to a // geometry after the type tag is found. - private void import_coordinates_(JsonReader json_iterator, ProgressTracker progress_tracker) - throws JSONException, JsonParseException, IOException { - assert(json_iterator.currentToken() == JsonToken.START_ARRAY); + private void import_coordinates_(JsonReader json_iterator, + ProgressTracker progress_tracker) throws JsonGeometryException { + assert (json_iterator.currentToken() == JsonReader.Token.START_ARRAY); int coordinates_level_lower = 1; int coordinates_level_upper = 4; json_iterator.nextToken(); - while (json_iterator.currentToken() != JsonToken.END_ARRAY) { + while (json_iterator.currentToken() != JsonReader.Token.END_ARRAY) { if (isDouble_(json_iterator)) { if (coordinates_level_upper > 1) { coordinates_level_upper = 1; } - } else if (json_iterator.currentToken() == JsonToken.START_ARRAY) { + } else if (json_iterator.currentToken() == JsonReader.Token.START_ARRAY) { if (coordinates_level_lower < 2) { coordinates_level_lower = 2; } } else { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } if (coordinates_level_lower > coordinates_level_upper) { throw new IllegalArgumentException("invalid argument"); } - if (coordinates_level_lower == coordinates_level_upper && coordinates_level_lower == 1) {// special - // code - // for - // Points + if (coordinates_level_lower == coordinates_level_upper + && coordinates_level_lower == 1) {// special + // code + // for + // Points readCoordinateAsPoint_(json_iterator); } else { boolean b_add_path_level_3 = true; boolean b_polygon_start_level_4 = true; - assert(json_iterator.currentToken() == JsonToken.START_ARRAY); + assert (json_iterator.currentToken() == JsonReader.Token.START_ARRAY); json_iterator.nextToken(); - while (json_iterator.currentToken() != JsonToken.END_ARRAY) { + while (json_iterator.currentToken() != JsonReader.Token.END_ARRAY) { if (isDouble_(json_iterator)) { if (coordinates_level_upper > 2) { coordinates_level_upper = 2; } - } else if (json_iterator.currentToken() == JsonToken.START_ARRAY) { + } else if (json_iterator.currentToken() == JsonReader.Token.START_ARRAY) { if (coordinates_level_lower < 3) { coordinates_level_lower = 3; } } else { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } if (coordinates_level_lower > coordinates_level_upper) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } - if (coordinates_level_lower == coordinates_level_upper && coordinates_level_lower == 2) {// LineString - // or - // MultiPoint + if (coordinates_level_lower == coordinates_level_upper + && coordinates_level_lower == 2) {// LineString + // or + // MultiPoint addCoordinate_(json_iterator); } else { boolean b_add_path_level_4 = true; - assert(json_iterator.currentToken() == JsonToken.START_ARRAY); + assert (json_iterator.currentToken() == JsonReader.Token.START_ARRAY); json_iterator.nextToken(); - while (json_iterator.currentToken() != JsonToken.END_ARRAY) { + while (json_iterator.currentToken() != JsonReader.Token.END_ARRAY) { if (isDouble_(json_iterator)) { if (coordinates_level_upper > 3) { coordinates_level_upper = 3; } - } else if (json_iterator.currentToken() == JsonToken.START_ARRAY) { + } else if (json_iterator.currentToken() == JsonReader.Token.START_ARRAY) { if (coordinates_level_lower < 4) { coordinates_level_lower = 4; } } else { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } if (coordinates_level_lower > coordinates_level_upper) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } if (coordinates_level_lower == coordinates_level_upper @@ -318,16 +408,15 @@ private void import_coordinates_(JsonReader json_iterator, ProgressTracker progr addCoordinate_(json_iterator); } else { - assert(json_iterator.currentToken() == JsonToken.START_ARRAY); + assert (json_iterator.currentToken() == JsonReader.Token.START_ARRAY); json_iterator.nextToken(); - if (json_iterator.currentToken() != JsonToken.END_ARRAY) { + if (json_iterator.currentToken() != JsonReader.Token.END_ARRAY) { if (!isDouble_(json_iterator)) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } - assert(coordinates_level_lower == coordinates_level_upper - && coordinates_level_lower == 4); + assert (coordinates_level_lower == coordinates_level_upper && coordinates_level_lower == 4); // MultiPolygon if (b_add_path_level_4) { @@ -363,8 +452,8 @@ private void import_coordinates_(JsonReader json_iterator, ProgressTracker progr } private void readCoordinateAsPoint_(JsonReader json_iterator) - throws JSONException, JsonParseException, IOException { - assert(isDouble_(json_iterator)); + throws JsonGeometryException { + assert (isDouble_(json_iterator)); m_point = new Point(); @@ -391,16 +480,18 @@ private void readCoordinateAsPoint_(JsonReader json_iterator) m_point.setM(m); } - if (json_iterator.currentToken() != JsonToken.END_ARRAY) { - throw new IllegalArgumentException("invalid argument"); + if (json_iterator.currentToken() != JsonReader.Token.END_ARRAY) { + throw new JsonGeometryException("parsing error"); } } - private void addCoordinate_(JsonReader json_iterator) throws JSONException, JsonParseException, IOException { - assert(isDouble_(json_iterator)); + private void addCoordinate_(JsonReader json_iterator) + throws JsonGeometryException { + assert (isDouble_(json_iterator)); if (m_position == null) { - m_position = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(0); + m_position = (AttributeStreamOfDbl) AttributeStreamBase + .createDoubleStream(0); } double x = readDouble_(json_iterator); @@ -417,11 +508,14 @@ private void addCoordinate_(JsonReader json_iterator) throws JSONException, Json if (!m_b_has_zs_known) { m_b_has_zs_known = true; m_b_has_zs = true; - m_zs = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(0); + m_zs = (AttributeStreamOfDbl) AttributeStreamBase + .createDoubleStream(0); } else { if (!m_b_has_zs) { - m_zs = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(size >> 1, - VertexDescription.getDefaultValue(Semantics.Z)); + m_zs = (AttributeStreamOfDbl) AttributeStreamBase + .createDoubleStream(size >> 1, + VertexDescription + .getDefaultValue(Semantics.Z)); m_b_has_zs = true; } } @@ -444,11 +538,14 @@ private void addCoordinate_(JsonReader json_iterator) throws JSONException, Json if (!m_b_has_ms_known) { m_b_has_ms_known = true; m_b_has_ms = true; - m_ms = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(0); + m_ms = (AttributeStreamOfDbl) AttributeStreamBase + .createDoubleStream(0); } else { if (!m_b_has_ms) { - m_ms = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(size >> 1, - VertexDescription.getDefaultValue(Semantics.M)); + m_ms = (AttributeStreamOfDbl) AttributeStreamBase + .createDoubleStream(size >> 1, + VertexDescription + .getDefaultValue(Semantics.M)); m_b_has_ms = true; } } @@ -467,14 +564,15 @@ private void addCoordinate_(JsonReader json_iterator) throws JSONException, Json } } - if (json_iterator.currentToken() != JsonToken.END_ARRAY) { - throw new IllegalArgumentException("invalid argument"); + if (json_iterator.currentToken() != JsonReader.Token.END_ARRAY) { + throw new JsonGeometryException("parsing error"); } } private void addPath_() { if (m_paths == null) { - m_paths = (AttributeStreamOfInt32) AttributeStreamBase.createIndexStream(0); + m_paths = (AttributeStreamOfInt32) AttributeStreamBase + .createIndexStream(0); } if (m_position == null) { @@ -486,68 +584,77 @@ private void addPath_() { private void addPathFlag_(boolean b_polygon_start) { if (m_path_flags == null) { - m_path_flags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(0); + m_path_flags = (AttributeStreamOfInt8) AttributeStreamBase + .createByteStream(0); } if (b_polygon_start) { - m_path_flags.add((byte) (PathFlags.enumClosed | PathFlags.enumOGCStartPolygon)); + m_path_flags + .add((byte) (PathFlags.enumClosed | PathFlags.enumOGCStartPolygon)); } else { m_path_flags.add((byte) PathFlags.enumClosed); } } - private double readDouble_(JsonReader json_iterator) throws JSONException, JsonParseException, IOException { - JsonToken current_token = json_iterator.currentToken(); - if (current_token == JsonToken.VALUE_NULL - || (current_token == JsonToken.VALUE_STRING && json_iterator.currentString().equals("NaN"))) { + private double readDouble_(JsonReader json_iterator) + throws JsonGeometryException { + JsonReader.Token current_token = json_iterator.currentToken(); + if (current_token == JsonReader.Token.VALUE_NULL + || (current_token == JsonReader.Token.VALUE_STRING && json_iterator + .currentString().equals("NaN"))) { return NumberUtils.NaN(); } else { return json_iterator.currentDoubleValue(); } } - private boolean isDouble_(JsonReader json_iterator) throws JSONException, JsonParseException, IOException { - JsonToken current_token = json_iterator.currentToken(); + private boolean isDouble_(JsonReader json_iterator) + throws JsonGeometryException { + JsonReader.Token current_token = json_iterator.currentToken(); - if (current_token == JsonToken.VALUE_NUMBER_FLOAT) { + if (current_token == JsonReader.Token.VALUE_NUMBER_FLOAT) { return true; } - if (current_token == JsonToken.VALUE_NUMBER_INT) { + if (current_token == JsonReader.Token.VALUE_NUMBER_INT) { return true; } - if (current_token == JsonToken.VALUE_NULL - || (current_token == JsonToken.VALUE_STRING && json_iterator.currentString().equals("NaN"))) { + if (current_token == JsonReader.Token.VALUE_NULL + || (current_token == JsonReader.Token.VALUE_STRING && json_iterator + .currentString().equals("NaN"))) { return true; } return false; } - private Geometry createGeometry_(String geo_json_type, int type) - throws JSONException, JsonParseException, IOException { + //does not accept GeometryCollection + private Geometry createGeometry_(GeoJsonType geo_json_type, int type) + throws JsonGeometryException { Geometry geometry; if (type != Geometry.GeometryType.Unknown) { switch (type) { case Geometry.GeometryType.Polygon: - if (!geo_json_type.equals("MultiPolygon") && !geo_json_type.equals("Polygon")) { + if (geo_json_type != GeoJsonType.MultiPolygon + && geo_json_type != GeoJsonType.Polygon) { throw new GeometryException("invalid shape type"); } break; case Geometry.GeometryType.Polyline: - if (!geo_json_type.equals("MultiLineString") && !geo_json_type.equals("LineString")) { + if (geo_json_type != GeoJsonType.MultiLineString + && geo_json_type != GeoJsonType.LineString) { throw new GeometryException("invalid shape type"); } break; case Geometry.GeometryType.MultiPoint: - if (!geo_json_type.equals("MultiPoint")) { + if (geo_json_type != GeoJsonType.MultiPoint) { throw new GeometryException("invalid shape type"); } break; case Geometry.GeometryType.Point: - if (!geo_json_type.equals("Point")) { + if (geo_json_type != GeoJsonType.Point) { throw new GeometryException("invalid shape type"); } break; @@ -555,70 +662,88 @@ private Geometry createGeometry_(String geo_json_type, int type) throw new GeometryException("invalid shape type"); } } - + + m_ogcType = geo_json_type.geogsjonvalue(); + if (geo_json_type == GeoJsonType.GeometryCollection) + throw new IllegalArgumentException("invalid argument"); + if (m_position == null && m_point == null) { - if (geo_json_type.equals("Point")) { + switch (geo_json_type) + { + case Point: { if (m_num_embeddings > 1) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } geometry = new Point(); - } else if (geo_json_type.equals("MultiPoint")) { + break; + } + case MultiPoint: { if (m_num_embeddings > 2) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } geometry = new MultiPoint(); - } else if (geo_json_type.equals("LineString")) { + break; + } + case LineString: { if (m_num_embeddings > 2) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } geometry = new Polyline(); - } else if (geo_json_type.equals("MultiLineString")) { + break; + } + case MultiLineString: { if (m_num_embeddings > 3) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } geometry = new Polyline(); - } else if (geo_json_type.equals("Polygon")) { + break; + } + case Polygon: { if (m_num_embeddings > 3) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } geometry = new Polygon(); - } else if (geo_json_type.equals("MultiPolygon")) { - assert(m_num_embeddings <= 4); + break; + } + case MultiPolygon: { + assert (m_num_embeddings <= 4); geometry = new Polygon(); - } else { - throw new IllegalArgumentException("invalid argument"); + break; + } + default: + throw new JsonGeometryException("parsing error"); } } else if (m_num_embeddings == 1) { - if (!geo_json_type.equals("Point")) { - throw new IllegalArgumentException("invalid argument"); + if (geo_json_type != GeoJsonType.Point) { + throw new JsonGeometryException("parsing error"); } - assert(m_point != null); + assert (m_point != null); geometry = m_point; } else if (m_num_embeddings == 2) { - if (geo_json_type.equals("MultiPoint")) { + if (geo_json_type == GeoJsonType.MultiPoint) { geometry = createMultiPointFromStreams_(); - } else if (geo_json_type.equals("LineString")) { + } else if (geo_json_type == GeoJsonType.LineString) { geometry = createPolylineFromStreams_(); } else { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } } else if (m_num_embeddings == 3) { - if (geo_json_type.equals("Polygon")) { + if (geo_json_type == GeoJsonType.Polygon) { geometry = createPolygonFromStreams_(); - } else if (geo_json_type.equals("MultiLineString")) { + } else if (geo_json_type == GeoJsonType.MultiLineString) { geometry = createPolylineFromStreams_(); } else { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } } else { - if (!geo_json_type.equals("MultiPolygon")) { - throw new IllegalArgumentException("invalid argument"); + if (geo_json_type != GeoJsonType.MultiPolygon) { + throw new JsonGeometryException("parsing error"); } geometry = createPolygonFromStreams_(); @@ -628,29 +753,34 @@ private Geometry createGeometry_(String geo_json_type, int type) } private Geometry createPolygonFromStreams_() { - assert(m_position != null); - assert(m_paths != null); - assert((m_num_embeddings == 3 && m_path_flags == null) || (m_num_embeddings == 4 && m_path_flags != null)); + assert (m_position != null); + assert (m_paths != null); + assert ((m_num_embeddings == 3 && m_path_flags == null) || (m_num_embeddings == 4 && m_path_flags != null)); Polygon polygon = new Polygon(); MultiPathImpl multi_path_impl = (MultiPathImpl) polygon._getImpl(); checkPathPointCountsForMultiPath_(true); - multi_path_impl.setAttributeStreamRef(Semantics.POSITION, m_position); + multi_path_impl.setAttributeStreamRef(Semantics.POSITION, + m_position); if (m_b_has_zs) { - assert(m_zs != null); + assert (m_zs != null); multi_path_impl.setAttributeStreamRef(Semantics.Z, m_zs); } if (m_b_has_ms) { - assert(m_ms != null); + assert (m_ms != null); multi_path_impl.setAttributeStreamRef(Semantics.M, m_ms); } if (m_path_flags == null) { - m_path_flags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(m_paths.size(), (byte) 0); - m_path_flags.setBits(0, (byte) (PathFlags.enumClosed | PathFlags.enumOGCStartPolygon)); + m_path_flags = (AttributeStreamOfInt8) AttributeStreamBase + .createByteStream(m_paths.size(), (byte) 0); + m_path_flags + .setBits( + 0, + (byte) (PathFlags.enumClosed | PathFlags.enumOGCStartPolygon)); for (int i = 1; i < m_path_flags.size() - 1; i++) { m_path_flags.setBits(i, (byte) PathFlags.enumClosed); @@ -659,13 +789,15 @@ private Geometry createPolygonFromStreams_() { multi_path_impl.setPathStreamRef(m_paths); multi_path_impl.setPathFlagsStreamRef(m_path_flags); - multi_path_impl.notifyModified(MultiVertexGeometryImpl.DirtyFlags.DirtyAll); + multi_path_impl + .notifyModified(MultiVertexGeometryImpl.DirtyFlags.DirtyAll); - AttributeStreamOfInt8 path_flags_clone = new AttributeStreamOfInt8(m_path_flags); + AttributeStreamOfInt8 path_flags_clone = new AttributeStreamOfInt8( + m_path_flags); for (int i = 0; i < path_flags_clone.size() - 1; i++) { - assert((path_flags_clone.read(i) & PathFlags.enumClosed) != 0); - assert((m_path_flags.read(i) & PathFlags.enumClosed) != 0); + assert ((path_flags_clone.read(i) & PathFlags.enumClosed) != 0); + assert ((m_path_flags.read(i) & PathFlags.enumClosed) != 0); if ((path_flags_clone.read(i) & PathFlags.enumOGCStartPolygon) != 0) {// Should // be @@ -680,69 +812,76 @@ private Geometry createPolygonFromStreams_() { } } } + multi_path_impl.setPathFlagsStreamRef(path_flags_clone); - multi_path_impl.setDirtyOGCFlags(false); + multi_path_impl.clearDirtyOGCFlags(); return polygon; } private Geometry createPolylineFromStreams_() { - assert(m_position != null); - assert((m_num_embeddings == 2 && m_paths == null) || (m_num_embeddings == 3 && m_paths != null)); - assert(m_path_flags == null); + assert (m_position != null); + assert ((m_num_embeddings == 2 && m_paths == null) || (m_num_embeddings == 3 && m_paths != null)); + assert (m_path_flags == null); Polyline polyline = new Polyline(); MultiPathImpl multi_path_impl = (MultiPathImpl) polyline._getImpl(); if (m_paths == null) { - m_paths = (AttributeStreamOfInt32) AttributeStreamBase.createIndexStream(0); + m_paths = (AttributeStreamOfInt32) AttributeStreamBase + .createIndexStream(0); m_paths.add(0); m_paths.add(m_position.size() / 2); } checkPathPointCountsForMultiPath_(false); - multi_path_impl.setAttributeStreamRef(Semantics.POSITION, m_position); + multi_path_impl.setAttributeStreamRef(Semantics.POSITION, + m_position); if (m_b_has_zs) { - assert(m_zs != null); + assert (m_zs != null); multi_path_impl.setAttributeStreamRef(Semantics.Z, m_zs); } if (m_b_has_ms) { - assert(m_ms != null); + assert (m_ms != null); multi_path_impl.setAttributeStreamRef(Semantics.M, m_ms); } - m_path_flags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(m_paths.size(), (byte) 0); + m_path_flags = (AttributeStreamOfInt8) AttributeStreamBase + .createByteStream(m_paths.size(), (byte) 0); multi_path_impl.setPathStreamRef(m_paths); multi_path_impl.setPathFlagsStreamRef(m_path_flags); - multi_path_impl.notifyModified(MultiVertexGeometryImpl.DirtyFlags.DirtyAll); + multi_path_impl + .notifyModified(MultiVertexGeometryImpl.DirtyFlags.DirtyAll); return polyline; } private Geometry createMultiPointFromStreams_() { - assert(m_position != null); - assert(m_paths == null); - assert(m_path_flags == null); + assert (m_position != null); + assert (m_paths == null); + assert (m_path_flags == null); MultiPoint multi_point = new MultiPoint(); - MultiPointImpl multi_point_impl = (MultiPointImpl) multi_point._getImpl(); - multi_point_impl.setAttributeStreamRef(Semantics.POSITION, m_position); + MultiPointImpl multi_point_impl = (MultiPointImpl) multi_point + ._getImpl(); + multi_point_impl.setAttributeStreamRef(Semantics.POSITION, + m_position); if (m_b_has_zs) { - assert(m_zs != null); + assert (m_zs != null); multi_point_impl.setAttributeStreamRef(Semantics.Z, m_zs); } if (m_b_has_ms) { - assert(m_ms != null); + assert (m_ms != null); multi_point_impl.setAttributeStreamRef(Semantics.M, m_ms); } + multi_point_impl.resize(m_position.size() / 2); multi_point_impl.notifyModified(MultiVertexGeometryImpl.DirtyFlags.DirtyAll); - return multi_point; } @@ -794,14 +933,15 @@ private void checkPathPointCountsForMultiPath_(boolean b_is_polygon) { int path_start = m_paths.read(path); int path_end = m_paths.read(path + 1); int path_size = path_end - path_start; - assert(path_size != 0); // we should not have added empty parts - // on import + assert (path_size != 0); // we should not have added empty parts + // on import if (path_size == 1) { - insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, adjusted_ms, adjusted_start, path_start, + insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, + adjusted_ms, adjusted_start, path_start, path_size); + insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, + adjusted_ms, adjusted_start + 1, path_start, path_size); - insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, adjusted_ms, adjusted_start + 1, - path_start, path_size); adjusted_start += 2; } else if (path_size >= 3 && b_is_polygon) { m_position.read(path_start * 2, pt1); @@ -817,19 +957,22 @@ private void checkPathPointCountsForMultiPath_(boolean b_is_polygon) { m2 = m_ms.readAsDbl(path_end - 1); } - if (pt1.equals(pt2) && (NumberUtils.isNaN(z1) && NumberUtils.isNaN(z2) || z1 == z2) + if (pt1.equals(pt2) + && (NumberUtils.isNaN(z1) && NumberUtils.isNaN(z2) || z1 == z2) && (NumberUtils.isNaN(m1) && NumberUtils.isNaN(m2) || m1 == m2)) { - insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, adjusted_ms, adjusted_start, + insertIntoAdjustedStreams_(adjusted_position, + adjusted_zs, adjusted_ms, adjusted_start, path_start, path_size - 1); adjusted_start += path_size - 1; } else { - insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, adjusted_ms, adjusted_start, + insertIntoAdjustedStreams_(adjusted_position, + adjusted_zs, adjusted_ms, adjusted_start, path_start, path_size); adjusted_start += path_size; } } else { - insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, adjusted_ms, adjusted_start, path_start, - path_size); + insertIntoAdjustedStreams_(adjusted_position, adjusted_zs, + adjusted_ms, adjusted_start, path_start, path_size); adjusted_start += path_size; } adjusted_paths.write(path + 1, adjusted_start); @@ -841,30 +984,35 @@ private void checkPathPointCountsForMultiPath_(boolean b_is_polygon) { m_ms = adjusted_ms; } - private void insertIntoAdjustedStreams_(AttributeStreamOfDbl adjusted_position, - AttributeStreamOfDbl adjusted_zs, AttributeStreamOfDbl adjusted_ms, int adjusted_start, int path_start, - int count) { - adjusted_position.insertRange(adjusted_start * 2, m_position, path_start * 2, count * 2, true, 2, - adjusted_start * 2); + private void insertIntoAdjustedStreams_( + AttributeStreamOfDbl adjusted_position, + AttributeStreamOfDbl adjusted_zs, + AttributeStreamOfDbl adjusted_ms, int adjusted_start, + int path_start, int count) { + adjusted_position.insertRange(adjusted_start * 2, m_position, + path_start * 2, count * 2, true, 2, adjusted_start * 2); if (m_b_has_zs) { - adjusted_zs.insertRange(adjusted_start, m_zs, path_start, count, true, 1, adjusted_start); + adjusted_zs.insertRange(adjusted_start, m_zs, path_start, + count, true, 1, adjusted_start); } if (m_b_has_ms) { - adjusted_ms.insertRange(adjusted_start, m_ms, path_start, count, true, 1, adjusted_start); + adjusted_ms.insertRange(adjusted_start, m_ms, path_start, + count, true, 1, adjusted_start); } } - static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, - ProgressTracker progress_tracker) throws JSONException, JsonParseException, IOException { + static SpatialReference importSpatialReferenceFromCrs( + JsonReader json_iterator, ProgressTracker progress_tracker) + throws JsonGeometryException { // According to the spec, a null crs corresponds to no spatial // reference - if (json_iterator.currentToken() == JsonToken.VALUE_NULL) { + if (json_iterator.currentToken() == JsonReader.Token.VALUE_NULL) { return null; } - if (json_iterator.currentToken() == JsonToken.VALUE_STRING) {// see + if (json_iterator.currentToken() == JsonReader.Token.VALUE_STRING) {// see // http://wiki.geojson.org/RFC-001 // (this // is @@ -879,7 +1027,8 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, // format) String crs_short_form = json_iterator.currentString(); - int wkid = GeoJsonCrsTables.getWkidFromCrsShortForm(crs_short_form); + int wkid = GeoJsonCrsTables + .getWkidFromCrsShortForm(crs_short_form); if (wkid == -1) { throw new GeometryException("not implemented"); @@ -895,8 +1044,8 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, return spatial_reference; } - if (json_iterator.currentToken() != JsonToken.START_OBJECT) { - throw new IllegalArgumentException("invalid argument"); + if (json_iterator.currentToken() != JsonReader.Token.START_OBJECT) { + throw new JsonGeometryException("parsing error"); } // This is to support all cases of crs identifiers I've seen. Some @@ -910,86 +1059,92 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, boolean b_found_properties_url = false; boolean b_found_properties_code = false; boolean b_found_esriwkt = false; - String crs_field = null, properties_field = null, type = null, crs_identifier_name = null, - crs_identifier_urn = null, crs_identifier_href = null, crs_identifier_url = null, esriwkt = null; + String crs_field = null; + String properties_field = null; + String crs_identifier_name = null; + String crs_identifier_urn = null; + String crs_identifier_href = null; + String crs_identifier_url = null; + String esriwkt = null; int crs_identifier_code = -1; - JsonToken current_token; + JsonReader.Token current_token; - while (json_iterator.nextToken() != JsonToken.END_OBJECT) { + while (json_iterator.nextToken() != JsonReader.Token.END_OBJECT) { crs_field = json_iterator.currentString(); if (crs_field.equals("type")) { if (b_found_type) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_type = true; current_token = json_iterator.nextToken(); - if (current_token != JsonToken.VALUE_STRING) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.VALUE_STRING) { + throw new JsonGeometryException("parsing error"); } - type = json_iterator.currentString(); + //type = json_iterator.currentString(); } else if (crs_field.equals("properties")) { if (b_found_properties) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_properties = true; current_token = json_iterator.nextToken(); - if (current_token != JsonToken.START_OBJECT) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.START_OBJECT) { + throw new JsonGeometryException("parsing error"); } - while (json_iterator.nextToken() != JsonToken.END_OBJECT) { + while (json_iterator.nextToken() != JsonReader.Token.END_OBJECT) { properties_field = json_iterator.currentString(); if (properties_field.equals("name")) { if (b_found_properties_name) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_properties_name = true; crs_identifier_name = getCrsIdentifier_(json_iterator); } else if (properties_field.equals("href")) { if (b_found_properties_href) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_properties_href = true; crs_identifier_href = getCrsIdentifier_(json_iterator); } else if (properties_field.equals("urn")) { if (b_found_properties_urn) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_properties_urn = true; crs_identifier_urn = getCrsIdentifier_(json_iterator); } else if (properties_field.equals("url")) { if (b_found_properties_url) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_properties_url = true; crs_identifier_url = getCrsIdentifier_(json_iterator); } else if (properties_field.equals("code")) { if (b_found_properties_code) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_properties_code = true; current_token = json_iterator.nextToken(); - if (current_token != JsonToken.VALUE_NUMBER_INT) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.VALUE_NUMBER_INT) { + throw new JsonGeometryException("parsing error"); } - crs_identifier_code = json_iterator.currentIntValue(); + crs_identifier_code = json_iterator + .currentIntValue(); } else { json_iterator.nextToken(); json_iterator.skipChildren(); @@ -997,15 +1152,15 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, } } else if (crs_field.equals("esriwkt")) { if (b_found_esriwkt) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } b_found_esriwkt = true; current_token = json_iterator.nextToken(); - if (current_token != JsonToken.VALUE_STRING) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.VALUE_STRING) { + throw new JsonGeometryException("parsing error"); } esriwkt = json_iterator.currentString(); @@ -1016,7 +1171,7 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, } if ((!b_found_type || !b_found_properties) && !b_found_esriwkt) { - throw new IllegalArgumentException("invalid argument"); + throw new JsonGeometryException("parsing error"); } int wkid = -1; @@ -1032,9 +1187,10 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, // (somewhat // common) } else if (b_found_properties_urn) { - wkid = GeoJsonCrsTables.getWkidFromCrsOgcUrn(crs_identifier_urn); // see - // http://wiki.geojson.org/GeoJSON_draft_version_5 - // (rare) + wkid = GeoJsonCrsTables + .getWkidFromCrsOgcUrn(crs_identifier_urn); // see + // http://wiki.geojson.org/GeoJSON_draft_version_5 + // (rare) } else if (b_found_properties_url) { wkid = GeoJsonCrsTables.getWkidFromCrsHref(crs_identifier_url); // see // http://wiki.geojson.org/GeoJSON_draft_version_5 @@ -1044,11 +1200,11 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, // http://wiki.geojson.org/GeoJSON_draft_version_5 // (rare) } else if (!b_found_esriwkt) { - throw new GeometryException("not implemented"); + throw new JsonGeometryException("parsing error"); } if (wkid < 0 && !b_found_esriwkt && !b_found_properties_name) { - throw new GeometryException("not implemented"); + throw new JsonGeometryException("parsing error"); } SpatialReference spatial_reference = null; @@ -1072,8 +1228,10 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, // the properties // name is like // "ESRI:" - String potential_wkt = GeoJsonCrsTables.getWktFromCrsName(crs_identifier_name); - spatial_reference = SpatialReference.create(potential_wkt); + String potential_wkt = GeoJsonCrsTables + .getWktFromCrsName(crs_identifier_name); + spatial_reference = SpatialReference + .create(potential_wkt); } } catch (Exception e) { } @@ -1083,16 +1241,17 @@ static SpatialReference importSpatialReferenceFromCrs(JsonReader json_iterator, } // see http://geojsonwg.github.io/draft-geojson/draft.html - static SpatialReference importSpatialReferenceFromCrsUrn_(JsonReader json_iterator, - ProgressTracker progress_tracker) throws JSONException, JsonParseException, IOException { + static SpatialReference importSpatialReferenceFromCrsUrn_( + JsonReader json_iterator, ProgressTracker progress_tracker) + throws JsonGeometryException { // According to the spec, a null crs corresponds to no spatial // reference - if (json_iterator.currentToken() == JsonToken.VALUE_NULL) { + if (json_iterator.currentToken() == JsonReader.Token.VALUE_NULL) { return null; } - if (json_iterator.currentToken() != JsonToken.VALUE_STRING) { - throw new IllegalArgumentException("invalid argument"); + if (json_iterator.currentToken() != JsonReader.Token.VALUE_STRING) { + throw new JsonGeometryException("parsing error"); } String crs_identifier_urn = json_iterator.currentString(); @@ -1121,11 +1280,11 @@ static SpatialReference importSpatialReferenceFromCrsUrn_(JsonReader json_iterat } private static String getCrsIdentifier_(JsonReader json_iterator) - throws JSONException, JsonParseException, IOException { - JsonToken current_token = json_iterator.nextToken(); + throws JsonGeometryException { + JsonReader.Token current_token = json_iterator.nextToken(); - if (current_token != JsonToken.VALUE_STRING) { - throw new IllegalArgumentException("invalid argument"); + if (current_token != JsonReader.Token.VALUE_STRING) { + throw new JsonGeometryException("parsing error"); } return json_iterator.currentString(); @@ -1133,466 +1292,28 @@ private static String getCrsIdentifier_(JsonReader json_iterator) } - static JSONArray getJSONArray(JSONObject obj, String name) throws JSONException { - if (obj.get(name) == JSONObject.NULL) - return new JSONArray(); - else - return obj.getJSONArray(name); - } - @Override - public MapOGCStructure executeOGC(int import_flags, String geoJsonString, ProgressTracker progress_tracker) - throws JSONException { - MapOGCStructure mapOGCStructure = null; - try { - JSONObject geoJsonObject = new JSONObject(geoJsonString); - ArrayList structureStack = new ArrayList(0); - ArrayList objectStack = new ArrayList(0); - AttributeStreamOfInt32 indices = new AttributeStreamOfInt32(0); - AttributeStreamOfInt32 numGeometries = new AttributeStreamOfInt32(0); - OGCStructure root = new OGCStructure(); - root.m_structures = new ArrayList(0); - structureStack.add(root); // add dummy root - objectStack.add(geoJsonObject); - indices.add(0); - numGeometries.add(1); - while (!objectStack.isEmpty()) { - if (indices.getLast() == numGeometries.getLast()) { - structureStack.remove(structureStack.size() - 1); - indices.removeLast(); - numGeometries.removeLast(); - continue; - } - OGCStructure lastStructure = structureStack.get(structureStack.size() - 1); - JSONObject lastObject = objectStack.get(objectStack.size() - 1); - objectStack.remove(objectStack.size() - 1); - indices.write(indices.size() - 1, indices.getLast() + 1); - String typeString = lastObject.getString("type"); - if (typeString.equalsIgnoreCase("GeometryCollection")) { - OGCStructure next = new OGCStructure(); - next.m_type = 7; - next.m_structures = new ArrayList(0); - lastStructure.m_structures.add(next); - structureStack.add(next); - JSONArray geometries = getJSONArray(lastObject, "geometries"); - indices.add(0); - numGeometries.add(geometries.length()); - for (int i = geometries.length() - 1; i >= 0; i--) - objectStack.add(geometries.getJSONObject(i)); - } else { - int ogcType; - if (typeString.equalsIgnoreCase("Point")) - ogcType = 1; - else if (typeString.equalsIgnoreCase("LineString")) - ogcType = 2; - else if (typeString.equalsIgnoreCase("Polygon")) - ogcType = 3; - else if (typeString.equalsIgnoreCase("MultiPoint")) - ogcType = 4; - else if (typeString.equalsIgnoreCase("MultiLineString")) - ogcType = 5; - else if (typeString.equalsIgnoreCase("MultiPolygon")) - ogcType = 6; - else - throw new UnsupportedOperationException(); - - MapGeometry map_geometry = execute(import_flags | GeoJsonImportFlags.geoJsonImportSkipCRS, - Geometry.Type.Unknown, lastObject, null); - OGCStructure leaf = new OGCStructure(); - leaf.m_type = ogcType; - leaf.m_geometry = map_geometry.getGeometry(); - lastStructure.m_structures.add(leaf); - } - } - mapOGCStructure = new MapOGCStructure(); - mapOGCStructure.m_ogcStructure = root; - - if ((import_flags & GeoJsonImportFlags.geoJsonImportSkipCRS) == 0) - mapOGCStructure.m_spatialReference = importSpatialReferenceFromGeoJson_(import_flags, geoJsonObject); - } catch (JSONException jsonException) { - throw jsonException; - } catch (JsonParseException jsonParseException) { - throw new JSONException(jsonParseException.getMessage()); - } catch (IOException ioException) { - throw new JSONException(ioException.getMessage()); - } - - return mapOGCStructure; - } - - private static SpatialReference importSpatialReferenceFromGeoJson_(int importFlags, JSONObject crsJSONObject) - throws JSONException, JsonParseException, IOException { - - SpatialReference spatial_reference = null; - boolean b_crs_found = false, b_crsURN_found = false; - - Object opt = crsJSONObject.opt("crs"); - - if (opt != null) { - b_crs_found = true; - JSONObject crs_object = new JSONObject(); - crs_object.put("crs", opt); - JsonValueReader json_iterator = new JsonValueReader(crs_object); - json_iterator.nextToken(); - json_iterator.nextToken(); - return OperatorImportFromGeoJsonHelper.importSpatialReferenceFromCrs(json_iterator, null); - } - - opt = crsJSONObject.opt("crsURN"); - - if (opt != null) { - b_crsURN_found = true; - JSONObject crs_object = new JSONObject(); - crs_object.put("crsURN", opt); - JsonValueReader json_iterator = new JsonValueReader(crs_object); - json_iterator.nextToken(); - json_iterator.nextToken(); - return OperatorImportFromGeoJsonHelper.importSpatialReferenceFromCrs(json_iterator, null); - } - - if ((importFlags & GeoJsonImportFlags.geoJsonImportNoWGS84Default) == 0) { - spatial_reference = SpatialReference.create(4326); - } - - return spatial_reference; - } - - /* - private static Geometry importGeometryFromGeoJson_(int importFlags, Geometry.Type type, - JSONObject geometryJSONObject) throws JSONException { - String typeString = geometryJSONObject.getString("type"); - JSONArray coordinateArray = getJSONArray(geometryJSONObject, "coordinates"); - if (typeString.equalsIgnoreCase("MultiPolygon")) { - if (type != Geometry.Type.Polygon && type != Geometry.Type.Unknown) - throw new IllegalArgumentException("invalid shapetype"); - return polygonTaggedText_(true, importFlags, coordinateArray); - } else if (typeString.equalsIgnoreCase("MultiLineString")) { - if (type != Geometry.Type.Polyline && type != Geometry.Type.Unknown) - throw new IllegalArgumentException("invalid shapetype"); - return lineStringTaggedText_(true, importFlags, coordinateArray); - } else if (typeString.equalsIgnoreCase("MultiPoint")) { - if (type != Geometry.Type.MultiPoint && type != Geometry.Type.Unknown) - throw new IllegalArgumentException("invalid shapetype"); - return multiPointTaggedText_(importFlags, coordinateArray); - } else if (typeString.equalsIgnoreCase("Polygon")) { - if (type != Geometry.Type.Polygon && type != Geometry.Type.Unknown) - throw new IllegalArgumentException("invalid shapetype"); - return polygonTaggedText_(false, importFlags, coordinateArray); - } else if (typeString.equalsIgnoreCase("LineString")) { - if (type != Geometry.Type.Polyline && type != Geometry.Type.Unknown) - throw new IllegalArgumentException("invalid shapetype"); - return lineStringTaggedText_(false, importFlags, coordinateArray); - } else if (typeString.equalsIgnoreCase("Point")) { - if (type != Geometry.Type.Point && type != Geometry.Type.Unknown) - throw new IllegalArgumentException("invalid shapetype"); - return pointTaggedText_(importFlags, coordinateArray); - } else { - return null; - } - } - - private static Geometry polygonTaggedText_(boolean bMultiPolygon, int importFlags, JSONArray coordinateArray) - throws JSONException { - MultiPath multiPath; - MultiPathImpl multiPathImpl; - AttributeStreamOfDbl zs = null; - AttributeStreamOfDbl ms = null; - AttributeStreamOfDbl position; - AttributeStreamOfInt32 paths; - AttributeStreamOfInt8 path_flags; - position = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(0); - paths = (AttributeStreamOfInt32) AttributeStreamBase.createIndexStream(1, 0); - path_flags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(1, (byte) 0); - multiPath = new Polygon(); - multiPathImpl = (MultiPathImpl) multiPath._getImpl(); - int pointCount; - if (bMultiPolygon) { - pointCount = multiPolygonText_(zs, ms, position, paths, path_flags, coordinateArray); - } else { - pointCount = polygonText_(zs, ms, position, paths, path_flags, 0, coordinateArray); - } - if (pointCount != 0) { - assert(2 * pointCount == position.size()); - multiPathImpl.setAttributeStreamRef(VertexDescription.Semantics.POSITION, position); - multiPathImpl.setPathStreamRef(paths); - multiPathImpl.setPathFlagsStreamRef(path_flags); - if (zs != null) { - multiPathImpl.setAttributeStreamRef(VertexDescription.Semantics.Z, zs); - } - if (ms != null) { - multiPathImpl.setAttributeStreamRef(VertexDescription.Semantics.M, ms); - } - multiPathImpl.notifyModified(MultiPathImpl.DirtyFlags.DirtyAll); - AttributeStreamOfInt8 path_flags_clone = new AttributeStreamOfInt8(path_flags); - for (int i = 0; i < path_flags_clone.size() - 1; i++) { - if (((int) path_flags_clone.read(i) & (int) PathFlags.enumOGCStartPolygon) != 0) {// Should - // be - // clockwise - if (!InternalUtils.isClockwiseRing(multiPathImpl, i)) - multiPathImpl.reversePath(i); // make clockwise - } else {// Should be counter-clockwise - if (InternalUtils.isClockwiseRing(multiPathImpl, i)) - multiPathImpl.reversePath(i); // make counter-clockwise - } - } - multiPathImpl.setPathFlagsStreamRef(path_flags_clone); - } - if ((importFlags & (int) GeoJsonImportFlags.geoJsonImportNonTrusted) == 0) { - multiPathImpl.setIsSimple(MultiPathImpl.GeometryXSimple.Weak, 0.0, false); - } - multiPathImpl.setDirtyOGCFlags(false); - return multiPath; - } - - private static Geometry lineStringTaggedText_(boolean bMultiLineString, int importFlags, JSONArray coordinateArray) - throws JSONException { - MultiPath multiPath; - MultiPathImpl multiPathImpl; - AttributeStreamOfDbl zs = null; - AttributeStreamOfDbl ms = null; - AttributeStreamOfDbl position; - AttributeStreamOfInt32 paths; - AttributeStreamOfInt8 path_flags; - position = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(0); - paths = (AttributeStreamOfInt32) AttributeStreamBase.createIndexStream(1, 0); - path_flags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(1, (byte) 0); - multiPath = new Polyline(); - multiPathImpl = (MultiPathImpl) multiPath._getImpl(); - int pointCount; - if (bMultiLineString) { - pointCount = multiLineStringText_(zs, ms, position, paths, path_flags, coordinateArray); - } else { - pointCount = lineStringText_(false, zs, ms, position, paths, path_flags, coordinateArray); - } - if (pointCount != 0) { - assert(2 * pointCount == position.size()); - multiPathImpl.setAttributeStreamRef(VertexDescription.Semantics.POSITION, position); - multiPathImpl.setPathStreamRef(paths); - multiPathImpl.setPathFlagsStreamRef(path_flags); - if (zs != null) { - multiPathImpl.setAttributeStreamRef(VertexDescription.Semantics.Z, zs); - } - if (ms != null) { - multiPathImpl.setAttributeStreamRef(VertexDescription.Semantics.M, ms); - } - multiPathImpl.notifyModified(MultiPathImpl.DirtyFlags.DirtyAll); - } - return multiPath; - } - - private static Geometry multiPointTaggedText_(int importFlags, JSONArray coordinateArray) throws JSONException { - MultiPoint multiPoint; - MultiPointImpl multiPointImpl; - AttributeStreamOfDbl zs = null; - AttributeStreamOfDbl ms = null; - AttributeStreamOfDbl position; - position = (AttributeStreamOfDbl) AttributeStreamBase.createDoubleStream(0); - multiPoint = new MultiPoint(); - multiPointImpl = (MultiPointImpl) multiPoint._getImpl(); - int pointCount = multiPointText_(zs, ms, position, coordinateArray); - if (pointCount != 0) { - assert(2 * pointCount == position.size()); - multiPointImpl.resize(pointCount); - multiPointImpl.setAttributeStreamRef(VertexDescription.Semantics.POSITION, position); - multiPointImpl.notifyModified(MultiPointImpl.DirtyFlags.DirtyAll); - } - return multiPoint; - } - - private static Geometry pointTaggedText_(int importFlags, JSONArray coordinateArray) throws JSONException { - Point point = new Point(); - int length = coordinateArray.length(); - if (length == 0) { - point.setEmpty(); - return point; - } - point.setXY(getDouble_(coordinateArray, 0), getDouble_(coordinateArray, 1)); - return point; - } - - private static int multiPolygonText_(AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, - AttributeStreamOfDbl position, AttributeStreamOfInt32 paths, AttributeStreamOfInt8 path_flags, - JSONArray coordinateArray) throws JSONException { - // At start of MultiPolygonText - int totalPointCount = 0; - int length = coordinateArray.length(); - if (length == 0) - return totalPointCount; - for (int current = 0; current < length; current++) { - JSONArray subArray = coordinateArray.optJSONArray(current); - if (subArray == null) {// Entry should be a JSONArray representing a - // polygon, but it is not a JSONArray. - throw new IllegalArgumentException(""); - } - - // At start of PolygonText - totalPointCount = polygonText_(zs, ms, position, paths, path_flags, totalPointCount, subArray); - } - return totalPointCount; - } - - private static int multiLineStringText_(AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, - AttributeStreamOfDbl position, AttributeStreamOfInt32 paths, AttributeStreamOfInt8 path_flags, - JSONArray coordinateArray) throws JSONException { - // At start of MultiLineStringText - int totalPointCount = 0; - int length = coordinateArray.length(); - if (length == 0) - return totalPointCount; - for (int current = 0; current < length; current++) { - JSONArray subArray = coordinateArray.optJSONArray(current); - if (subArray == null) {// Entry should be a JSONArray representing a - // line string, but it is not a JSONArray. - throw new IllegalArgumentException(""); - } - - // At start of LineStringText - totalPointCount += lineStringText_(false, zs, ms, position, paths, path_flags, subArray); - } - return totalPointCount; - } - - private static int multiPointText_(AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position, - JSONArray coordinateArray) throws JSONException { - // At start of MultiPointText - int pointCount = 0; - for (int current = 0; current < coordinateArray.length(); current++) { - JSONArray subArray = coordinateArray.optJSONArray(current); - if (subArray == null) {// Entry should be a JSONArray representing a - // point, but it is not a JSONArray. - throw new IllegalArgumentException(""); - } - pointCount += pointText_(zs, ms, position, subArray); - } - return pointCount; - } - - private static int polygonText_(AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position, - AttributeStreamOfInt32 paths, AttributeStreamOfInt8 path_flags, int totalPointCount, - JSONArray coordinateArray) throws JSONException { - // At start of PolygonText - int length = coordinateArray.length(); - if (length == 0) { - return totalPointCount; - } - boolean bFirstLineString = true; - for (int current = 0; current < length; current++) { - JSONArray subArray = coordinateArray.optJSONArray(current); - if (subArray == null) {// Entry should be a JSONArray representing a - // line string, but it is not a JSONArray. - throw new IllegalArgumentException(""); - } - // At start of LineStringText - int pointCount = lineStringText_(true, zs, ms, position, paths, path_flags, subArray); - if (pointCount != 0) { - if (bFirstLineString) { - bFirstLineString = false; - path_flags.setBits(path_flags.size() - 2, (byte) PathFlags.enumOGCStartPolygon); - } - path_flags.setBits(path_flags.size() - 2, (byte) PathFlags.enumClosed); - totalPointCount += pointCount; - } - } - return totalPointCount; + public MapOGCStructure executeOGC(int import_flags, String geoJsonString, + ProgressTracker progress_tracker) throws JsonGeometryException { + return executeOGC(import_flags, JsonParserReader.createFromString(geoJsonString), + progress_tracker); } - private static int lineStringText_(boolean bRing, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, - AttributeStreamOfDbl position, AttributeStreamOfInt32 paths, AttributeStreamOfInt8 path_flags, - JSONArray coordinateArray) throws JSONException { - // At start of LineStringText - int pointCount = 0; - int length = coordinateArray.length(); - if (length == 0) - return pointCount; - boolean bStartPath = true; - double startX = NumberUtils.TheNaN; - double startY = NumberUtils.TheNaN; - double startZ = NumberUtils.TheNaN; - double startM = NumberUtils.TheNaN; - for (int current = 0; current < length; current++) { - JSONArray subArray = coordinateArray.optJSONArray(current); - if (subArray == null) {// Entry should be a JSONArray representing a - // single point, but it is not a JSONArray. - throw new IllegalArgumentException(""); - } - // At start of x - double x = getDouble_(subArray, 0); - double y = getDouble_(subArray, 1); - double z = NumberUtils.TheNaN; - double m = NumberUtils.TheNaN; - boolean bAddPoint = true; - if (bRing && pointCount >= 2 && current == length - 1) {// If the - // last - // point in - // the ring - // is not - // equal to - // the start - // point, - // then - // let's add - // it. - if ((startX == x || (NumberUtils.isNaN(startX) && NumberUtils.isNaN(x))) - && (startY == y || (NumberUtils.isNaN(startY) && NumberUtils.isNaN(y)))) { - bAddPoint = false; - } - } - if (bAddPoint) { - if (bStartPath) { - bStartPath = false; - startX = x; - startY = y; - startZ = z; - startM = m; - } - pointCount++; - addToStreams_(zs, ms, position, x, y, z, m); - } - } - if (pointCount == 1) { - pointCount++; - addToStreams_(zs, ms, position, startX, startY, startZ, startM); - } - paths.add(position.size() / 2); - path_flags.add((byte) 0); - return pointCount; + public MapOGCStructure executeOGC(int import_flags, + JsonReader json_iterator, ProgressTracker progress_tracker) + throws JsonGeometryException { + MapOGCStructure mapOGCStructure = OperatorImportFromGeoJsonHelper.importFromGeoJson( + import_flags, Geometry.Type.Unknown, json_iterator, + progress_tracker, false, 0); + + //This is to restore legacy behavior when we always return a geometry collection of one element. + MapOGCStructure res = new MapOGCStructure(); + res.m_ogcStructure = new OGCStructure(); + res.m_ogcStructure.m_type = 0; + res.m_ogcStructure.m_structures = new ArrayList(); + res.m_ogcStructure.m_structures.add(mapOGCStructure.m_ogcStructure); + res.m_spatialReference = mapOGCStructure.m_spatialReference; + return res; } - private static int pointText_(AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position, - JSONArray coordinateArray) throws JSONException { - // At start of PointText - int length = coordinateArray.length(); - if (length == 0) - return 0; - // At start of x - double x = getDouble_(coordinateArray, 0); - double y = getDouble_(coordinateArray, 1); - double z = NumberUtils.TheNaN; - double m = NumberUtils.TheNaN; - addToStreams_(zs, ms, position, x, y, z, m); - return 1; - } - - private static void addToStreams_(AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position, - double x, double y, double z, double m) { - position.add(x); - position.add(y); - if (zs != null) - zs.add(z); - if (ms != null) - ms.add(m); - } - - private static double getDouble_(JSONArray coordinateArray, int index) throws JSONException { - if (index < 0 || index >= coordinateArray.length()) { - throw new IllegalArgumentException(""); - } - if (coordinateArray.isNull(index)) { - return NumberUtils.TheNaN; - } - if (coordinateArray.optDouble(index, NumberUtils.TheNaN) != NumberUtils.TheNaN) { - return coordinateArray.getDouble(index); - } - throw new IllegalArgumentException(""); - }*/ } diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromJson.java b/src/main/java/com/esri/core/geometry/OperatorImportFromJson.java index 6a88d05c..93f30da5 100644 --- a/src/main/java/com/esri/core/geometry/OperatorImportFromJson.java +++ b/src/main/java/com/esri/core/geometry/OperatorImportFromJson.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,15 +24,6 @@ package com.esri.core.geometry; -import java.io.IOException; - -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.json.JSONObject; -import org.json.JSONException; - -import com.esri.core.geometry.Operator.Type; - /** *Import from JSON format. */ @@ -48,29 +39,20 @@ public Type getType() { * @return Returns a MapGeometryCursor. */ abstract MapGeometryCursor execute(Geometry.Type type, - JsonParserCursor jsonParserCursor); + JsonReaderCursor jsonReaderCursor); /** *Performs the ImportFromJson operation on a single Json string *@return Returns a MapGeometry. */ public abstract MapGeometry execute(Geometry.Type type, - JsonParser jsonParser); + JsonReader jsonReader); /** *Performs the ImportFromJson operation on a single Json string *@return Returns a MapGeometry. */ - public abstract MapGeometry execute(Geometry.Type type, String string) - throws JsonParseException, IOException; - - /** - *Performs the ImportFromJson operation on a JSONObject - *@return Returns a MapGeometry. - */ - public abstract MapGeometry execute(Geometry.Type type, JSONObject jsonObject) - throws JSONException, IOException; - + public abstract MapGeometry execute(Geometry.Type type, String string); public static OperatorImportFromJson local() { return (OperatorImportFromJson) OperatorFactoryLocal.getInstance() diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromJsonCursor.java b/src/main/java/com/esri/core/geometry/OperatorImportFromJsonCursor.java index 8c267d7a..2971f441 100644 --- a/src/main/java/com/esri/core/geometry/OperatorImportFromJsonCursor.java +++ b/src/main/java/com/esri/core/geometry/OperatorImportFromJsonCursor.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -26,18 +26,15 @@ import com.esri.core.geometry.MultiVertexGeometryImpl.DirtyFlags; import com.esri.core.geometry.VertexDescription.Semantics; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; class OperatorImportFromJsonCursor extends MapGeometryCursor { - JsonParserCursor m_inputJsonParsers; + JsonReaderCursor m_inputJsonParsers; int m_type; int m_index; - public OperatorImportFromJsonCursor(int type, JsonParserCursor jsonParsers) { + public OperatorImportFromJsonCursor(int type, JsonReaderCursor jsonParsers) { m_index = -1; if (jsonParsers == null) throw new IllegalArgumentException(); @@ -53,10 +50,10 @@ public int getGeometryID() { @Override public MapGeometry next() { - JsonParser jsonParser; + JsonReader jsonParser; if ((jsonParser = m_inputJsonParsers.next()) != null) { m_index = m_inputJsonParsers.getID(); - return importFromJsonParser(m_type, new JsonParserReader(jsonParser)); + return importFromJsonParser(m_type, jsonParser); } return null; } @@ -108,26 +105,26 @@ static MapGeometry importFromJsonParser(int gt, JsonReader parser) { Geometry geometry = null; SpatialReference spatial_reference = null; - while (parser.nextToken() != JsonToken.END_OBJECT) { + while (parser.nextToken() != JsonReader.Token.END_OBJECT) { String name = parser.currentString(); parser.nextToken(); if (!bFoundSpatial_reference && name.equals("spatialReference")) { bFoundSpatial_reference = true; - if (parser.currentToken() == JsonToken.START_OBJECT) { + if (parser.currentToken() == JsonReader.Token.START_OBJECT) { spatial_reference = SpatialReference.fromJson(parser); } else { - if (parser.currentToken() != JsonToken.VALUE_NULL) + if (parser.currentToken() != JsonReader.Token.VALUE_NULL) throw new GeometryException( "failed to parse spatial reference: object or null is expected"); } } else if (!bFoundHasZ && name.equals("hasZ")) { bFoundHasZ = true; - bHasZ = (parser.currentToken() == JsonToken.VALUE_TRUE); + bHasZ = (parser.currentToken() == JsonReader.Token.VALUE_TRUE); } else if (!bFoundHasM && name.equals("hasM")) { bFoundHasM = true; - bHasM = (parser.currentToken() == JsonToken.VALUE_TRUE); + bHasM = (parser.currentToken() == JsonReader.Token.VALUE_TRUE); } else if (!bFoundPolygon && name.equals("rings") && (gt == Geometry.GeometryType.Unknown || gt == Geometry.GeometryType.Polygon)) { @@ -308,15 +305,13 @@ public static MapGeometry fromJsonToMultiPoint(JsonReader parser) return importFromJsonParser(Geometry.GeometryType.MultiPoint, parser); } - private static void windup(JsonReader parser) throws Exception, - JsonParseException { + private static void windup(JsonReader parser) { parser.skipChildren(); } - private static double readDouble(JsonReader parser) throws Exception, - JsonParseException { - if (parser.currentToken() == JsonToken.VALUE_NULL - || parser.currentToken() == JsonToken.VALUE_STRING + private static double readDouble(JsonReader parser) { + if (parser.currentToken() == JsonReader.Token.VALUE_NULL + || parser.currentToken() == JsonReader.Token.VALUE_STRING && parser.currentString().equals("NaN")) return NumberUtils.NaN(); else @@ -325,7 +320,7 @@ private static double readDouble(JsonReader parser) throws Exception, private static Geometry importFromJsonMultiPoint(JsonReader parser, AttributeStreamOfDbl as, AttributeStreamOfDbl bs) throws Exception { - if (parser.currentToken() != JsonToken.START_ARRAY) + if (parser.currentToken() != JsonReader.Token.START_ARRAY) throw new GeometryException( "failed to parse multipoint: array of vertices is expected"); @@ -340,13 +335,13 @@ private static Geometry importFromJsonMultiPoint(JsonReader parser, // At start of rings int sz; double[] buf = new double[4]; - while (parser.nextToken() != JsonToken.END_ARRAY) { - if (parser.currentToken() != JsonToken.START_ARRAY) + while (parser.nextToken() != JsonReader.Token.END_ARRAY) { + if (parser.currentToken() != JsonReader.Token.START_ARRAY) throw new GeometryException( "failed to parse multipoint: array is expected, multipoint vertices consist of arrays of cooridinates"); sz = 0; - while (parser.nextToken() != JsonToken.END_ARRAY) { + while (parser.nextToken() != JsonReader.Token.END_ARRAY) { buf[sz++] = readDouble(parser); } @@ -408,7 +403,7 @@ else if (c < 16) private static Geometry importFromJsonMultiPath(boolean b_polygon, JsonReader parser, AttributeStreamOfDbl as, AttributeStreamOfDbl bs) throws Exception { - if (parser.currentToken() != JsonToken.START_ARRAY) + if (parser.currentToken() != JsonReader.Token.START_ARRAY) throw new GeometryException( "failed to parse multipath: array of array of vertices is expected"); @@ -436,8 +431,8 @@ private static Geometry importFromJsonMultiPath(boolean b_polygon, int requiredSize = b_polygon ? 3 : 2; // At start of rings - while (parser.nextToken() != JsonToken.END_ARRAY) { - if (parser.currentToken() != JsonToken.START_ARRAY) + while (parser.nextToken() != JsonReader.Token.END_ARRAY) { + if (parser.currentToken() != JsonReader.Token.START_ARRAY) throw new GeometryException( "failed to parse multipath: ring/path array is expected"); @@ -447,13 +442,13 @@ private static Geometry importFromJsonMultiPath(boolean b_polygon, int szstart = 0; parser.nextToken(); - while (parser.currentToken() != JsonToken.END_ARRAY) { - if (parser.currentToken() != JsonToken.START_ARRAY) + while (parser.currentToken() != JsonReader.Token.END_ARRAY) { + if (parser.currentToken() != JsonReader.Token.START_ARRAY) throw new GeometryException( "failed to parse multipath: array is expected, rings/paths vertices consist of arrays of cooridinates"); sz = 0; - while (parser.nextToken() != JsonToken.END_ARRAY) { + while (parser.nextToken() != JsonReader.Token.END_ARRAY) { buf[sz++] = readDouble(parser); } @@ -522,7 +517,7 @@ else if (c < 16) point_count++; pathPointCount++; } while (pathPointCount < requiredSize - && parser.currentToken() == JsonToken.END_ARRAY); + && parser.currentToken() == JsonReader.Token.END_ARRAY); } if (b_polygon && pathPointCount > requiredSize && sz == szstart diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromJsonLocal.java b/src/main/java/com/esri/core/geometry/OperatorImportFromJsonLocal.java index 4e41a491..55d94171 100644 --- a/src/main/java/com/esri/core/geometry/OperatorImportFromJsonLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorImportFromJsonLocal.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,46 +23,20 @@ */ package com.esri.core.geometry; -import java.io.IOException; - -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.json.JSONObject; -import org.json.JSONException; - -import com.esri.core.geometry.ogc.OGCGeometry; - class OperatorImportFromJsonLocal extends OperatorImportFromJson { @Override public MapGeometryCursor execute(Geometry.Type type, - JsonParserCursor jsonParserCursor) { + JsonReaderCursor jsonParserCursor) { return new OperatorImportFromJsonCursor(type.value(), jsonParserCursor); } @Override - public MapGeometry execute(Geometry.Type type, JsonParser jsonParser) { - SimpleJsonParserCursor jsonParserCursor = new SimpleJsonParserCursor( - jsonParser); - OperatorImportFromJsonCursor cursor = new OperatorImportFromJsonCursor( - type.value(), jsonParserCursor); - return cursor.next(); + public MapGeometry execute(Geometry.Type type, JsonReader jsonParser) { + return OperatorImportFromJsonCursor.importFromJsonParser(type.value(), jsonParser); } @Override - public MapGeometry execute(Geometry.Type type, String string) - throws JsonParseException, IOException { - JsonFactory factory = new JsonFactory(); - JsonParser jsonParserPt = factory.createJsonParser(string); - jsonParserPt.nextToken(); - return execute(type, jsonParserPt); + public MapGeometry execute(Geometry.Type type, String string) { + return execute(type, JsonParserReader.createFromString(string)); } - @Override - public MapGeometry execute(Geometry.Type type, JSONObject jsonObject) - throws JSONException, IOException { - if (jsonObject == null) - return null; - - return OperatorImportFromJsonCursor.importFromJsonParser(type.value(), new JsonValueReader(jsonObject)); - } } diff --git a/src/main/java/com/esri/core/geometry/SimpleJsonParserCursor.java b/src/main/java/com/esri/core/geometry/SimpleJsonReaderCursor.java similarity index 78% rename from src/main/java/com/esri/core/geometry/SimpleJsonParserCursor.java rename to src/main/java/com/esri/core/geometry/SimpleJsonReaderCursor.java index 5f034a82..9a0793fc 100644 --- a/src/main/java/com/esri/core/geometry/SimpleJsonParserCursor.java +++ b/src/main/java/com/esri/core/geometry/SimpleJsonReaderCursor.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,23 +23,21 @@ */ package com.esri.core.geometry; -import org.codehaus.jackson.JsonParser; +class SimpleJsonReaderCursor extends JsonReaderCursor { -class SimpleJsonParserCursor extends JsonParserCursor { - - JsonParser m_jsonParser; - JsonParser[] m_jsonParserArray; + JsonReader m_jsonParser; + JsonReader[] m_jsonParserArray; int m_index; int m_count; - public SimpleJsonParserCursor(JsonParser jsonString) { + public SimpleJsonReaderCursor(JsonReader jsonString) { m_jsonParser = jsonString; m_index = -1; m_count = 1; } - public SimpleJsonParserCursor(JsonParser[] jsonStringArray) { + public SimpleJsonReaderCursor(JsonReader[] jsonStringArray) { m_jsonParserArray = jsonStringArray; m_index = -1; m_count = jsonStringArray.length; @@ -51,7 +49,7 @@ public int getID() { } @Override - public JsonParser next() { + public JsonReader next() { if (m_index < m_count - 1) { m_index++; return m_jsonParser != null ? m_jsonParser diff --git a/src/main/java/com/esri/core/geometry/SpatialReference.java b/src/main/java/com/esri/core/geometry/SpatialReference.java index 39b1e90a..44fe3912 100644 --- a/src/main/java/com/esri/core/geometry/SpatialReference.java +++ b/src/main/java/com/esri/core/geometry/SpatialReference.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -26,12 +26,11 @@ import java.io.ObjectStreamException; import java.io.Serializable; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.SpatialReferenceSerializer; import com.esri.core.geometry.VertexDescription; +import com.fasterxml.jackson.core.JsonParser; /** * A class that represents the spatial reference for the geometry. @@ -91,7 +90,11 @@ public static SpatialReference fromJson(JsonParser parser) throws Exception { return fromJson(new JsonParserReader(parser)); } - static SpatialReference fromJson(JsonReader parser) throws Exception { + public static SpatialReference fromJson(String string) throws Exception { + return fromJson(JsonParserReader.createFromString(string)); + } + + public static SpatialReference fromJson(JsonReader parser) throws Exception { // Note this class is processed specially: it is expected that the // iterator points to the first element of the SR object. boolean bFoundWkid = false; @@ -105,34 +108,34 @@ static SpatialReference fromJson(JsonReader parser) throws Exception { int vcs_wkid = -1; int latestVcsWkid = -1; String wkt = null; - while (parser.nextToken() != JsonToken.END_OBJECT) { + while (parser.nextToken() != JsonReader.Token.END_OBJECT) { String name = parser.currentString(); parser.nextToken(); if (!bFoundWkid && name.equals("wkid")) { bFoundWkid = true; - if (parser.currentToken() == JsonToken.VALUE_NUMBER_INT) + if (parser.currentToken() == JsonReader.Token.VALUE_NUMBER_INT) wkid = parser.currentIntValue(); } else if (!bFoundLatestWkid && name.equals("latestWkid")) { bFoundLatestWkid = true; - if (parser.currentToken() == JsonToken.VALUE_NUMBER_INT) + if (parser.currentToken() == JsonReader.Token.VALUE_NUMBER_INT) latestWkid = parser.currentIntValue(); } else if (!bFoundWkt && name.equals("wkt")) { bFoundWkt = true; - if (parser.currentToken() == JsonToken.VALUE_STRING) + if (parser.currentToken() == JsonReader.Token.VALUE_STRING) wkt = parser.currentString(); } else if (!bFoundVcsWkid && name.equals("vcsWkid")) { bFoundVcsWkid = true; - if (parser.currentToken() == JsonToken.VALUE_NUMBER_INT) + if (parser.currentToken() == JsonReader.Token.VALUE_NUMBER_INT) vcs_wkid = parser.currentIntValue(); } else if (!bFoundLatestVcsWkid && name.equals("latestVcsWkid")) { bFoundLatestVcsWkid = true; - if (parser.currentToken() == JsonToken.VALUE_NUMBER_INT) + if (parser.currentToken() == JsonReader.Token.VALUE_NUMBER_INT) latestVcsWkid = parser.currentIntValue(); } } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 04b2df77..49197b83 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -5,42 +5,7 @@ import java.util.ArrayList; import java.util.Arrays; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.json.JSONException; - -import com.esri.core.geometry.Envelope; -import com.esri.core.geometry.Envelope1D; -import com.esri.core.geometry.Geometry; -import com.esri.core.geometry.GeometryCursor; -import com.esri.core.geometry.GeometryCursorAppend; -import com.esri.core.geometry.GeometryEngine; -import com.esri.core.geometry.MapGeometry; -import com.esri.core.geometry.MapOGCStructure; -import com.esri.core.geometry.MultiPoint; -import com.esri.core.geometry.NumberUtils; -import com.esri.core.geometry.OGCStructure; -import com.esri.core.geometry.Operator; -import com.esri.core.geometry.OperatorBuffer; -import com.esri.core.geometry.OperatorConvexHull; -import com.esri.core.geometry.OperatorExportToWkb; -import com.esri.core.geometry.OperatorExportToGeoJson; -import com.esri.core.geometry.OperatorFactoryLocal; -import com.esri.core.geometry.OperatorImportFromESRIShape; -import com.esri.core.geometry.OperatorImportFromGeoJson; -import com.esri.core.geometry.OperatorImportFromWkb; -import com.esri.core.geometry.OperatorImportFromWkt; -import com.esri.core.geometry.OperatorIntersection; -import com.esri.core.geometry.OperatorSimplify; -import com.esri.core.geometry.OperatorSimplifyOGC; -import com.esri.core.geometry.OperatorUnion; -import com.esri.core.geometry.Point; -import com.esri.core.geometry.Polygon; -import com.esri.core.geometry.Polyline; -import com.esri.core.geometry.SimpleGeometryCursor; -import com.esri.core.geometry.SpatialReference; -import com.esri.core.geometry.VertexDescription; +import com.esri.core.geometry.*; /** * OGC Simple Feature Access specification v.1.2.1 @@ -493,18 +458,13 @@ public static OGCGeometry fromEsriShape(ByteBuffer buffer) { SpatialReference.create(4326)); } - public static OGCGeometry fromJson(String string) - throws JsonParseException, IOException { - JsonFactory factory = new JsonFactory(); - JsonParser jsonParserPt = factory.createJsonParser(string); - jsonParserPt.nextToken(); - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPt); + public static OGCGeometry fromJson(String string) { + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(JsonParserReader.createFromString(string)); return OGCGeometry.createFromEsriGeometry(mapGeom.getGeometry(), mapGeom.getSpatialReference()); } - public static OGCGeometry fromGeoJson(String string) - throws JSONException { + public static OGCGeometry fromGeoJson(String string) { OperatorImportFromGeoJson op = (OperatorImportFromGeoJson) OperatorFactoryLocal .getInstance().getOperator(Operator.Type.ImportFromGeoJson); MapOGCStructure mapOGCStructure = op.executeOGC(0, string, null); diff --git a/src/test/java/com/esri/core/geometry/GeometryUtils.java b/src/test/java/com/esri/core/geometry/GeometryUtils.java index c1af6866..62ddbc37 100644 --- a/src/test/java/com/esri/core/geometry/GeometryUtils.java +++ b/src/test/java/com/esri/core/geometry/GeometryUtils.java @@ -4,9 +4,6 @@ import java.io.FileNotFoundException; import java.util.Scanner; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParser; - public class GeometryUtils { public static String getGeometryType(Geometry geomIn) { // there are five types: esriGeometryPoint @@ -29,12 +26,8 @@ public static String getGeometryType(Geometry geomIn) { } static Geometry getGeometryFromJSon(String jsonStr) { - JsonFactory jf = new JsonFactory(); - try { - JsonParser jp = jf.createJsonParser(jsonStr); - jp.nextToken(); - Geometry geom = GeometryEngine.jsonToGeometry(jp).getGeometry(); + Geometry geom = GeometryEngine.jsonToGeometry(jsonStr).getGeometry(); return geom; } catch (Exception ex) { return null; diff --git a/src/test/java/com/esri/core/geometry/TestCommonMethods.java b/src/test/java/com/esri/core/geometry/TestCommonMethods.java index 420718d4..b38aeec4 100644 --- a/src/test/java/com/esri/core/geometry/TestCommonMethods.java +++ b/src/test/java/com/esri/core/geometry/TestCommonMethods.java @@ -5,8 +5,6 @@ import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParser; import junit.framework.TestCase; import org.junit.Test; @@ -237,15 +235,8 @@ public static Object readObjectFromFile(String fileName) { } public static MapGeometry fromJson(String jsonString) { - JsonFactory factory = new JsonFactory(); try { - JsonParser jsonParser = factory.createJsonParser(jsonString); - jsonParser.nextToken(); - OperatorImportFromJson importer = (OperatorImportFromJson) OperatorFactoryLocal - .getInstance().getOperator( - Operator.Type.ImportFromJson); - - return importer.execute(Geometry.Type.Unknown, jsonParser); + return OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jsonString); } catch (Exception ex) { } diff --git a/src/test/java/com/esri/core/geometry/TestContains.java b/src/test/java/com/esri/core/geometry/TestContains.java index 71c811e9..4488b3ef 100644 --- a/src/test/java/com/esri/core/geometry/TestContains.java +++ b/src/test/java/com/esri/core/geometry/TestContains.java @@ -1,12 +1,15 @@ package com.esri.core.geometry; -import java.io.IOException; import junit.framework.TestCase; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; + +import java.io.IOException; + import org.junit.Test; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; + public class TestContains extends TestCase { @Override protected void setUp() throws Exception { @@ -19,11 +22,10 @@ protected void tearDown() throws Exception { } @Test - public static void testContainsFailureCR186456() throws JsonParseException, - IOException { + public static void testContainsFailureCR186456() throws JsonParseException, IOException { String str = "{\"rings\":[[[406944.399999999,287461.450000001],[406947.750000011,287462.299999997],[406946.44999999,287467.450000001],[406943.050000005,287466.550000005],[406927.799999992,287456.849999994],[406926.949999996,287456.599999995],[406924.800000005,287455.999999998],[406924.300000007,287455.849999999],[406924.200000008,287456.099999997],[406923.450000011,287458.449999987],[406922.999999987,287459.800000008],[406922.29999999,287462.099999998],[406921.949999991,287463.449999992],[406921.449999993,287465.050000011],[406920.749999996,287466.700000004],[406919.800000001,287468.599999996],[406919.050000004,287469.99999999],[406917.800000009,287471.800000008],[406916.04999999,287473.550000001],[406915.449999993,287473.999999999],[406913.700000001,287475.449999993],[406913.300000002,287475.899999991],[406912.050000008,287477.250000011],[406913.450000002,287478.150000007],[406915.199999994,287478.650000005],[406915.999999991,287478.800000005],[406918.300000007,287479.200000003],[406920.649999997,287479.450000002],[406923.100000013,287479.550000001],[406925.750000001,287479.450000002],[406928.39999999,287479.150000003],[406929.80000001,287478.950000004],[406932.449999998,287478.350000006],[406935.099999987,287477.60000001],[406938.699999998,287476.349999989],[406939.649999994,287473.949999999],[406939.799999993,287473.949999999],[406941.249999987,287473.75],[406942.700000007,287473.250000002],[406943.100000005,287473.100000003],[406943.950000001,287472.750000004],[406944.799999998,287472.300000006],[406944.999999997,287472.200000007],[406946.099999992,287471.200000011],[406946.299999991,287470.950000012],[406948.00000001,287468.599999996],[406948.10000001,287468.399999997],[406950.100000001,287465.050000011],[406951.949999993,287461.450000001],[406952.049999993,287461.300000001],[406952.69999999,287459.900000007],[406953.249999987,287458.549999987],[406953.349999987,287458.299999988],[406953.650000012,287457.299999992],[406953.900000011,287456.349999996],[406954.00000001,287455.300000001],[406954.00000001,287454.750000003],[406953.850000011,287453.750000008],[406953.550000012,287452.900000011],[406953.299999987,287452.299999988],[406954.500000008,287450.299999996],[406954.00000001,287449.000000002],[406953.399999987,287447.950000006],[406953.199999988,287447.550000008],[406952.69999999,287446.850000011],[406952.149999992,287446.099999988],[406951.499999995,287445.499999991],[406951.149999996,287445.249999992],[406950.449999999,287444.849999994],[406949.600000003,287444.599999995],[406949.350000004,287444.549999995],[406948.250000009,287444.499999995],[406947.149999987,287444.699999994],[406946.849999989,287444.749999994],[406945.899999993,287444.949999993],[406944.999999997,287445.349999991],[406944.499999999,287445.64999999],[406943.650000003,287446.349999987],[406942.900000006,287447.10000001],[406942.500000008,287447.800000007],[406942.00000001,287448.700000003],[406941.600000011,287449.599999999],[406941.350000013,287450.849999994],[406941.350000013,287451.84999999],[406941.450000012,287452.850000012],[406941.750000011,287453.850000007],[406941.800000011,287454.000000007],[406942.150000009,287454.850000003],[406942.650000007,287455.6],[406943.150000005,287456.299999997],[406944.499999999,287457.299999992],[406944.899999997,287457.599999991],[406945.299999995,287457.949999989],[406944.399999999,287461.450000001],[406941.750000011,287461.999999998],[406944.399999999,287461.450000001]],[[406944.399999999,287461.450000001],[406947.750000011,287462.299999997],[406946.44999999,287467.450000001],[406943.050000005,287466.550000005],[406927.799999992,287456.849999994],[406944.399999999,287461.450000001]]]}"; JsonFactory jsonFactory = new JsonFactory(); - JsonParser jsonParser = jsonFactory.createJsonParser(str); + JsonParser jsonParser = jsonFactory.createParser(str); MapGeometry mg = GeometryEngine.jsonToGeometry(jsonParser); boolean res = GeometryEngine.contains(mg.getGeometry(), mg.getGeometry(), null); diff --git a/src/test/java/com/esri/core/geometry/TestDistance.java b/src/test/java/com/esri/core/geometry/TestDistance.java index b531bb17..efcdaeeb 100644 --- a/src/test/java/com/esri/core/geometry/TestDistance.java +++ b/src/test/java/com/esri/core/geometry/TestDistance.java @@ -1,10 +1,6 @@ package com.esri.core.geometry; -import java.io.IOException; import junit.framework.TestCase; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; import org.junit.Test; public class TestDistance extends TestCase { @@ -146,17 +142,13 @@ private static Point makePoint() { } @Test - public static void testDistanceWithNullSpatialReference() - throws JsonParseException, IOException { + public static void testDistanceWithNullSpatialReference() { // There was a bug that distance op did not work with null Spatial // Reference. String str1 = "{\"paths\":[[[-117.138791850991,34.017492675023],[-117.138762336971,34.0174925550462]]]}"; String str2 = "{\"paths\":[[[-117.138867827972,34.0174854109623],[-117.138850197027,34.0174929160126],[-117.138791850991,34.017492675023]]]}"; - JsonFactory jsonFactory = new JsonFactory(); - JsonParser jsonParser1 = jsonFactory.createJsonParser(str1); - JsonParser jsonParser2 = jsonFactory.createJsonParser(str2); - MapGeometry geom1 = GeometryEngine.jsonToGeometry(jsonParser1); - MapGeometry geom2 = GeometryEngine.jsonToGeometry(jsonParser2); + MapGeometry geom1 = GeometryEngine.jsonToGeometry(JsonParserReader.createFromString(str1)); + MapGeometry geom2 = GeometryEngine.jsonToGeometry(JsonParserReader.createFromString(str2)); double distance = GeometryEngine.distance(geom1.getGeometry(), geom2.getGeometry(), null); assertTrue(distance == 0); diff --git a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java index 5ef3157e..aa480b26 100644 --- a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java +++ b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java @@ -27,12 +27,10 @@ import com.esri.core.geometry.ogc.OGCMultiPoint; import com.esri.core.geometry.ogc.OGCLineString; import com.esri.core.geometry.ogc.OGCPolygon; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; import junit.framework.TestCase; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParser; -import org.json.JSONException; -import org.json.JSONObject; import org.junit.Test; import java.io.IOException; @@ -228,10 +226,10 @@ public void testPolygonWithHoleReversed() { public void testMultiPolygon() throws IOException { JsonFactory jsonFactory = new JsonFactory(); - String geoJsonPolygon = "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-100,-100],[-100,100],[100,100],[100,-100],[-100,-100]],[[-90,-90],[90,90],[-90,90],[90,-90],[-90,-90]]],[[[-10.0,-10.0],[-10.0,10.0],[10.0,10.0],[10.0,-10.0],[-10.0,-10.0]]]]}"; + //String geoJsonPolygon = "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-100,-100],[-100,100],[100,100],[100,-100],[-100,-100]],[[-90,-90],[90,90],[-90,90],[90,-90],[-90,-90]]],[[[-10.0,-10.0],[-10.0,10.0],[10.0,10.0],[10.0,-10.0],[-10.0,-10.0]]]]}"; String esriJsonPolygon = "{\"rings\": [[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[-90, -90], [90, 90], [-90, 90], [90, -90], [-90, -90]], [[-10, -10], [-10, 10], [10, 10], [10, -10], [-10, -10]]]}"; - JsonParser parser = jsonFactory.createJsonParser(esriJsonPolygon); + JsonParser parser = jsonFactory.createParser(esriJsonPolygon); MapGeometry parsedPoly = GeometryEngine.jsonToGeometry(parser); //MapGeometry parsedPoly = GeometryEngine.geometryFromGeoJson(jsonPolygon, 0, Geometry.Type.Polygon); @@ -244,9 +242,8 @@ public void testMultiPolygon() throws IOException { } - @Deprecated @Test - public void testEmptyPolygon() throws JSONException { + public void testEmptyPolygon() { Polygon p = new Polygon(); OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory.getOperator(Operator.Type.ExportToGeoJson); String result = exporter.execute(p); @@ -386,16 +383,6 @@ public void testGeometryCollection() { geoms, sr); String s2 = collection.asGeoJson(); - JSONObject json = null; - boolean valid = false; - try { - json = new JSONObject(s2); - valid = true; - } catch (Exception e) { - } - - assertTrue(valid); - assertEquals("{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"Point\",\"coordinates\":[1,1]},{\"type\":\"LineString\",\"coordinates\":[[1,1],[2,2]]},{\"type\":\"Polygon\",\"coordinates\":[[[1,1],[2,0],[3,1],[2,2],[1,1]]]}],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", collection.asGeoJson()); } @@ -435,7 +422,7 @@ public void testEnvelopeGeometryEngine() { } @Test - public void testOldCRS() throws JSONException { + public void testOldCRS() { String inputStr = "{\"type\":\"Polygon\",\"coordinates\":[[[-180,-90],[180,-90],[180,90],[-180,90],[-180,-90]]], \"crs\":\"EPSG:4267\"}"; MapGeometry mg = OperatorImportFromGeoJson.local().execute(GeoJsonImportFlags.geoJsonImportDefaults, Geometry.Type.Unknown, inputStr, null); String result = GeometryEngine.geometryToGeoJson(mg.getSpatialReference(), mg.getGeometry()); diff --git a/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java b/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java index ce4f81dc..237abb4c 100644 --- a/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java +++ b/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java @@ -1,12 +1,13 @@ package com.esri.core.geometry; import java.io.IOException; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; import junit.framework.TestCase; import org.junit.Test; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; + public class TestGeomToJSonExportSRFromWkiOrWkt_CR181369 extends TestCase { @Override protected void setUp() throws Exception { @@ -43,7 +44,7 @@ boolean testPoint() throws JsonParseException, IOException { Point pointEmpty = new Point(); { JsonParser pointWebMerc1Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( + .createParser(GeometryEngine.geometryToJson( spatialReferenceWebMerc1, point1)); MapGeometry pointWebMerc1MP = GeometryEngine .jsonToGeometry(pointWebMerc1Parser); @@ -59,7 +60,7 @@ boolean testPoint() throws JsonParseException, IOException { bAnswer = false; } - pointWebMerc1Parser = factory.createJsonParser(GeometryEngine + pointWebMerc1Parser = factory.createParser(GeometryEngine .geometryToJson(null, point1)); pointWebMerc1MP = GeometryEngine .jsonToGeometry(pointWebMerc1Parser); @@ -73,11 +74,11 @@ boolean testPoint() throws JsonParseException, IOException { String pointEmptyString = GeometryEngine.geometryToJson( spatialReferenceWebMerc1, pointEmpty); - pointWebMerc1Parser = factory.createJsonParser(pointEmptyString); + pointWebMerc1Parser = factory.createParser(pointEmptyString); } JsonParser pointWebMerc2Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( + .createParser(GeometryEngine.geometryToJson( spatialReferenceWebMerc2, point1)); MapGeometry pointWebMerc2MP = GeometryEngine .jsonToGeometry(pointWebMerc2Parser); @@ -94,7 +95,7 @@ boolean testPoint() throws JsonParseException, IOException { { JsonParser pointWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( + .createParser(GeometryEngine.geometryToJson( spatialReferenceWGS84, point1)); MapGeometry pointWgs84MP = GeometryEngine .jsonToGeometry(pointWgs84Parser); @@ -135,7 +136,7 @@ boolean testPoint() throws JsonParseException, IOException { {// import String s = "{\"x\":0.0,\"y\":1.0,\"z\":5.0,\"m\":11.0,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; - JsonParser parser = factory.createJsonParser(s); + JsonParser parser = factory.createParser(s); MapGeometry map_pt = GeometryEngine.jsonToGeometry(parser); Point pt = (Point) map_pt.getGeometry(); assertTrue(pt.getX() == 0.0); @@ -146,7 +147,7 @@ boolean testPoint() throws JsonParseException, IOException { { String s = "{\"x\" : 5.0, \"y\" : null, \"spatialReference\" : {\"wkid\" : 4326}} "; - JsonParser parser = factory.createJsonParser(s); + JsonParser parser = factory.createParser(s); MapGeometry map_pt = GeometryEngine.jsonToGeometry(parser); Point pt = (Point) map_pt.getGeometry(); assertTrue(pt.isEmpty()); @@ -169,7 +170,7 @@ boolean testMultiPoint() throws JsonParseException, IOException { { String s = GeometryEngine.geometryToJson(spatialReferenceWGS84, multiPoint1); - JsonParser mPointWgs84Parser = factory.createJsonParser(s); + JsonParser mPointWgs84Parser = factory.createParser(s); MapGeometry mPointWgs84MP = GeometryEngine .jsonToGeometry(mPointWgs84Parser); assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP @@ -210,7 +211,7 @@ boolean testMultiPoint() throws JsonParseException, IOException { { String points = "{\"hasM\" : false, \"hasZ\" : true, \"uncle remus\" : null, \"points\" : [ [0,0,1], [0.0,10.0,1], [10.0,10.0,1], [10.0,0.0,1, 6666] ],\"spatialReference\" : {\"wkid\" : 4326}}"; MapGeometry mp = GeometryEngine.jsonToGeometry(factory - .createJsonParser(points)); + .createParser(points)); MultiPoint multipoint = (MultiPoint) mp.getGeometry(); assertTrue(multipoint.getPointCount() == 4); Point2D point2d; @@ -248,7 +249,7 @@ boolean testPolyline() throws JsonParseException, IOException { { JsonParser polylinePathsWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( + .createParser(GeometryEngine.geometryToJson( spatialReferenceWGS84, polyline)); MapGeometry mPolylineWGS84MP = GeometryEngine .jsonToGeometry(polylinePathsWgs84Parser); @@ -307,7 +308,7 @@ boolean testPolyline() throws JsonParseException, IOException { { String paths = "{\"hasZ\" : true, \"paths\" : [ [ [0.0, 0.0,3], [0, 10.0,3], [10.0, 10.0,3, 6666], [10.0, 0.0,3, 6666] ], [ [1.0, 1,3], [1.0, 9.0,3], [9.0, 9.0,3], [1.0, 9.0,3] ] ], \"spatialReference\" : {\"wkid\" : 4326}, \"hasM\" : false}"; MapGeometry mapGeometry = GeometryEngine.jsonToGeometry(factory - .createJsonParser(paths)); + .createParser(paths)); Polyline p = (Polyline) mapGeometry.getGeometry(); assertTrue(p.getPathCount() == 2); @SuppressWarnings("unused") @@ -341,7 +342,7 @@ boolean testPolygon() throws JsonParseException, IOException { { JsonParser polygonPathsWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( + .createParser(GeometryEngine.geometryToJson( spatialReferenceWGS84, polygon)); MapGeometry mPolygonWGS84MP = GeometryEngine .jsonToGeometry(polygonPathsWgs84Parser); @@ -405,7 +406,7 @@ boolean testPolygon() throws JsonParseException, IOException { // Test Import Polygon from Polygon String rings = "{\"hasZ\": true, \"rings\" : [ [ [0,0, 5], [0.0, 10.0, 5], [10.0,10.0, 5, 66666], [10.0,0.0, 5] ], [ [12, 12] ], [ [13 , 17], [13 , 17] ], [ [1.0, 1.0, 5, 66666], [9.0,1.0, 5], [9.0,9.0, 5], [1.0,9.0, 5], [1.0, 1.0, 5] ] ] }"; MapGeometry mapGeometry = GeometryEngine.jsonToGeometry(factory - .createJsonParser(rings)); + .createParser(rings)); Polygon p = (Polygon) mapGeometry.getGeometry(); @SuppressWarnings("unused") double area = p.calculateArea2D(); @@ -429,7 +430,7 @@ boolean testEnvelope() throws JsonParseException, IOException { { JsonParser envelopeWGS84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( + .createParser(GeometryEngine.geometryToJson( spatialReferenceWGS84, envelope)); MapGeometry envelopeWGS84MP = GeometryEngine .jsonToGeometry(envelopeWGS84Parser); @@ -475,7 +476,7 @@ boolean testEnvelope() throws JsonParseException, IOException { {// import String s = "{\"xmin\":0.0,\"ymin\":1.0,\"xmax\":2.0,\"ymax\":3.0,\"zmin\":5.0,\"zmax\":7.0,\"mmin\":11.0,\"mmax\":13.0,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; - JsonParser parser = factory.createJsonParser(s); + JsonParser parser = factory.createParser(s); MapGeometry map_env = GeometryEngine.jsonToGeometry(parser); Envelope env = (Envelope) map_env.getGeometry(); Envelope1D z = env.queryInterval(VertexDescription.Semantics.Z, 0); @@ -488,7 +489,7 @@ boolean testEnvelope() throws JsonParseException, IOException { { String s = "{ \"zmin\" : 33, \"xmin\" : -109.55, \"zmax\" : 53, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94, \"mmax\" : 13}"; - JsonParser parser = factory.createJsonParser(s); + JsonParser parser = factory.createParser(s); MapGeometry map_env = GeometryEngine.jsonToGeometry(parser); Envelope env = (Envelope) map_env.getGeometry(); Envelope2D e = new Envelope2D(); @@ -513,13 +514,13 @@ boolean testCR181369() throws JsonParseException, IOException { String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; JsonParser jsonParserPointAndWKT = factory - .createJsonParser(jsonStringPointAndWKT); + .createParser(jsonStringPointAndWKT); MapGeometry mapGeom2 = GeometryEngine .jsonToGeometry(jsonParserPointAndWKT); String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson( mapGeom2.getSpatialReference(), mapGeom2.getGeometry()); JsonParser jsonParserPointAndWKT2 = factory - .createJsonParser(jsonStringPointAndWKT2); + .createParser(jsonStringPointAndWKT2); MapGeometry mapGeom3 = GeometryEngine .jsonToGeometry(jsonParserPointAndWKT2); assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3 diff --git a/src/test/java/com/esri/core/geometry/TestImportExport.java b/src/test/java/com/esri/core/geometry/TestImportExport.java index 1138c082..5fd97f10 100644 --- a/src/test/java/com/esri/core/geometry/TestImportExport.java +++ b/src/test/java/com/esri/core/geometry/TestImportExport.java @@ -4,8 +4,6 @@ import java.nio.ByteOrder; import junit.framework.TestCase; -import org.json.JSONException; -import org.json.JSONObject; import org.junit.Test; public class TestImportExport extends TestCase { @@ -1228,7 +1226,7 @@ public static void testImportExportWktPoint() { @Deprecated @Test - public static void testImportGeoJsonGeometryCollection() throws JSONException { + public static void testImportGeoJsonGeometryCollection() { OperatorImportFromGeoJson importer = (OperatorImportFromGeoJson) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.ImportFromGeoJson); String geoJsonString; @@ -1305,8 +1303,7 @@ public static void testImportGeoJsonMultiPolygon() throws Exception { assertTrue(polygon.getPathCount() == 5); assertTrue(spatial_reference.getLatestID() == 3857); - JSONObject jsonObject = new JSONObject(geoJsonString); - map_geometry = importerGeoJson.execute(0, Geometry.Type.Unknown, jsonObject, null); + map_geometry = importerGeoJson.execute(0, Geometry.Type.Unknown, geoJsonString, null); polygon = (Polygon) map_geometry.getGeometry(); spatial_reference = map_geometry.getSpatialReference(); assertTrue(polygon != null); diff --git a/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java b/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java index 243f7c26..8abd75cf 100644 --- a/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java +++ b/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java @@ -1,13 +1,14 @@ package com.esri.core.geometry; import java.io.IOException; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; import junit.framework.TestCase; import org.junit.Test; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + public class TestJSonToGeomFromWkiOrWkt_CR177613 extends TestCase { JsonFactory factory = new JsonFactory(); @@ -28,7 +29,7 @@ public void testPolygonWithEmptyWKT_NoWKI() throws JsonParseException, + "[-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], " + "[ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], " + "\"spatialReference\" : {\"wkt\" : \"\"}}"; - JsonParser jsonParserPg = factory.createJsonParser(jsonStringPg); + JsonParser jsonParserPg = factory.createParser(jsonStringPg); jsonParserPg.nextToken(); MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); diff --git a/src/test/java/com/esri/core/geometry/TestJsonParser.java b/src/test/java/com/esri/core/geometry/TestJsonParser.java index a2214e5e..d6593115 100644 --- a/src/test/java/com/esri/core/geometry/TestJsonParser.java +++ b/src/test/java/com/esri/core/geometry/TestJsonParser.java @@ -4,14 +4,14 @@ import java.io.IOException; import java.util.Map; import junit.framework.TestCase; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONObject; import org.junit.Assert; import org.junit.Test; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + public class TestJsonParser extends TestCase { JsonFactory factory = new JsonFactory(); @@ -34,7 +34,7 @@ protected void tearDown() throws Exception { public void test3DPoint() throws JsonParseException, IOException { String jsonString3DPt = "{\"x\" : -118.15, \"y\" : 33.80, \"z\" : 10.0, \"spatialReference\" : {\"wkid\" : 4326}}"; - JsonParser jsonParser3DPt = factory.createJsonParser(jsonString3DPt); + JsonParser jsonParser3DPt = factory.createParser(jsonString3DPt); MapGeometry point3DMP = GeometryEngine.jsonToGeometry(jsonParser3DPt); assertTrue(-118.15 == ((Point) point3DMP.getGeometry()).getX()); assertTrue(33.80 == ((Point) point3DMP.getGeometry()).getY()); diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index 5b2ef6b3..3edf417c 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -11,9 +11,9 @@ import com.esri.core.geometry.ogc.OGCMultiPolygon; import com.esri.core.geometry.ogc.OGCPoint; import com.esri.core.geometry.ogc.OGCPolygon; +import com.fasterxml.jackson.core.JsonParseException; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; -import org.codehaus.jackson.JsonParseException; import org.junit.Test; import java.io.IOException; @@ -850,15 +850,7 @@ public void testMultiPointSinglePoint() { public void testWktMultiPolygon() { String restJson = "{\"rings\": [[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[-90, -90], [90, 90], [-90, 90], [90, -90], [-90, -90]], [[-10, -10], [-10, 10], [10, 10], [10, -10], [-10, -10]]]}"; MapGeometry g = null; - try { - g = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, restJson); - } catch (JsonParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + g = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, restJson); String wkt = OperatorExportToWkt.local().execute(0, g.getGeometry(), null); assertTrue(wkt.equals("MULTIPOLYGON (((-100 -100, 100 -100, 100 100, -100 100, -100 -100), (-90 -90, 90 -90, -90 90, 90 90, -90 -90)), ((-10 -10, 10 -10, 10 10, -10 10, -10 -10)))")); } diff --git a/src/test/java/com/esri/core/geometry/TestPolygon.java b/src/test/java/com/esri/core/geometry/TestPolygon.java index e34a14b7..8b918e9c 100644 --- a/src/test/java/com/esri/core/geometry/TestPolygon.java +++ b/src/test/java/com/esri/core/geometry/TestPolygon.java @@ -4,7 +4,6 @@ import junit.framework.TestCase; -import org.json.JSONException; import org.junit.Test; import com.esri.core.geometry.ogc.OGCGeometry; @@ -1205,7 +1204,7 @@ public void testReplaceNaNs() { } @Test - public void testPolygon2PolygonFails() throws IOException, JSONException { + public void testPolygon2PolygonFails() { OperatorFactoryLocal factory = OperatorFactoryLocal.getInstance(); OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory .getOperator(Operator.Type.ExportToGeoJson); @@ -1221,10 +1220,10 @@ public void testPolygon2PolygonFails() throws IOException, JSONException { } @Test - public void testPolygon2PolygonFails2() throws JSONException { + public void testPolygon2PolygonFails2() { String birminghamGeojson = GeometryEngine .geometryToGeoJson(birmingham()); - MapGeometry returnedGeometry = GeometryEngine.geometryFromGeoJson( + MapGeometry returnedGeometry = GeometryEngine.geoJsonToGeometry( birminghamGeojson, GeoJsonImportFlags.geoJsonImportDefaults, Geometry.Type.Polygon); Polygon polygon = (Polygon) returnedGeometry.getGeometry(); @@ -1232,10 +1231,10 @@ public void testPolygon2PolygonFails2() throws JSONException { } @Test - public void testPolygon2PolygonWorks() throws JSONException { + public void testPolygon2PolygonWorks() { String birminghamGeojson = GeometryEngine .geometryToGeoJson(birmingham()); - MapGeometry returnedGeometry = GeometryEngine.geometryFromGeoJson( + MapGeometry returnedGeometry = GeometryEngine.geoJsonToGeometry( birminghamGeojson, GeoJsonImportFlags.geoJsonImportDefaults, Geometry.Type.Polygon); Polygon polygon = (Polygon) returnedGeometry.getGeometry(); @@ -1243,7 +1242,7 @@ public void testPolygon2PolygonWorks() throws JSONException { } @Test - public void testPolygon2Polygon2Works() throws JSONException, IOException { + public void testPolygon2Polygon2Works() { String birminghamJson = GeometryEngine.geometryToJson(4326, birmingham()); MapGeometry returnedGeometry = GeometryEngine diff --git a/src/test/java/com/esri/core/geometry/TestRelation.java b/src/test/java/com/esri/core/geometry/TestRelation.java index 5c00d8ad..041908cf 100644 --- a/src/test/java/com/esri/core/geometry/TestRelation.java +++ b/src/test/java/com/esri/core/geometry/TestRelation.java @@ -4,7 +4,6 @@ import junit.framework.TestCase; -import org.codehaus.jackson.JsonParseException; import org.junit.Test; import com.esri.core.geometry.Geometry.GeometryAccelerationDegree; @@ -5498,7 +5497,7 @@ public void testDisjointCrash() { } @Test - public void testDisjointFail() throws JsonParseException, IOException { + public void testDisjointFail() { MapGeometry geometry1 = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"paths\":[[[3,3],[3,3]]],\"spatialReference\":{\"wkid\":4326}}"); MapGeometry geometry2 = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"rings\":[[[2,2],[2,4],[4,4],[4,2],[2,2]]],\"spatialReference\":{\"wkid\":4326}}"); OperatorDisjoint.local().accelerateGeometry(geometry1.getGeometry(), geometry1.getSpatialReference(), GeometryAccelerationDegree.enumMedium); diff --git a/src/test/java/com/esri/core/geometry/TestSimplify.java b/src/test/java/com/esri/core/geometry/TestSimplify.java index bdc2be0f..b7380851 100644 --- a/src/test/java/com/esri/core/geometry/TestSimplify.java +++ b/src/test/java/com/esri/core/geometry/TestSimplify.java @@ -9,10 +9,10 @@ import junit.framework.TestCase; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; import org.junit.Test; +import com.fasterxml.jackson.core.JsonFactory; + public class TestSimplify extends TestCase { OperatorFactoryLocal factory = null; OperatorSimplify simplifyOp = null; @@ -1233,18 +1233,16 @@ public void testisSimpleOGC() { } @Test - public void testPolylineIsSimpleForOGC() throws IOException { + public void testPolylineIsSimpleForOGC() { OperatorImportFromJson importerJson = (OperatorImportFromJson) factory .getOperator(Operator.Type.ImportFromJson); OperatorSimplify simplify = (OperatorSimplify) factory .getOperator(Operator.Type.Simplify); - JsonFactory f = new JsonFactory(); - { String s = "{\"paths\":[[[0, 10], [8, 5], [5, 2], [6, 0]]]}"; Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(res); } @@ -1252,7 +1250,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { String s = "{\"paths\":[[[0, 10], [6, 0], [7, 5], [0, 3]]]}";// self // intersection Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(!res); } @@ -1260,7 +1258,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { { String s = "{\"paths\":[[[0, 10], [6, 0], [0, 3], [0, 10]]]}"; // closed Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(res); } @@ -1271,7 +1269,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { // self // tangent Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(!res); } @@ -1284,7 +1282,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { // a // point Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(res); } @@ -1298,7 +1296,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { // one // point Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(!res); } @@ -1308,7 +1306,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { // lines // intersect Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(!res); } @@ -1320,7 +1318,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { // mid // point. Geometry g = importerJson.execute(Geometry.Type.Unknown, - f.createJsonParser(s)).getGeometry(); + JsonParserReader.createFromString(s)).getGeometry(); boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); assertTrue(!res); } @@ -1328,7 +1326,7 @@ public void testPolylineIsSimpleForOGC() throws IOException { } @Test - public void testFillRule() throws JsonParseException, IOException { + public void testFillRule() { //self intersecting star shape MapGeometry mg = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"rings\":[[[0,0], [5,10], [10, 0], [0, 7], [10, 7], [0, 0]]]}"); Polygon poly = (Polygon)mg.getGeometry(); diff --git a/src/test/java/com/esri/core/geometry/TestWKBSupport.java b/src/test/java/com/esri/core/geometry/TestWKBSupport.java index 196e5e1e..0c84d883 100644 --- a/src/test/java/com/esri/core/geometry/TestWKBSupport.java +++ b/src/test/java/com/esri/core/geometry/TestWKBSupport.java @@ -2,9 +2,6 @@ import java.io.IOException; import java.nio.ByteBuffer; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; import junit.framework.TestCase; import org.junit.Test; @@ -23,35 +20,27 @@ protected void tearDown() throws Exception { @Test public void testWKB() { - try { - // JSON -> GEOM -> WKB - - String strPolygon1 = "{\"xmin\":-1.1663479012889031E7,\"ymin\":4919777.494405342,\"xmax\":-1.1658587043078788E7,\"ymax\":4924669.464215587,\"spatialReference\":{\"wkid\":102100}}"; - // String strPolygon1 = - // "{\"rings\":[[[-119.152450421001,38.4118009590513],[-119.318825070203,38.5271086243914],[-119.575687062955,38.7029101298904],[-119.889341639399,38.9222515603984],[-119.995254694357,38.9941061536377],[-119.995150114198,39.0634913594691],[-119.994541258334,39.1061318056708],[-119.995527335641,39.1587132866355],[-119.995304181493,39.3115454332125],[-119.996011479298,39.4435009764511],[-119.996165311172,39.7206108077274],[-119.996324660047,41.1775662656441],[-119.993459369715,41.9892049531992],[-119.351692186077,41.9888529749781],[-119.3109421304,41.9891353872811],[-118.185316829038,41.9966370981387],[-117.018864363596,41.9947941808341],[-116.992313337997,41.9947945094663],[-115.947544658193,41.9945994628997],[-115.024862911148,41.996506455953],[-114.269471632824,41.9959242345073],[-114.039072662345,41.9953908974688],[-114.038151248682,40.9976868405942],[-114.038108189376,40.1110466529553],[-114.039844684228,39.9087788600023],[-114.040105338584,39.5386849268845],[-114.044267501155,38.6789958815881],[-114.045090206153,38.5710950539539],[-114.047272999176,38.1376524399918],[-114.047260595159,37.5984784866001],[-114.043939384154,36.9965379371421],[-114.043716435713,36.8418489458647],[-114.037392074194,36.2160228969702],[-114.045105557286,36.1939778840226],[-114.107775185788,36.1210907070504],[-114.12902308363,36.041730493896],[-114.206768869568,36.0172554164834],[-114.233472615347,36.0183310595897],[-114.307587598189,36.0622330993643],[-114.303857056018,36.0871084040611],[-114.316095374696,36.1114380366653],[-114.344233941709,36.1374802520568],[-114.380803116644,36.1509912717765],[-114.443945697733,36.1210532841897],[-114.466613475422,36.1247112590539],[-114.530573568745,36.1550902046725],[-114.598935242024,36.1383354528834],[-114.621610747198,36.1419666834504],[-114.712761724737,36.1051810523675],[-114.728150311069,36.0859627711604],[-114.728966012834,36.0587530361083],[-114.717673567756,36.0367580437018],[-114.736212493583,35.9876483502758],[-114.699275906446,35.9116119537412],[-114.661600122152,35.8804735854242],[-114.662462095522,35.8709599070091],[-114.689867343369,35.8474424944766],[-114.682739704595,35.7647034175617],[-114.688820027649,35.7325957399896],[-114.665091345861,35.6930994107107],[-114.668486064922,35.6563989882404],[-114.654065925137,35.6465840800053],[-114.6398667219,35.6113485698329],[-114.653134321223,35.5848331056108],[-114.649792053474,35.5466373866597],[-114.672215155693,35.5157541647721],[-114.645396168451,35.4507608261463],[-114.589584275424,35.3583787306827],[-114.587889840369,35.30476812919],[-114.559583045727,35.2201828714608],[-114.561039964054,35.1743461616313],[-114.572255261053,35.1400677445931],[-114.582616239058,35.1325604694085],[-114.626440825485,35.1339067529872],[-114.6359090842,35.1186557767895],[-114.595631971944,35.0760579746697],[-114.633779872695,35.0418633504303],[-114.621068606189,34.9989144286133],[-115.626197382816,35.7956983148418],[-115.88576934392,36.0012259572723],[-117.160423771838,36.9595941441767],[-117.838686423167,37.457298239715],[-118.417419755966,37.8866767486211],[-119.152450421001,38.4118009590513]]], \"spatialReference\":{\"wkid\":4326}}"; - - JsonFactory factory = new JsonFactory(); - JsonParser parser = factory.createJsonParser(strPolygon1); - parser.nextToken(); - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(parser); - Geometry geom = mapGeom.getGeometry(); - OperatorExportToWkb operatorExport = (OperatorExportToWkb) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ExportToWkb); - ByteBuffer byteBuffer = operatorExport.execute(0, geom, null); - byte[] wkb = byteBuffer.array(); - - // WKB -> GEOM -> JSON - OperatorImportFromWkb operatorImport = (OperatorImportFromWkb) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ImportFromWkb); - geom = operatorImport.execute(0, Geometry.Type.Polygon, - ByteBuffer.wrap(wkb), null); - // geom = operatorImport.execute(0, Geometry.Type.Polygon, - // byteBuffer); - String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom); - } catch (JsonParseException ex) { - } catch (IOException ex) { - } - + // JSON -> GEOM -> WKB + + String strPolygon1 = "{\"xmin\":-1.1663479012889031E7,\"ymin\":4919777.494405342,\"xmax\":-1.1658587043078788E7,\"ymax\":4924669.464215587,\"spatialReference\":{\"wkid\":102100}}"; + // String strPolygon1 = + // "{\"rings\":[[[-119.152450421001,38.4118009590513],[-119.318825070203,38.5271086243914],[-119.575687062955,38.7029101298904],[-119.889341639399,38.9222515603984],[-119.995254694357,38.9941061536377],[-119.995150114198,39.0634913594691],[-119.994541258334,39.1061318056708],[-119.995527335641,39.1587132866355],[-119.995304181493,39.3115454332125],[-119.996011479298,39.4435009764511],[-119.996165311172,39.7206108077274],[-119.996324660047,41.1775662656441],[-119.993459369715,41.9892049531992],[-119.351692186077,41.9888529749781],[-119.3109421304,41.9891353872811],[-118.185316829038,41.9966370981387],[-117.018864363596,41.9947941808341],[-116.992313337997,41.9947945094663],[-115.947544658193,41.9945994628997],[-115.024862911148,41.996506455953],[-114.269471632824,41.9959242345073],[-114.039072662345,41.9953908974688],[-114.038151248682,40.9976868405942],[-114.038108189376,40.1110466529553],[-114.039844684228,39.9087788600023],[-114.040105338584,39.5386849268845],[-114.044267501155,38.6789958815881],[-114.045090206153,38.5710950539539],[-114.047272999176,38.1376524399918],[-114.047260595159,37.5984784866001],[-114.043939384154,36.9965379371421],[-114.043716435713,36.8418489458647],[-114.037392074194,36.2160228969702],[-114.045105557286,36.1939778840226],[-114.107775185788,36.1210907070504],[-114.12902308363,36.041730493896],[-114.206768869568,36.0172554164834],[-114.233472615347,36.0183310595897],[-114.307587598189,36.0622330993643],[-114.303857056018,36.0871084040611],[-114.316095374696,36.1114380366653],[-114.344233941709,36.1374802520568],[-114.380803116644,36.1509912717765],[-114.443945697733,36.1210532841897],[-114.466613475422,36.1247112590539],[-114.530573568745,36.1550902046725],[-114.598935242024,36.1383354528834],[-114.621610747198,36.1419666834504],[-114.712761724737,36.1051810523675],[-114.728150311069,36.0859627711604],[-114.728966012834,36.0587530361083],[-114.717673567756,36.0367580437018],[-114.736212493583,35.9876483502758],[-114.699275906446,35.9116119537412],[-114.661600122152,35.8804735854242],[-114.662462095522,35.8709599070091],[-114.689867343369,35.8474424944766],[-114.682739704595,35.7647034175617],[-114.688820027649,35.7325957399896],[-114.665091345861,35.6930994107107],[-114.668486064922,35.6563989882404],[-114.654065925137,35.6465840800053],[-114.6398667219,35.6113485698329],[-114.653134321223,35.5848331056108],[-114.649792053474,35.5466373866597],[-114.672215155693,35.5157541647721],[-114.645396168451,35.4507608261463],[-114.589584275424,35.3583787306827],[-114.587889840369,35.30476812919],[-114.559583045727,35.2201828714608],[-114.561039964054,35.1743461616313],[-114.572255261053,35.1400677445931],[-114.582616239058,35.1325604694085],[-114.626440825485,35.1339067529872],[-114.6359090842,35.1186557767895],[-114.595631971944,35.0760579746697],[-114.633779872695,35.0418633504303],[-114.621068606189,34.9989144286133],[-115.626197382816,35.7956983148418],[-115.88576934392,36.0012259572723],[-117.160423771838,36.9595941441767],[-117.838686423167,37.457298239715],[-118.417419755966,37.8866767486211],[-119.152450421001,38.4118009590513]]], \"spatialReference\":{\"wkid\":4326}}"; + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(strPolygon1); + Geometry geom = mapGeom.getGeometry(); + OperatorExportToWkb operatorExport = (OperatorExportToWkb) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.ExportToWkb); + ByteBuffer byteBuffer = operatorExport.execute(0, geom, null); + byte[] wkb = byteBuffer.array(); + + // WKB -> GEOM -> JSON + OperatorImportFromWkb operatorImport = (OperatorImportFromWkb) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.ImportFromWkb); + geom = operatorImport.execute(0, Geometry.Type.Polygon, + ByteBuffer.wrap(wkb), null); + // geom = operatorImport.execute(0, Geometry.Type.Polygon, + // byteBuffer); + String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom); } @Test @@ -62,10 +51,7 @@ public void testWKB2() throws Exception { // "{\"xmin\":-1.16605115291E7,\"ymin\":4925189.941699997,\"xmax\":-1.16567772126E7,\"ymax\":4928658.771399997,\"spatialReference\":{\"wkid\":102100}}"; String strPolygon1 = "{\"rings\" : [ [ [-1.16605115291E7,4925189.941699997], [-1.16567772126E7,4925189.941699997], [-1.16567772126E7,4928658.771399997], [-1.16605115291E7,4928658.771399997], [-1.16605115291E7,4925189.941699997] ] ], \"spatialReference\" : {\"wkid\" : 102100}}"; - JsonFactory factory = new JsonFactory(); - JsonParser parser = factory.createJsonParser(strPolygon1); - parser.nextToken(); - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(parser); + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(strPolygon1); Geometry geom = mapGeom.getGeometry(); // simplifying geom From d6999a9d0bfff7113f331ced7165ab46cf341881 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Fri, 7 Jul 2017 14:27:29 -0700 Subject: [PATCH 02/75] Sergey/gitattribs (#137) --- .gitattributes | 9 + .../esri/core/geometry/GeometryEngine.java | 1823 +++++------ .../java/com/esri/core/geometry/TestCut.java | 1040 +++---- .../com/esri/core/geometry/TestFailed.java | 128 +- .../com/esri/core/geometry/TestGeodetic.java | 209 +- ...omToJSonExportSRFromWkiOrWkt_CR181369.java | 1130 +++---- .../esri/core/geometry/TestJSonGeometry.java | 95 +- .../TestJSonToGeomFromWkiOrWkt_CR177613.java | 248 +- .../esri/core/geometry/TestJsonParser.java | 1328 ++++---- .../esri/core/geometry/TestSerialization.java | 760 ++--- .../com/esri/core/geometry/TestSimplify.java | 2688 ++++++++--------- .../esri/core/geometry/TestWKBSupport.java | 171 +- 12 files changed, 4821 insertions(+), 4808 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..e1945df3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +* text=auto +*.java text +*.xml text + +# +# Binary specific files +# +resouces/* binary +*.jar binary diff --git a/src/main/java/com/esri/core/geometry/GeometryEngine.java b/src/main/java/com/esri/core/geometry/GeometryEngine.java index 1339538c..6f729cea 100644 --- a/src/main/java/com/esri/core/geometry/GeometryEngine.java +++ b/src/main/java/com/esri/core/geometry/GeometryEngine.java @@ -1,911 +1,912 @@ -/* - Copyright 1995-2017 Esri - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - - email: contracts@esri.com - */ - -package com.esri.core.geometry; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; - -import com.fasterxml.jackson.core.JsonParser; - -/** - * Provides services that operate on geometry instances. The methods of GeometryEngine class call corresponding OperatorXXX classes. - * Consider using OperatorXXX classes directly as they often provide more functionality and better performance. For example, some Operators accept - * GeometryCursor class that could be implemented to wrap a feature cursor and make it feed geometries directly into an Operator. - * Also, some operators provide a way to accelerate an operation by using Operator.accelerateGeometry method. - */ -public class GeometryEngine { - - private static OperatorFactoryLocal factory = OperatorFactoryLocal - .getInstance(); - - /** - * Imports the MapGeometry from its JSON representation. M and Z values are - * not imported from JSON representation. - * - * See OperatorImportFromJson. - * - * @param json - * The JSON representation of the geometry (with spatial - * reference). - * @return The MapGeometry instance containing the imported geometry and its - * spatial reference. - */ - public static MapGeometry jsonToGeometry(JsonParser json) { - MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, new JsonParserReader(json)); - return geom; - } - - /** - * Imports the MapGeometry from its JSON representation. M and Z values are - * not imported from JSON representation. - * - * See OperatorImportFromJson. - * - * @param json - * The JSON representation of the geometry (with spatial - * reference). - * @return The MapGeometry instance containing the imported geometry and its - * spatial reference. - */ - public static MapGeometry jsonToGeometry(JsonReader json) { - MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); - return geom; - } - - /** - * Imports the MapGeometry from its JSON representation. M and Z values are - * not imported from JSON representation. - * - * See OperatorImportFromJson. - * - * @param json - * The JSON representation of the geometry (with spatial - * reference). - * @return The MapGeometry instance containing the imported geometry and its - * spatial reference. - * @throws IOException - * @throws JsonParseException - */ - public static MapGeometry jsonToGeometry(String json) { - MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); - return geom; - } - - /** - * Exports the specified geometry instance to it's JSON representation. - * - * See OperatorExportToJson. - * - * @see GeometryEngine#geometryToJson(SpatialReference spatialiReference, - * Geometry geometry) - * @param wkid - * The spatial reference Well Known ID to be used for the JSON - * representation. - * @param geometry - * The geometry to be exported to JSON. - * @return The JSON representation of the specified Geometry. - */ - public static String geometryToJson(int wkid, Geometry geometry) { - return GeometryEngine.geometryToJson( - wkid > 0 ? SpatialReference.create(wkid) : null, geometry); - } - - /** - * Exports the specified geometry instance to it's JSON representation. M - * and Z values are not imported from JSON representation. - * - * See OperatorExportToJson. - * - * @param spatialReference - * The spatial reference of associated object. - * @param geometry - * The geometry. - * @return The JSON representation of the specified geometry. - */ - public static String geometryToJson(SpatialReference spatialReference, - Geometry geometry) { - OperatorExportToJson exporter = (OperatorExportToJson) factory - .getOperator(Operator.Type.ExportToJson); - - return exporter.execute(spatialReference, geometry); - } - - public static String geometryToGeoJson(Geometry geometry) { - OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory - .getOperator(Operator.Type.ExportToGeoJson); - - return exporter.execute(geometry); - } - - /** - * Imports the MapGeometry from its JSON representation. M and Z values are - * not imported from JSON representation. - * - * See OperatorImportFromJson. - * - * @param json - * The JSON representation of the geometry (with spatial - * reference). - * @return The MapGeometry instance containing the imported geometry and its - * spatial reference. - * @throws IOException - * @throws JsonParseException - */ - public static MapGeometry geoJsonToGeometry(String json, int importFlags, Geometry.Type type) { - MapGeometry geom = OperatorImportFromGeoJson.local().execute(importFlags, type, json, null); - return geom; - } - - /** - * Exports the specified geometry instance to its GeoJSON representation. - * - * See OperatorExportToGeoJson. - * - * @see GeometryEngine#geometryToGeoJson(SpatialReference spatialReference, - * Geometry geometry) - * - * @param wkid - * The spatial reference Well Known ID to be used for the GeoJSON - * representation. - * @param geometry - * The geometry to be exported to GeoJSON. - * @return The GeoJSON representation of the specified geometry. - */ - public static String geometryToGeoJson(int wkid, Geometry geometry) { - return GeometryEngine.geometryToGeoJson(wkid > 0 ? SpatialReference.create(wkid) : null, geometry); - } - - /** - * Exports the specified geometry instance to it's JSON representation. - * - * See OperatorImportFromGeoJson. - * - * @param spatialReference - * The spatial reference of associated object. - * @param geometry - * The geometry. - * @return The GeoJSON representation of the specified geometry. - */ - public static String geometryToGeoJson(SpatialReference spatialReference, Geometry geometry) { - OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory.getOperator(Operator.Type.ExportToGeoJson); - - return exporter.execute(spatialReference, geometry); - } - - /** - * Imports geometry from the ESRI shape file format. - * - * See OperatorImportFromESRIShape. - * - * @param esriShapeBuffer - * The buffer containing geometry in the ESRI shape file format. - * @param geometryType - * The required type of the Geometry to be imported. Use - * Geometry.Type.Unknown if the geometry type needs to be - * determined from the buffer content. - * @return The geometry or null if the buffer contains null shape. - * @throws GeometryException - * when the geometryType is not Geometry.Type.Unknown and the - * buffer contains geometry that cannot be converted to the - * given geometryType. or the buffer is corrupt. Another - * exception possible is IllegalArgumentsException. - */ - public static Geometry geometryFromEsriShape(byte[] esriShapeBuffer, - Geometry.Type geometryType) { - OperatorImportFromESRIShape op = (OperatorImportFromESRIShape) factory - .getOperator(Operator.Type.ImportFromESRIShape); - return op - .execute( - ShapeImportFlags.ShapeImportNonTrusted, - geometryType, - ByteBuffer.wrap(esriShapeBuffer).order( - ByteOrder.LITTLE_ENDIAN)); - } - - /** - * Exports geometry to the ESRI shape file format. - * - * See OperatorExportToESRIShape. - * - * @param geometry - * The geometry to export. (null value is not allowed) - * @return Array containing the exported ESRI shape file. - */ - public static byte[] geometryToEsriShape(Geometry geometry) { - if (geometry == null) - throw new IllegalArgumentException(); - OperatorExportToESRIShape op = (OperatorExportToESRIShape) factory - .getOperator(Operator.Type.ExportToESRIShape); - return op.execute(0, geometry).array(); - } - - /** - * Imports a geometry from a WKT string. - * - * See OperatorImportFromWkt. - * - * @param wkt The string containing the geometry in WKT format. - * @param importFlags Use the {@link WktImportFlags} interface. - * @param geometryType The required type of the Geometry to be imported. Use Geometry.Type.Unknown if the geometry type needs to be determined from the WKT context. - * @return The geometry. - * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the WKT contains a geometry that cannot be converted to the given geometryType. - * @throws IllegalArgument exception if an error is found while parsing the WKT string. - */ - public static Geometry geometryFromWkt(String wkt, int importFlags, - Geometry.Type geometryType) { - OperatorImportFromWkt op = (OperatorImportFromWkt) factory - .getOperator(Operator.Type.ImportFromWkt); - return op.execute(importFlags, geometryType, wkt, null); - } - - /** - * Exports a geometry to a string in WKT format. - * - * See OperatorExportToWkt. - * - * @param geometry The geometry to export. (null value is not allowed) - * @param exportFlags Use the {@link WktExportFlags} interface. - * @return A String containing the exported geometry in WKT format. - */ - public static String geometryToWkt(Geometry geometry, int exportFlags) { - OperatorExportToWkt op = (OperatorExportToWkt) factory - .getOperator(Operator.Type.ExportToWkt); - return op.execute(exportFlags, geometry, null); - } - - /** - * Constructs a new geometry by union an array of geometries. All inputs - * must be of the same type of geometries and share one spatial reference. - * - * See OperatorUnion. - * - * @param geometries - * The geometries to union. - * @param spatialReference - * The spatial reference of the geometries. - * @return The geometry object representing the resultant union. - */ - public static Geometry union(Geometry[] geometries, - SpatialReference spatialReference) { - OperatorUnion op = (OperatorUnion) factory - .getOperator(Operator.Type.Union); - - SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor( - geometries); - GeometryCursor result = op.execute(inputGeometries, spatialReference, - null); - return result.next(); - } - - /** - * Creates the difference of two geometries. The dimension of geometry2 has - * to be equal to or greater than that of geometry1. - * - * See OperatorDifference. - * - * @param geometry1 - * The geometry being subtracted. - * @param substractor - * The geometry object to subtract from. - * @param spatialReference - * The spatial reference of the geometries. - * @return The geometry of the differences. - */ - public static Geometry difference(Geometry geometry1, Geometry substractor, - SpatialReference spatialReference) { - OperatorDifference op = (OperatorDifference) factory - .getOperator(Operator.Type.Difference); - Geometry result = op.execute(geometry1, substractor, spatialReference, - null); - return result; - } - - /** - * Creates the symmetric difference of two geometries. - * - * See OperatorSymmetricDifference. - * - * @param leftGeometry - * is one of the Geometry instances in the XOR operation. - * @param rightGeometry - * is one of the Geometry instances in the XOR operation. - * @param spatialReference - * The spatial reference of the geometries. - * @return Returns the result of the symmetric difference. - */ - public static Geometry symmetricDifference(Geometry leftGeometry, - Geometry rightGeometry, SpatialReference spatialReference) { - OperatorSymmetricDifference op = (OperatorSymmetricDifference) factory - .getOperator(Operator.Type.SymmetricDifference); - Geometry result = op.execute(leftGeometry, rightGeometry, - spatialReference, null); - return result; - } - - /** - * Indicates if two geometries are equal. - * - * See OperatorEquals. - * - * @param geometry1 - * Geometry. - * @param geometry2 - * Geometry. - * @param spatialReference - * The spatial reference of the geometries. - * @return TRUE if both geometry objects are equal. - */ - public static boolean equals(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorEquals op = (OperatorEquals) factory - .getOperator(Operator.Type.Equals); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * See OperatorDisjoint. - * - */ - public static boolean disjoint(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorDisjoint op = (OperatorDisjoint) factory - .getOperator(Operator.Type.Disjoint); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * Constructs the set-theoretic intersection between an array of geometries - * and another geometry. - * - * See OperatorIntersection (also for dimension specific intersection). - * - * @param inputGeometries - * An array of geometry objects. - * @param geometry - * The geometry object. - * @return Any array of geometry objects showing the intersection. - */ - static Geometry[] intersect(Geometry[] inputGeometries, Geometry geometry, - SpatialReference spatialReference) { - OperatorIntersection op = (OperatorIntersection) factory - .getOperator(Operator.Type.Intersection); - SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor( - inputGeometries); - SimpleGeometryCursor intersectorCursor = new SimpleGeometryCursor( - geometry); - GeometryCursor result = op.execute(inputGeometriesCursor, - intersectorCursor, spatialReference, null); - - ArrayList resultGeoms = new ArrayList(); - Geometry g; - while ((g = result.next()) != null) { - resultGeoms.add(g); - } - - Geometry[] resultarr = resultGeoms.toArray(new Geometry[0]); - return resultarr; - } - - /** - * Creates a geometry through intersection between two geometries. - * - * See OperatorIntersection. - * - * @param geometry1 - * The first geometry. - * @param intersector - * The geometry to intersect the first geometry. - * @param spatialReference - * The spatial reference of the geometries. - * @return The geometry created through intersection. - */ - public static Geometry intersect(Geometry geometry1, Geometry intersector, - SpatialReference spatialReference) { - OperatorIntersection op = (OperatorIntersection) factory - .getOperator(Operator.Type.Intersection); - Geometry result = op.execute(geometry1, intersector, spatialReference, - null); - return result; - } - - /** - * Indicates if one geometry is within another geometry. - * - * See OperatorWithin. - * - * @param geometry1 - * The base geometry that is tested for within relationship to - * the other geometry. - * @param geometry2 - * The comparison geometry that is tested for the contains - * relationship to the other geometry. - * @param spatialReference - * The spatial reference of the geometries. - * @return TRUE if the first geometry is within the other geometry. - */ - public static boolean within(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorWithin op = (OperatorWithin) factory - .getOperator(Operator.Type.Within); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * Indicates if one geometry contains another geometry. - * - * See OperatorContains. - * - * @param geometry1 - * The geometry that is tested for the contains relationship to - * the other geometry.. - * @param geometry2 - * The geometry that is tested for within relationship to the - * other geometry. - * @param spatialReference - * The spatial reference of the geometries. - * @return TRUE if geometry1 contains geometry2. - */ - public static boolean contains(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorContains op = (OperatorContains) factory - .getOperator(Operator.Type.Contains); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * Indicates if one geometry crosses another geometry. - * - * See OperatorCrosses. - * - * @param geometry1 - * The geometry to cross. - * @param geometry2 - * The geometry being crossed. - * @param spatialReference - * The spatial reference of the geometries. - * @return TRUE if geometry1 crosses geometry2. - */ - public static boolean crosses(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorCrosses op = (OperatorCrosses) factory - .getOperator(Operator.Type.Crosses); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * Indicates if one geometry touches another geometry. - * - * See OperatorTouches. - * - * @param geometry1 - * The geometry to touch. - * @param geometry2 - * The geometry to be touched. - * @param spatialReference - * The spatial reference of the geometries. - * @return TRUE if geometry1 touches geometry2. - */ - public static boolean touches(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorTouches op = (OperatorTouches) factory - .getOperator(Operator.Type.Touches); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * Indicates if one geometry overlaps another geometry. - * - * See OperatorOverlaps. - * - * @param geometry1 - * The geometry to overlap. - * @param geometry2 - * The geometry to be overlapped. - * @param spatialReference - * The spatial reference of the geometries. - * @return TRUE if geometry1 overlaps geometry2. - */ - public static boolean overlaps(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorOverlaps op = (OperatorOverlaps) factory - .getOperator(Operator.Type.Overlaps); - boolean result = op.execute(geometry1, geometry2, spatialReference, - null); - return result; - } - - /** - * Indicates if the given relation holds for the two geometries. - * - * See OperatorRelate. - * - * @param geometry1 - * The first geometry for the relation. - * @param geometry2 - * The second geometry for the relation. - * @param spatialReference - * The spatial reference of the geometries. - * @param relation - * The DE-9IM relation. - * @return TRUE if the given relation holds between geometry1 and geometry2. - */ - public static boolean relate(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference, String relation) { - OperatorRelate op = (OperatorRelate) factory - .getOperator(Operator.Type.Relate); - boolean result = op.execute(geometry1, geometry2, spatialReference, - relation, null); - return result; - } - - /** - * Calculates the 2D planar distance between two geometries. - * - * See OperatorDistance. - * - * @param geometry1 - * Geometry. - * @param geometry2 - * Geometry. - * @param spatialReference - * The spatial reference of the geometries. This parameter is not - * used and can be null. - * @return The distance between the two geometries. - */ - public static double distance(Geometry geometry1, Geometry geometry2, - SpatialReference spatialReference) { - OperatorDistance op = (OperatorDistance) factory - .getOperator(Operator.Type.Distance); - double result = op.execute(geometry1, geometry2, null); - return result; - } - - /** - * Calculates the clipped geometry from a target geometry using an envelope. - * - * See OperatorClip. - * - * @param geometry - * The geometry to be clipped. - * @param envelope - * The envelope used to clip. - * @param spatialReference - * The spatial reference of the geometries. - * @return The geometry created by clipping. - */ - public static Geometry clip(Geometry geometry, Envelope envelope, - SpatialReference spatialReference) { - OperatorClip op = (OperatorClip) factory - .getOperator(Operator.Type.Clip); - Geometry result = op.execute(geometry, Envelope2D.construct( - envelope.getXMin(), envelope.getYMin(), envelope.getXMax(), - envelope.getYMax()), spatialReference, null); - return result; - } - - /** - * Calculates the cut geometry from a target geometry using a polyline. For - * Polylines, all left cuts will be grouped together in the first Geometry, - * Right cuts and coincident cuts are grouped in the second Geometry, and - * each undefined cut, along with any uncut parts, are output as separate - * Polylines. For Polygons, all left cuts are grouped in the first Polygon, - * all right cuts are in the second Polygon, and each undefined cut, along - * with any left-over parts after cutting, are output as a separate Polygon. - * If there were no cuts then the array will be empty. An undefined cut will - * only be produced if a left cut or right cut was produced, and there was a - * part left over after cutting or a cut is bounded to the left and right of - * the cutter. - * - * See OperatorCut. - * - * @param cuttee - * The geometry to be cut. - * @param cutter - * The polyline to cut the geometry. - * @param spatialReference - * The spatial reference of the geometries. - * @return An array of geometries created from cutting. - */ - public static Geometry[] cut(Geometry cuttee, Polyline cutter, - SpatialReference spatialReference) { - if (cuttee == null || cutter == null) - return null; - - OperatorCut op = (OperatorCut) factory.getOperator(Operator.Type.Cut); - GeometryCursor cursor = op.execute(true, cuttee, cutter, - spatialReference, null); - ArrayList cutsList = new ArrayList(); - - Geometry geometry; - while ((geometry = cursor.next()) != null) { - if (!geometry.isEmpty()) { - cutsList.add(geometry); - } - } - - return cutsList.toArray(new Geometry[0]); - } - /** - * Calculates a buffer polygon for each geometry at each of the - * corresponding specified distances. It is assumed that all geometries have - * the same spatial reference. There is an option to union the - * returned geometries. - * - * See OperatorBuffer. - * - * @param geometries An array of geometries to be buffered. - * @param spatialReference The spatial reference of the geometries. - * @param distances The corresponding distances for the input geometries to be buffered. - * @param toUnionResults TRUE if all geometries buffered at a given distance are to be unioned into a single polygon. - * @return The buffer of the geometries. - */ - public static Polygon[] buffer(Geometry[] geometries, - SpatialReference spatialReference, double[] distances, - boolean toUnionResults) { - // initially assume distances are in unit of spatial reference - double[] bufferDistances = distances; - - OperatorBuffer op = (OperatorBuffer) factory - .getOperator(Operator.Type.Buffer); - - if (toUnionResults) { - SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor( - geometries); - GeometryCursor result = op.execute(inputGeometriesCursor, - spatialReference, bufferDistances, toUnionResults, null); - - ArrayList resultGeoms = new ArrayList(); - Geometry g; - while ((g = result.next()) != null) { - resultGeoms.add((Polygon) g); - } - Polygon[] buffers = resultGeoms.toArray(new Polygon[0]); - return buffers; - } else { - Polygon[] buffers = new Polygon[geometries.length]; - for (int i = 0; i < geometries.length; i++) { - buffers[i] = (Polygon) op.execute(geometries[i], - spatialReference, bufferDistances[i], null); - } - return buffers; - } - } - - /** - * Calculates a buffer polygon of the geometry as specified by the - * distance input. The buffer is implemented in the xy-plane. - * - * See OperatorBuffer - * - * @param geometry Geometry to be buffered. - * @param spatialReference The spatial reference of the geometry. - * @param distance The specified distance for buffer. Same units as the spatial reference. - * @return The buffer polygon at the specified distances. - */ - public static Polygon buffer(Geometry geometry, - SpatialReference spatialReference, double distance) { - double bufferDistance = distance; - - OperatorBuffer op = (OperatorBuffer) factory - .getOperator(Operator.Type.Buffer); - Geometry result = op.execute(geometry, spatialReference, - bufferDistance, null); - return (Polygon) result; - } - - /** - * Calculates the convex hull geometry. - * - * See OperatorConvexHull. - * - * @param geometry The input geometry. - * @return Returns the convex hull. - * - * For a Point - returns the same point. For an Envelope - - * returns the same envelope. For a MultiPoint - If the point - * count is one, returns the same multipoint. If the point count - * is two, returns a polyline of the points. Otherwise computes - * and returns the convex hull polygon. For a Segment - returns a - * polyline consisting of the segment. For a Polyline - If - * consists of only one segment, returns the same polyline. - * Otherwise computes and returns the convex hull polygon. For a - * Polygon - If more than one path, or if the path isn't already - * convex, computes and returns the convex hull polygon. - * Otherwise returns the same polygon. - */ - public static Geometry convexHull(Geometry geometry) { - OperatorConvexHull op = (OperatorConvexHull) factory - .getOperator(Operator.Type.ConvexHull); - return op.execute(geometry, null); - } - - /** - * Calculates the convex hull. - * - * See OperatorConvexHull - * - * @param geometries - * The input geometry array. - * @param b_merge - * Put true if you want the convex hull of all the geometries in - * the array combined. Put false if you want the convex hull of - * each geometry in the array individually. - * @return Returns an array of convex hulls. If b_merge is true, the result - * will be a one element array consisting of the merged convex hull. - */ - public static Geometry[] convexHull(Geometry[] geometries, boolean b_merge) { - OperatorConvexHull op = (OperatorConvexHull) factory - .getOperator(Operator.Type.ConvexHull); - SimpleGeometryCursor simple_cursor = new SimpleGeometryCursor( - geometries); - GeometryCursor cursor = op.execute(simple_cursor, b_merge, null); - - ArrayList resultGeoms = new ArrayList(); - Geometry g; - while ((g = cursor.next()) != null) { - resultGeoms.add(g); - } - - Geometry[] output = new Geometry[resultGeoms.size()]; - - for (int i = 0; i < resultGeoms.size(); i++) - output[i] = resultGeoms.get(i); - - return output; - } - - /** - * Finds the coordinate of the geometry which is closest to the specified - * point. - * - * See OperatorProximity2D. - * - * @param inputPoint - * The point to find the nearest coordinate in the geometry for. - * @param geometry - * The geometry to consider. - * @return Proximity2DResult containing the nearest coordinate. - */ - public static Proximity2DResult getNearestCoordinate(Geometry geometry, - Point inputPoint, boolean bTestPolygonInterior) { - - OperatorProximity2D proximity = (OperatorProximity2D) factory - .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D); - Proximity2DResult result = proximity.getNearestCoordinate(geometry, - inputPoint, bTestPolygonInterior); - return result; - } - - /** - * Finds nearest vertex on the geometry which is closed to the specified - * point. - * - * See OperatorProximity2D. - * - * @param inputPoint - * The point to find the nearest vertex of the geometry for. - * @param geometry - * The geometry to consider. - * @return Proximity2DResult containing the nearest vertex. - */ - public static Proximity2DResult getNearestVertex(Geometry geometry, - Point inputPoint) { - OperatorProximity2D proximity = (OperatorProximity2D) factory - .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D); - Proximity2DResult result = proximity.getNearestVertex(geometry, - inputPoint); - return result; - } - - /** - * Finds all vertices in the given distance from the specified point, sorted - * from the closest to the furthest. - * - * See OperatorProximity2D. - * - * @param inputPoint - * The point to start from. - * @param geometry - * The geometry to consider. - * @param searchRadius - * The search radius. - * @param maxVertexCountToReturn - * The maximum number number of vertices to return. - * @return Proximity2DResult containing the array of nearest vertices. - */ - public static Proximity2DResult[] getNearestVertices(Geometry geometry, - Point inputPoint, double searchRadius, int maxVertexCountToReturn) { - OperatorProximity2D proximity = (OperatorProximity2D) factory - .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D); - - Proximity2DResult[] results = proximity.getNearestVertices(geometry, - inputPoint, searchRadius, maxVertexCountToReturn); - - return results; - } - - /** - * Performs the simplify operation on the geometry. - * - * See OperatorSimplify and See OperatorSimplifyOGC. - * - * @param geometry - * The geometry to be simplified. - * @param spatialReference - * The spatial reference of the geometry to be simplified. - * @return The simplified geometry. - */ - public static Geometry simplify(Geometry geometry, - SpatialReference spatialReference) { - OperatorSimplify op = (OperatorSimplify) factory - .getOperator(Operator.Type.Simplify); - Geometry result = op.execute(geometry, spatialReference, false, null); - return result; - } - - /** - * Checks if the Geometry is simple. - * - * See OperatorSimplify. - * - * @param geometry - * The geometry to be checked. - * @param spatialReference - * The spatial reference of the geometry. - * @return TRUE if the geometry is simple. - */ - static boolean isSimple(Geometry geometry, SpatialReference spatialReference) { - OperatorSimplify op = (OperatorSimplify) factory - .getOperator(Operator.Type.Simplify); - boolean result = op.isSimpleAsFeature(geometry, spatialReference, null); - return result; - } - - /** - * A geodesic distance is the shortest distance between any two points on the earth's surface when the earth's - * surface is approximated by a spheroid. The function returns the shortest distance between two points on the - * WGS84 spheroid. - * @param ptFrom The "from" point: long, lat in degrees. - * @param ptTo The "to" point: long, lat in degrees. - * @return The geodesic distance between two points in meters. - */ - public static double geodesicDistanceOnWGS84(Point ptFrom, Point ptTo) { - return SpatialReferenceImpl.geodesicDistanceOnWGS84Impl(ptFrom, ptTo); - } -} +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + +package com.esri.core.geometry; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import com.fasterxml.jackson.core.JsonParser; + +/** + * Provides services that operate on geometry instances. The methods of GeometryEngine class call corresponding OperatorXXX classes. + * Consider using OperatorXXX classes directly as they often provide more functionality and better performance. For example, some Operators accept + * GeometryCursor class that could be implemented to wrap a feature cursor and make it feed geometries directly into an Operator. + * Also, some operators provide a way to accelerate an operation by using Operator.accelerateGeometry method. + */ +public class GeometryEngine { + + private static OperatorFactoryLocal factory = OperatorFactoryLocal + .getInstance(); + + + /** + * Imports the MapGeometry from its JSON representation. M and Z values are + * not imported from JSON representation. + * + * See OperatorImportFromJson. + * + * @param json + * The JSON representation of the geometry (with spatial + * reference). + * @return The MapGeometry instance containing the imported geometry and its + * spatial reference. + */ + public static MapGeometry jsonToGeometry(JsonParser json) { + MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, new JsonParserReader(json)); + return geom; + } + + /** + * Imports the MapGeometry from its JSON representation. M and Z values are + * not imported from JSON representation. + * + * See OperatorImportFromJson. + * + * @param json + * The JSON representation of the geometry (with spatial + * reference). + * @return The MapGeometry instance containing the imported geometry and its + * spatial reference. + */ + public static MapGeometry jsonToGeometry(JsonReader json) { + MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); + return geom; + } + + /** + * Imports the MapGeometry from its JSON representation. M and Z values are + * not imported from JSON representation. + * + * See OperatorImportFromJson. + * + * @param json + * The JSON representation of the geometry (with spatial + * reference). + * @return The MapGeometry instance containing the imported geometry and its + * spatial reference. + * @throws IOException + * @throws JsonParseException + */ + public static MapGeometry jsonToGeometry(String json) { + MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); + return geom; + } + + /** + * Exports the specified geometry instance to it's JSON representation. + * + * See OperatorExportToJson. + * + * @see GeometryEngine#geometryToJson(SpatialReference spatialiReference, + * Geometry geometry) + * @param wkid + * The spatial reference Well Known ID to be used for the JSON + * representation. + * @param geometry + * The geometry to be exported to JSON. + * @return The JSON representation of the specified Geometry. + */ + public static String geometryToJson(int wkid, Geometry geometry) { + return GeometryEngine.geometryToJson( + wkid > 0 ? SpatialReference.create(wkid) : null, geometry); + } + + /** + * Exports the specified geometry instance to it's JSON representation. M + * and Z values are not imported from JSON representation. + * + * See OperatorExportToJson. + * + * @param spatialReference + * The spatial reference of associated object. + * @param geometry + * The geometry. + * @return The JSON representation of the specified geometry. + */ + public static String geometryToJson(SpatialReference spatialReference, + Geometry geometry) { + OperatorExportToJson exporter = (OperatorExportToJson) factory + .getOperator(Operator.Type.ExportToJson); + + return exporter.execute(spatialReference, geometry); + } + + public static String geometryToGeoJson(Geometry geometry) { + OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory + .getOperator(Operator.Type.ExportToGeoJson); + + return exporter.execute(geometry); + } + + /** + * Imports the MapGeometry from its JSON representation. M and Z values are + * not imported from JSON representation. + * + * See OperatorImportFromJson. + * + * @param json + * The JSON representation of the geometry (with spatial + * reference). + * @return The MapGeometry instance containing the imported geometry and its + * spatial reference. + * @throws IOException + * @throws JsonParseException + */ + public static MapGeometry geoJsonToGeometry(String json, int importFlags, Geometry.Type type) { + MapGeometry geom = OperatorImportFromGeoJson.local().execute(importFlags, type, json, null); + return geom; + } + + /** + * Exports the specified geometry instance to its GeoJSON representation. + * + * See OperatorExportToGeoJson. + * + * @see GeometryEngine#geometryToGeoJson(SpatialReference spatialReference, + * Geometry geometry) + * + * @param wkid + * The spatial reference Well Known ID to be used for the GeoJSON + * representation. + * @param geometry + * The geometry to be exported to GeoJSON. + * @return The GeoJSON representation of the specified geometry. + */ + public static String geometryToGeoJson(int wkid, Geometry geometry) { + return GeometryEngine.geometryToGeoJson(wkid > 0 ? SpatialReference.create(wkid) : null, geometry); + } + + /** + * Exports the specified geometry instance to it's JSON representation. + * + * See OperatorImportFromGeoJson. + * + * @param spatialReference + * The spatial reference of associated object. + * @param geometry + * The geometry. + * @return The GeoJSON representation of the specified geometry. + */ + public static String geometryToGeoJson(SpatialReference spatialReference, Geometry geometry) { + OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory.getOperator(Operator.Type.ExportToGeoJson); + + return exporter.execute(spatialReference, geometry); + } + + /** + * Imports geometry from the ESRI shape file format. + * + * See OperatorImportFromESRIShape. + * + * @param esriShapeBuffer + * The buffer containing geometry in the ESRI shape file format. + * @param geometryType + * The required type of the Geometry to be imported. Use + * Geometry.Type.Unknown if the geometry type needs to be + * determined from the buffer content. + * @return The geometry or null if the buffer contains null shape. + * @throws GeometryException + * when the geometryType is not Geometry.Type.Unknown and the + * buffer contains geometry that cannot be converted to the + * given geometryType. or the buffer is corrupt. Another + * exception possible is IllegalArgumentsException. + */ + public static Geometry geometryFromEsriShape(byte[] esriShapeBuffer, + Geometry.Type geometryType) { + OperatorImportFromESRIShape op = (OperatorImportFromESRIShape) factory + .getOperator(Operator.Type.ImportFromESRIShape); + return op + .execute( + ShapeImportFlags.ShapeImportNonTrusted, + geometryType, + ByteBuffer.wrap(esriShapeBuffer).order( + ByteOrder.LITTLE_ENDIAN)); + } + + /** + * Exports geometry to the ESRI shape file format. + * + * See OperatorExportToESRIShape. + * + * @param geometry + * The geometry to export. (null value is not allowed) + * @return Array containing the exported ESRI shape file. + */ + public static byte[] geometryToEsriShape(Geometry geometry) { + if (geometry == null) + throw new IllegalArgumentException(); + OperatorExportToESRIShape op = (OperatorExportToESRIShape) factory + .getOperator(Operator.Type.ExportToESRIShape); + return op.execute(0, geometry).array(); + } + + /** + * Imports a geometry from a WKT string. + * + * See OperatorImportFromWkt. + * + * @param wkt The string containing the geometry in WKT format. + * @param importFlags Use the {@link WktImportFlags} interface. + * @param geometryType The required type of the Geometry to be imported. Use Geometry.Type.Unknown if the geometry type needs to be determined from the WKT context. + * @return The geometry. + * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the WKT contains a geometry that cannot be converted to the given geometryType. + * @throws IllegalArgument exception if an error is found while parsing the WKT string. + */ + public static Geometry geometryFromWkt(String wkt, int importFlags, + Geometry.Type geometryType) { + OperatorImportFromWkt op = (OperatorImportFromWkt) factory + .getOperator(Operator.Type.ImportFromWkt); + return op.execute(importFlags, geometryType, wkt, null); + } + + /** + * Exports a geometry to a string in WKT format. + * + * See OperatorExportToWkt. + * + * @param geometry The geometry to export. (null value is not allowed) + * @param exportFlags Use the {@link WktExportFlags} interface. + * @return A String containing the exported geometry in WKT format. + */ + public static String geometryToWkt(Geometry geometry, int exportFlags) { + OperatorExportToWkt op = (OperatorExportToWkt) factory + .getOperator(Operator.Type.ExportToWkt); + return op.execute(exportFlags, geometry, null); + } + + /** + * Constructs a new geometry by union an array of geometries. All inputs + * must be of the same type of geometries and share one spatial reference. + * + * See OperatorUnion. + * + * @param geometries + * The geometries to union. + * @param spatialReference + * The spatial reference of the geometries. + * @return The geometry object representing the resultant union. + */ + public static Geometry union(Geometry[] geometries, + SpatialReference spatialReference) { + OperatorUnion op = (OperatorUnion) factory + .getOperator(Operator.Type.Union); + + SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor( + geometries); + GeometryCursor result = op.execute(inputGeometries, spatialReference, + null); + return result.next(); + } + + /** + * Creates the difference of two geometries. The dimension of geometry2 has + * to be equal to or greater than that of geometry1. + * + * See OperatorDifference. + * + * @param geometry1 + * The geometry being subtracted. + * @param substractor + * The geometry object to subtract from. + * @param spatialReference + * The spatial reference of the geometries. + * @return The geometry of the differences. + */ + public static Geometry difference(Geometry geometry1, Geometry substractor, + SpatialReference spatialReference) { + OperatorDifference op = (OperatorDifference) factory + .getOperator(Operator.Type.Difference); + Geometry result = op.execute(geometry1, substractor, spatialReference, + null); + return result; + } + + /** + * Creates the symmetric difference of two geometries. + * + * See OperatorSymmetricDifference. + * + * @param leftGeometry + * is one of the Geometry instances in the XOR operation. + * @param rightGeometry + * is one of the Geometry instances in the XOR operation. + * @param spatialReference + * The spatial reference of the geometries. + * @return Returns the result of the symmetric difference. + */ + public static Geometry symmetricDifference(Geometry leftGeometry, + Geometry rightGeometry, SpatialReference spatialReference) { + OperatorSymmetricDifference op = (OperatorSymmetricDifference) factory + .getOperator(Operator.Type.SymmetricDifference); + Geometry result = op.execute(leftGeometry, rightGeometry, + spatialReference, null); + return result; + } + + /** + * Indicates if two geometries are equal. + * + * See OperatorEquals. + * + * @param geometry1 + * Geometry. + * @param geometry2 + * Geometry. + * @param spatialReference + * The spatial reference of the geometries. + * @return TRUE if both geometry objects are equal. + */ + public static boolean equals(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorEquals op = (OperatorEquals) factory + .getOperator(Operator.Type.Equals); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * See OperatorDisjoint. + * + */ + public static boolean disjoint(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorDisjoint op = (OperatorDisjoint) factory + .getOperator(Operator.Type.Disjoint); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * Constructs the set-theoretic intersection between an array of geometries + * and another geometry. + * + * See OperatorIntersection (also for dimension specific intersection). + * + * @param inputGeometries + * An array of geometry objects. + * @param geometry + * The geometry object. + * @return Any array of geometry objects showing the intersection. + */ + static Geometry[] intersect(Geometry[] inputGeometries, Geometry geometry, + SpatialReference spatialReference) { + OperatorIntersection op = (OperatorIntersection) factory + .getOperator(Operator.Type.Intersection); + SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor( + inputGeometries); + SimpleGeometryCursor intersectorCursor = new SimpleGeometryCursor( + geometry); + GeometryCursor result = op.execute(inputGeometriesCursor, + intersectorCursor, spatialReference, null); + + ArrayList resultGeoms = new ArrayList(); + Geometry g; + while ((g = result.next()) != null) { + resultGeoms.add(g); + } + + Geometry[] resultarr = resultGeoms.toArray(new Geometry[0]); + return resultarr; + } + + /** + * Creates a geometry through intersection between two geometries. + * + * See OperatorIntersection. + * + * @param geometry1 + * The first geometry. + * @param intersector + * The geometry to intersect the first geometry. + * @param spatialReference + * The spatial reference of the geometries. + * @return The geometry created through intersection. + */ + public static Geometry intersect(Geometry geometry1, Geometry intersector, + SpatialReference spatialReference) { + OperatorIntersection op = (OperatorIntersection) factory + .getOperator(Operator.Type.Intersection); + Geometry result = op.execute(geometry1, intersector, spatialReference, + null); + return result; + } + + /** + * Indicates if one geometry is within another geometry. + * + * See OperatorWithin. + * + * @param geometry1 + * The base geometry that is tested for within relationship to + * the other geometry. + * @param geometry2 + * The comparison geometry that is tested for the contains + * relationship to the other geometry. + * @param spatialReference + * The spatial reference of the geometries. + * @return TRUE if the first geometry is within the other geometry. + */ + public static boolean within(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorWithin op = (OperatorWithin) factory + .getOperator(Operator.Type.Within); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * Indicates if one geometry contains another geometry. + * + * See OperatorContains. + * + * @param geometry1 + * The geometry that is tested for the contains relationship to + * the other geometry.. + * @param geometry2 + * The geometry that is tested for within relationship to the + * other geometry. + * @param spatialReference + * The spatial reference of the geometries. + * @return TRUE if geometry1 contains geometry2. + */ + public static boolean contains(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorContains op = (OperatorContains) factory + .getOperator(Operator.Type.Contains); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * Indicates if one geometry crosses another geometry. + * + * See OperatorCrosses. + * + * @param geometry1 + * The geometry to cross. + * @param geometry2 + * The geometry being crossed. + * @param spatialReference + * The spatial reference of the geometries. + * @return TRUE if geometry1 crosses geometry2. + */ + public static boolean crosses(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorCrosses op = (OperatorCrosses) factory + .getOperator(Operator.Type.Crosses); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * Indicates if one geometry touches another geometry. + * + * See OperatorTouches. + * + * @param geometry1 + * The geometry to touch. + * @param geometry2 + * The geometry to be touched. + * @param spatialReference + * The spatial reference of the geometries. + * @return TRUE if geometry1 touches geometry2. + */ + public static boolean touches(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorTouches op = (OperatorTouches) factory + .getOperator(Operator.Type.Touches); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * Indicates if one geometry overlaps another geometry. + * + * See OperatorOverlaps. + * + * @param geometry1 + * The geometry to overlap. + * @param geometry2 + * The geometry to be overlapped. + * @param spatialReference + * The spatial reference of the geometries. + * @return TRUE if geometry1 overlaps geometry2. + */ + public static boolean overlaps(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorOverlaps op = (OperatorOverlaps) factory + .getOperator(Operator.Type.Overlaps); + boolean result = op.execute(geometry1, geometry2, spatialReference, + null); + return result; + } + + /** + * Indicates if the given relation holds for the two geometries. + * + * See OperatorRelate. + * + * @param geometry1 + * The first geometry for the relation. + * @param geometry2 + * The second geometry for the relation. + * @param spatialReference + * The spatial reference of the geometries. + * @param relation + * The DE-9IM relation. + * @return TRUE if the given relation holds between geometry1 and geometry2. + */ + public static boolean relate(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference, String relation) { + OperatorRelate op = (OperatorRelate) factory + .getOperator(Operator.Type.Relate); + boolean result = op.execute(geometry1, geometry2, spatialReference, + relation, null); + return result; + } + + /** + * Calculates the 2D planar distance between two geometries. + * + * See OperatorDistance. + * + * @param geometry1 + * Geometry. + * @param geometry2 + * Geometry. + * @param spatialReference + * The spatial reference of the geometries. This parameter is not + * used and can be null. + * @return The distance between the two geometries. + */ + public static double distance(Geometry geometry1, Geometry geometry2, + SpatialReference spatialReference) { + OperatorDistance op = (OperatorDistance) factory + .getOperator(Operator.Type.Distance); + double result = op.execute(geometry1, geometry2, null); + return result; + } + + /** + * Calculates the clipped geometry from a target geometry using an envelope. + * + * See OperatorClip. + * + * @param geometry + * The geometry to be clipped. + * @param envelope + * The envelope used to clip. + * @param spatialReference + * The spatial reference of the geometries. + * @return The geometry created by clipping. + */ + public static Geometry clip(Geometry geometry, Envelope envelope, + SpatialReference spatialReference) { + OperatorClip op = (OperatorClip) factory + .getOperator(Operator.Type.Clip); + Geometry result = op.execute(geometry, Envelope2D.construct( + envelope.getXMin(), envelope.getYMin(), envelope.getXMax(), + envelope.getYMax()), spatialReference, null); + return result; + } + + /** + * Calculates the cut geometry from a target geometry using a polyline. For + * Polylines, all left cuts will be grouped together in the first Geometry, + * Right cuts and coincident cuts are grouped in the second Geometry, and + * each undefined cut, along with any uncut parts, are output as separate + * Polylines. For Polygons, all left cuts are grouped in the first Polygon, + * all right cuts are in the second Polygon, and each undefined cut, along + * with any left-over parts after cutting, are output as a separate Polygon. + * If there were no cuts then the array will be empty. An undefined cut will + * only be produced if a left cut or right cut was produced, and there was a + * part left over after cutting or a cut is bounded to the left and right of + * the cutter. + * + * See OperatorCut. + * + * @param cuttee + * The geometry to be cut. + * @param cutter + * The polyline to cut the geometry. + * @param spatialReference + * The spatial reference of the geometries. + * @return An array of geometries created from cutting. + */ + public static Geometry[] cut(Geometry cuttee, Polyline cutter, + SpatialReference spatialReference) { + if (cuttee == null || cutter == null) + return null; + + OperatorCut op = (OperatorCut) factory.getOperator(Operator.Type.Cut); + GeometryCursor cursor = op.execute(true, cuttee, cutter, + spatialReference, null); + ArrayList cutsList = new ArrayList(); + + Geometry geometry; + while ((geometry = cursor.next()) != null) { + if (!geometry.isEmpty()) { + cutsList.add(geometry); + } + } + + return cutsList.toArray(new Geometry[0]); + } + /** + * Calculates a buffer polygon for each geometry at each of the + * corresponding specified distances. It is assumed that all geometries have + * the same spatial reference. There is an option to union the + * returned geometries. + * + * See OperatorBuffer. + * + * @param geometries An array of geometries to be buffered. + * @param spatialReference The spatial reference of the geometries. + * @param distances The corresponding distances for the input geometries to be buffered. + * @param toUnionResults TRUE if all geometries buffered at a given distance are to be unioned into a single polygon. + * @return The buffer of the geometries. + */ + public static Polygon[] buffer(Geometry[] geometries, + SpatialReference spatialReference, double[] distances, + boolean toUnionResults) { + // initially assume distances are in unit of spatial reference + double[] bufferDistances = distances; + + OperatorBuffer op = (OperatorBuffer) factory + .getOperator(Operator.Type.Buffer); + + if (toUnionResults) { + SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor( + geometries); + GeometryCursor result = op.execute(inputGeometriesCursor, + spatialReference, bufferDistances, toUnionResults, null); + + ArrayList resultGeoms = new ArrayList(); + Geometry g; + while ((g = result.next()) != null) { + resultGeoms.add((Polygon) g); + } + Polygon[] buffers = resultGeoms.toArray(new Polygon[0]); + return buffers; + } else { + Polygon[] buffers = new Polygon[geometries.length]; + for (int i = 0; i < geometries.length; i++) { + buffers[i] = (Polygon) op.execute(geometries[i], + spatialReference, bufferDistances[i], null); + } + return buffers; + } + } + + /** + * Calculates a buffer polygon of the geometry as specified by the + * distance input. The buffer is implemented in the xy-plane. + * + * See OperatorBuffer + * + * @param geometry Geometry to be buffered. + * @param spatialReference The spatial reference of the geometry. + * @param distance The specified distance for buffer. Same units as the spatial reference. + * @return The buffer polygon at the specified distances. + */ + public static Polygon buffer(Geometry geometry, + SpatialReference spatialReference, double distance) { + double bufferDistance = distance; + + OperatorBuffer op = (OperatorBuffer) factory + .getOperator(Operator.Type.Buffer); + Geometry result = op.execute(geometry, spatialReference, + bufferDistance, null); + return (Polygon) result; + } + + /** + * Calculates the convex hull geometry. + * + * See OperatorConvexHull. + * + * @param geometry The input geometry. + * @return Returns the convex hull. + * + * For a Point - returns the same point. For an Envelope - + * returns the same envelope. For a MultiPoint - If the point + * count is one, returns the same multipoint. If the point count + * is two, returns a polyline of the points. Otherwise computes + * and returns the convex hull polygon. For a Segment - returns a + * polyline consisting of the segment. For a Polyline - If + * consists of only one segment, returns the same polyline. + * Otherwise computes and returns the convex hull polygon. For a + * Polygon - If more than one path, or if the path isn't already + * convex, computes and returns the convex hull polygon. + * Otherwise returns the same polygon. + */ + public static Geometry convexHull(Geometry geometry) { + OperatorConvexHull op = (OperatorConvexHull) factory + .getOperator(Operator.Type.ConvexHull); + return op.execute(geometry, null); + } + + /** + * Calculates the convex hull. + * + * See OperatorConvexHull + * + * @param geometries + * The input geometry array. + * @param b_merge + * Put true if you want the convex hull of all the geometries in + * the array combined. Put false if you want the convex hull of + * each geometry in the array individually. + * @return Returns an array of convex hulls. If b_merge is true, the result + * will be a one element array consisting of the merged convex hull. + */ + public static Geometry[] convexHull(Geometry[] geometries, boolean b_merge) { + OperatorConvexHull op = (OperatorConvexHull) factory + .getOperator(Operator.Type.ConvexHull); + SimpleGeometryCursor simple_cursor = new SimpleGeometryCursor( + geometries); + GeometryCursor cursor = op.execute(simple_cursor, b_merge, null); + + ArrayList resultGeoms = new ArrayList(); + Geometry g; + while ((g = cursor.next()) != null) { + resultGeoms.add(g); + } + + Geometry[] output = new Geometry[resultGeoms.size()]; + + for (int i = 0; i < resultGeoms.size(); i++) + output[i] = resultGeoms.get(i); + + return output; + } + + /** + * Finds the coordinate of the geometry which is closest to the specified + * point. + * + * See OperatorProximity2D. + * + * @param inputPoint + * The point to find the nearest coordinate in the geometry for. + * @param geometry + * The geometry to consider. + * @return Proximity2DResult containing the nearest coordinate. + */ + public static Proximity2DResult getNearestCoordinate(Geometry geometry, + Point inputPoint, boolean bTestPolygonInterior) { + + OperatorProximity2D proximity = (OperatorProximity2D) factory + .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D); + Proximity2DResult result = proximity.getNearestCoordinate(geometry, + inputPoint, bTestPolygonInterior); + return result; + } + + /** + * Finds nearest vertex on the geometry which is closed to the specified + * point. + * + * See OperatorProximity2D. + * + * @param inputPoint + * The point to find the nearest vertex of the geometry for. + * @param geometry + * The geometry to consider. + * @return Proximity2DResult containing the nearest vertex. + */ + public static Proximity2DResult getNearestVertex(Geometry geometry, + Point inputPoint) { + OperatorProximity2D proximity = (OperatorProximity2D) factory + .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D); + Proximity2DResult result = proximity.getNearestVertex(geometry, + inputPoint); + return result; + } + + /** + * Finds all vertices in the given distance from the specified point, sorted + * from the closest to the furthest. + * + * See OperatorProximity2D. + * + * @param inputPoint + * The point to start from. + * @param geometry + * The geometry to consider. + * @param searchRadius + * The search radius. + * @param maxVertexCountToReturn + * The maximum number number of vertices to return. + * @return Proximity2DResult containing the array of nearest vertices. + */ + public static Proximity2DResult[] getNearestVertices(Geometry geometry, + Point inputPoint, double searchRadius, int maxVertexCountToReturn) { + OperatorProximity2D proximity = (OperatorProximity2D) factory + .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D); + + Proximity2DResult[] results = proximity.getNearestVertices(geometry, + inputPoint, searchRadius, maxVertexCountToReturn); + + return results; + } + + /** + * Performs the simplify operation on the geometry. + * + * See OperatorSimplify and See OperatorSimplifyOGC. + * + * @param geometry + * The geometry to be simplified. + * @param spatialReference + * The spatial reference of the geometry to be simplified. + * @return The simplified geometry. + */ + public static Geometry simplify(Geometry geometry, + SpatialReference spatialReference) { + OperatorSimplify op = (OperatorSimplify) factory + .getOperator(Operator.Type.Simplify); + Geometry result = op.execute(geometry, spatialReference, false, null); + return result; + } + + /** + * Checks if the Geometry is simple. + * + * See OperatorSimplify. + * + * @param geometry + * The geometry to be checked. + * @param spatialReference + * The spatial reference of the geometry. + * @return TRUE if the geometry is simple. + */ + static boolean isSimple(Geometry geometry, SpatialReference spatialReference) { + OperatorSimplify op = (OperatorSimplify) factory + .getOperator(Operator.Type.Simplify); + boolean result = op.isSimpleAsFeature(geometry, spatialReference, null); + return result; + } + + /** + * A geodesic distance is the shortest distance between any two points on the earth's surface when the earth's + * surface is approximated by a spheroid. The function returns the shortest distance between two points on the + * WGS84 spheroid. + * @param ptFrom The "from" point: long, lat in degrees. + * @param ptTo The "to" point: long, lat in degrees. + * @return The geodesic distance between two points in meters. + */ + public static double geodesicDistanceOnWGS84(Point ptFrom, Point ptTo) { + return SpatialReferenceImpl.geodesicDistanceOnWGS84Impl(ptFrom, ptTo); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestCut.java b/src/test/java/com/esri/core/geometry/TestCut.java index f67a4d1f..8bb8f25c 100644 --- a/src/test/java/com/esri/core/geometry/TestCut.java +++ b/src/test/java/com/esri/core/geometry/TestCut.java @@ -1,520 +1,520 @@ -package com.esri.core.geometry; - -import junit.framework.TestCase; -import org.junit.Test; - -public class TestCut extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public static void testCut4326() { - SpatialReference sr = SpatialReference.create(4326); - testConsiderTouch1(sr); - testConsiderTouch2(sr); - testPolygon5(sr); - testPolygon7(sr); - testPolygon8(sr); - testPolygon9(sr); - testEngine(sr); - - } - - public static void testConsiderTouch1(SpatialReference spatialReference) { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); - - Polyline polyline1 = makePolyline1(); - Polyline cutter1 = makePolylineCutter1(); - - GeometryCursor cursor = opCut.execute(true, polyline1, cutter1, - spatialReference, null); - Polyline cut; - int pathCount; - int segmentCount; - double length; - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 4); - assertTrue(segmentCount == 4); - assertTrue(length == 6); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 6); - assertTrue(segmentCount == 8); - assertTrue(length == 12); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 1); - assertTrue(segmentCount == 1); - assertTrue(length == 1); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 1); - assertTrue(segmentCount == 1); - assertTrue(length == 1); - - cut = (Polyline) cursor.next(); - assertTrue(cut == null); - } - - public static void testConsiderTouch2(SpatialReference spatialReference) { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); - - Polyline polyline2 = makePolyline2(); - Polyline cutter2 = makePolylineCutter2(); - - GeometryCursor cursor = opCut.execute(true, polyline2, cutter2, - spatialReference, null); - Polyline cut; - int pathCount; - int segmentCount; - double length; - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 4); - assertTrue(segmentCount == 4); - assertTrue(Math.abs(length - 5.74264068) <= 0.001); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 6); - assertTrue(segmentCount == 8); - assertTrue(length == 6.75); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 1); - assertTrue(segmentCount == 1); - assertTrue(Math.abs(length - 0.5) <= 0.001); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 1); - assertTrue(segmentCount == 1); - assertTrue(Math.abs(length - 0.25) <= 0.001); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 1); - assertTrue(segmentCount == 1); - assertTrue(Math.abs(length - 1) <= 0.001); - - cut = (Polyline) cursor.next(); - pathCount = cut.getPathCount(); - segmentCount = cut.getSegmentCount(); - length = cut.calculateLength2D(); - assertTrue(pathCount == 1); - assertTrue(segmentCount == 1); - assertTrue(Math.abs(length - 1.41421356) <= 0.001); - - cut = (Polyline) cursor.next(); - assertTrue(cut == null); - } - - public static void testPolygon5(SpatialReference spatialReference) { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); - - Polygon polygon5 = makePolygon5(); - Polyline cutter5 = makePolygonCutter5(); - - GeometryCursor cursor = opCut.execute(true, polygon5, cutter5, - spatialReference, null); - Polygon cut; - int pathCount; - int pointCount; - double area; - - cut = (Polygon) cursor.next(); - pathCount = cut.getPathCount(); - pointCount = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(pathCount == 4); - assertTrue(pointCount == 12); - assertTrue(area == 450); - - cut = (Polygon) cursor.next(); - pathCount = cut.getPathCount(); - pointCount = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(pathCount == 1); - assertTrue(pointCount == 4); - assertTrue(area == 450); - - cut = (Polygon) cursor.next(); - assertTrue(cut == null); - } - - public static void testPolygon7(SpatialReference spatialReference) { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); - - Polygon cut; - int path_count; - int point_count; - double area; - - Polygon polygon7 = makePolygon7(); - Polyline cutter7 = makePolygonCutter7(); - GeometryCursor cursor = opCut.execute(false, polygon7, cutter7, - spatialReference, null); - - cut = (Polygon) cursor.next(); - path_count = cut.getPathCount(); - point_count = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(path_count == 1); - assertTrue(point_count == 4); - assertTrue(area == 100); - - cut = (Polygon) cursor.next(); - assertTrue(cut.isEmpty()); - - cut = (Polygon) cursor.next(); - path_count = cut.getPathCount(); - point_count = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(path_count == 2); - assertTrue(point_count == 8); - assertTrue(area == 800); - - cut = (Polygon) cursor.next(); - assertTrue(cut == null); - } - - public static void testPolygon8(SpatialReference spatialReference) { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); - - Polygon polygon8 = makePolygon8(); - Polyline cutter8 = makePolygonCutter8(); - - GeometryCursor cursor = opCut.execute(true, polygon8, cutter8, - spatialReference, null); - Polygon cut; - int pathCount; - int pointCount; - double area; - - cut = (Polygon) cursor.next(); - assertTrue(cut.isEmpty()); - - cut = (Polygon) cursor.next(); - pathCount = cut.getPathCount(); - pointCount = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(pathCount == 1); - assertTrue(pointCount == 4); - assertTrue(area == 100); - - cut = (Polygon) cursor.next(); - pathCount = cut.getPathCount(); - pointCount = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(pathCount == 2); - assertTrue(pointCount == 8); - assertTrue(area == 800); - - cut = (Polygon) cursor.next(); - assertTrue(cut == null); - } - - public static void testPolygon9(SpatialReference spatialReference) { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); - - Polygon cut; - int path_count; - int point_count; - double area; - - Polygon polygon9 = makePolygon9(); - Polyline cutter9 = makePolygonCutter9(); - GeometryCursor cursor = opCut.execute(false, polygon9, cutter9, - spatialReference, null); - - cut = (Polygon) cursor.next(); - path_count = cut.getPathCount(); - point_count = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(path_count == 3); - assertTrue(point_count == 12); - assertTrue(area == 150); - - cut = (Polygon) cursor.next(); - path_count = cut.getPathCount(); - point_count = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(path_count == 3); - assertTrue(point_count == 12); - assertTrue(area == 150); - - cut = (Polygon) cursor.next(); - assertTrue(cut == null); - } - - public static void testEngine(SpatialReference spatialReference) { - Polygon polygon8 = makePolygon8(); - Polyline cutter8 = makePolygonCutter8(); - - Geometry[] cuts = GeometryEngine.cut(polygon8, cutter8, - spatialReference); - Polygon cut; - int pathCount; - int pointCount; - double area; - - cut = (Polygon) cuts[0]; - pathCount = cut.getPathCount(); - pointCount = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(pathCount == 1); - assertTrue(pointCount == 4); - assertTrue(area == 100); - - cut = (Polygon) cuts[1]; - pathCount = cut.getPathCount(); - pointCount = cut.getPointCount(); - area = cut.calculateArea2D(); - assertTrue(pathCount == 2); - assertTrue(pointCount == 8); - assertTrue(area == 800); - } - - public static Polyline makePolyline1() { - Polyline poly = new Polyline(); - - poly.startPath(0, 0); - poly.lineTo(2, 0); - poly.lineTo(4, 0); - poly.lineTo(6, 0); - poly.lineTo(8, 0); - poly.lineTo(10, 0); - poly.lineTo(12, 0); - poly.lineTo(14, 0); - poly.lineTo(16, 0); - poly.lineTo(18, 0); - poly.lineTo(20, 0); - - return poly; - } - - public static Polyline makePolylineCutter1() { - Polyline poly = new Polyline(); - - poly.startPath(1, 0); - poly.lineTo(4, 0); - - poly.startPath(6, -1); - poly.lineTo(6, 1); - - poly.startPath(6, 0); - poly.lineTo(8, 0); - - poly.startPath(9, -1); - poly.lineTo(9, 1); - - poly.startPath(10, 0); - poly.lineTo(12, 0); - - poly.startPath(12, 1); - poly.lineTo(12, -1); - - poly.startPath(12, 0); - poly.lineTo(15, 0); - - poly.startPath(15, 1); - poly.lineTo(15, -1); - - poly.startPath(16, 0); - poly.lineTo(16, -1); - poly.lineTo(17, -1); - poly.lineTo(17, 1); - poly.lineTo(17, 0); - poly.lineTo(18, 0); - - poly.startPath(18, 0); - poly.lineTo(18, -1); - - return poly; - } - - public static Polyline makePolyline2() { - Polyline poly = new Polyline(); - - poly.startPath(-2, 0); - poly.lineTo(-1, 0); - poly.lineTo(0, 0); - poly.lineTo(2, 0); - poly.lineTo(4, 2); - poly.lineTo(8, 2); - poly.lineTo(10, 4); - poly.lineTo(12, 4); - - return poly; - } - - public static Polyline makePolylineCutter2() { - Polyline poly = new Polyline(); - - poly.startPath(-1.5, 0); - poly.lineTo(-.75, 0); - - poly.startPath(-.5, 0); - poly.lineTo(1, 0); - poly.lineTo(1, 2); - poly.lineTo(3, -2); - poly.lineTo(4, 2); - poly.lineTo(5, -2); - poly.lineTo(5, 4); - poly.lineTo(8, 2); - poly.lineTo(6, 0); - poly.lineTo(6, 3); - - poly.startPath(9, 5); - poly.lineTo(9, 2); - poly.lineTo(10, 2); - poly.lineTo(10, 5); - poly.lineTo(10.5, 5); - poly.lineTo(10.5, 3); - - poly.startPath(11, 4); - poly.lineTo(11, 5); - - poly.startPath(12, 5); - poly.lineTo(12, 4); - - return poly; - } - - public static Polygon makePolygon5() { - Polygon poly = new Polygon(); - - poly.startPath(0, 0); - poly.lineTo(0, 30); - poly.lineTo(30, 30); - poly.lineTo(30, 0); - - return poly; - } - - public static Polyline makePolygonCutter5() { - Polyline poly = new Polyline(); - - poly.startPath(15, 0); - poly.lineTo(0, 15); - poly.lineTo(15, 30); - poly.lineTo(30, 15); - poly.lineTo(15, 0); - - return poly; - } - - public static Polygon makePolygon7() { - Polygon poly = new Polygon(); - - poly.startPath(0, 0); - poly.lineTo(0, 30); - poly.lineTo(30, 30); - poly.lineTo(30, 0); - - return poly; - } - - public static Polyline makePolygonCutter7() { - Polyline poly = new Polyline(); - - poly.startPath(10, 10); - poly.lineTo(20, 10); - poly.lineTo(20, 20); - poly.lineTo(10, 20); - poly.lineTo(10, 10); - - return poly; - } - - public static Polygon makePolygon8() { - Polygon poly = new Polygon(); - - poly.startPath(0, 0); - poly.lineTo(0, 30); - poly.lineTo(30, 30); - poly.lineTo(30, 0); - - return poly; - } - - public static Polyline makePolygonCutter8() { - Polyline poly = new Polyline(); - - poly.startPath(10, 10); - poly.lineTo(10, 20); - poly.lineTo(20, 20); - poly.lineTo(20, 10); - poly.lineTo(10, 10); - - return poly; - } - - public static Polygon makePolygon9() { - Polygon poly = new Polygon(); - - poly.startPath(0, 0); - poly.lineTo(0, 10); - poly.lineTo(10, 10); - poly.lineTo(10, 0); - - poly.startPath(0, 20); - poly.lineTo(0, 30); - poly.lineTo(10, 30); - poly.lineTo(10, 20); - - poly.startPath(0, 40); - poly.lineTo(0, 50); - poly.lineTo(10, 50); - poly.lineTo(10, 40); - - return poly; - } - - public static Polyline makePolygonCutter9() { - Polyline poly = new Polyline(); - - poly.startPath(5, -1); - poly.lineTo(5, 51); - - return poly; - } -} +package com.esri.core.geometry; + +import junit.framework.TestCase; +import org.junit.Test; + +public class TestCut extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public static void testCut4326() { + SpatialReference sr = SpatialReference.create(4326); + testConsiderTouch1(sr); + testConsiderTouch2(sr); + testPolygon5(sr); + testPolygon7(sr); + testPolygon8(sr); + testPolygon9(sr); + testEngine(sr); + + } + + public static void testConsiderTouch1(SpatialReference spatialReference) { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); + + Polyline polyline1 = makePolyline1(); + Polyline cutter1 = makePolylineCutter1(); + + GeometryCursor cursor = opCut.execute(true, polyline1, cutter1, + spatialReference, null); + Polyline cut; + int pathCount; + int segmentCount; + double length; + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 4); + assertTrue(segmentCount == 4); + assertTrue(length == 6); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 6); + assertTrue(segmentCount == 8); + assertTrue(length == 12); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 1); + assertTrue(segmentCount == 1); + assertTrue(length == 1); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 1); + assertTrue(segmentCount == 1); + assertTrue(length == 1); + + cut = (Polyline) cursor.next(); + assertTrue(cut == null); + } + + public static void testConsiderTouch2(SpatialReference spatialReference) { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); + + Polyline polyline2 = makePolyline2(); + Polyline cutter2 = makePolylineCutter2(); + + GeometryCursor cursor = opCut.execute(true, polyline2, cutter2, + spatialReference, null); + Polyline cut; + int pathCount; + int segmentCount; + double length; + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 4); + assertTrue(segmentCount == 4); + assertTrue(Math.abs(length - 5.74264068) <= 0.001); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 6); + assertTrue(segmentCount == 8); + assertTrue(length == 6.75); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 1); + assertTrue(segmentCount == 1); + assertTrue(Math.abs(length - 0.5) <= 0.001); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 1); + assertTrue(segmentCount == 1); + assertTrue(Math.abs(length - 0.25) <= 0.001); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 1); + assertTrue(segmentCount == 1); + assertTrue(Math.abs(length - 1) <= 0.001); + + cut = (Polyline) cursor.next(); + pathCount = cut.getPathCount(); + segmentCount = cut.getSegmentCount(); + length = cut.calculateLength2D(); + assertTrue(pathCount == 1); + assertTrue(segmentCount == 1); + assertTrue(Math.abs(length - 1.41421356) <= 0.001); + + cut = (Polyline) cursor.next(); + assertTrue(cut == null); + } + + public static void testPolygon5(SpatialReference spatialReference) { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); + + Polygon polygon5 = makePolygon5(); + Polyline cutter5 = makePolygonCutter5(); + + GeometryCursor cursor = opCut.execute(true, polygon5, cutter5, + spatialReference, null); + Polygon cut; + int pathCount; + int pointCount; + double area; + + cut = (Polygon) cursor.next(); + pathCount = cut.getPathCount(); + pointCount = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(pathCount == 4); + assertTrue(pointCount == 12); + assertTrue(area == 450); + + cut = (Polygon) cursor.next(); + pathCount = cut.getPathCount(); + pointCount = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(pathCount == 1); + assertTrue(pointCount == 4); + assertTrue(area == 450); + + cut = (Polygon) cursor.next(); + assertTrue(cut == null); + } + + public static void testPolygon7(SpatialReference spatialReference) { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); + + Polygon cut; + int path_count; + int point_count; + double area; + + Polygon polygon7 = makePolygon7(); + Polyline cutter7 = makePolygonCutter7(); + GeometryCursor cursor = opCut.execute(false, polygon7, cutter7, + spatialReference, null); + + cut = (Polygon) cursor.next(); + path_count = cut.getPathCount(); + point_count = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(path_count == 1); + assertTrue(point_count == 4); + assertTrue(area == 100); + + cut = (Polygon) cursor.next(); + assertTrue(cut.isEmpty()); + + cut = (Polygon) cursor.next(); + path_count = cut.getPathCount(); + point_count = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(path_count == 2); + assertTrue(point_count == 8); + assertTrue(area == 800); + + cut = (Polygon) cursor.next(); + assertTrue(cut == null); + } + + public static void testPolygon8(SpatialReference spatialReference) { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); + + Polygon polygon8 = makePolygon8(); + Polyline cutter8 = makePolygonCutter8(); + + GeometryCursor cursor = opCut.execute(true, polygon8, cutter8, + spatialReference, null); + Polygon cut; + int pathCount; + int pointCount; + double area; + + cut = (Polygon) cursor.next(); + assertTrue(cut.isEmpty()); + + cut = (Polygon) cursor.next(); + pathCount = cut.getPathCount(); + pointCount = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(pathCount == 1); + assertTrue(pointCount == 4); + assertTrue(area == 100); + + cut = (Polygon) cursor.next(); + pathCount = cut.getPathCount(); + pointCount = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(pathCount == 2); + assertTrue(pointCount == 8); + assertTrue(area == 800); + + cut = (Polygon) cursor.next(); + assertTrue(cut == null); + } + + public static void testPolygon9(SpatialReference spatialReference) { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); + + Polygon cut; + int path_count; + int point_count; + double area; + + Polygon polygon9 = makePolygon9(); + Polyline cutter9 = makePolygonCutter9(); + GeometryCursor cursor = opCut.execute(false, polygon9, cutter9, + spatialReference, null); + + cut = (Polygon) cursor.next(); + path_count = cut.getPathCount(); + point_count = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(path_count == 3); + assertTrue(point_count == 12); + assertTrue(area == 150); + + cut = (Polygon) cursor.next(); + path_count = cut.getPathCount(); + point_count = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(path_count == 3); + assertTrue(point_count == 12); + assertTrue(area == 150); + + cut = (Polygon) cursor.next(); + assertTrue(cut == null); + } + + public static void testEngine(SpatialReference spatialReference) { + Polygon polygon8 = makePolygon8(); + Polyline cutter8 = makePolygonCutter8(); + + Geometry[] cuts = GeometryEngine.cut(polygon8, cutter8, + spatialReference); + Polygon cut; + int pathCount; + int pointCount; + double area; + + cut = (Polygon) cuts[0]; + pathCount = cut.getPathCount(); + pointCount = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(pathCount == 1); + assertTrue(pointCount == 4); + assertTrue(area == 100); + + cut = (Polygon) cuts[1]; + pathCount = cut.getPathCount(); + pointCount = cut.getPointCount(); + area = cut.calculateArea2D(); + assertTrue(pathCount == 2); + assertTrue(pointCount == 8); + assertTrue(area == 800); + } + + public static Polyline makePolyline1() { + Polyline poly = new Polyline(); + + poly.startPath(0, 0); + poly.lineTo(2, 0); + poly.lineTo(4, 0); + poly.lineTo(6, 0); + poly.lineTo(8, 0); + poly.lineTo(10, 0); + poly.lineTo(12, 0); + poly.lineTo(14, 0); + poly.lineTo(16, 0); + poly.lineTo(18, 0); + poly.lineTo(20, 0); + + return poly; + } + + public static Polyline makePolylineCutter1() { + Polyline poly = new Polyline(); + + poly.startPath(1, 0); + poly.lineTo(4, 0); + + poly.startPath(6, -1); + poly.lineTo(6, 1); + + poly.startPath(6, 0); + poly.lineTo(8, 0); + + poly.startPath(9, -1); + poly.lineTo(9, 1); + + poly.startPath(10, 0); + poly.lineTo(12, 0); + + poly.startPath(12, 1); + poly.lineTo(12, -1); + + poly.startPath(12, 0); + poly.lineTo(15, 0); + + poly.startPath(15, 1); + poly.lineTo(15, -1); + + poly.startPath(16, 0); + poly.lineTo(16, -1); + poly.lineTo(17, -1); + poly.lineTo(17, 1); + poly.lineTo(17, 0); + poly.lineTo(18, 0); + + poly.startPath(18, 0); + poly.lineTo(18, -1); + + return poly; + } + + public static Polyline makePolyline2() { + Polyline poly = new Polyline(); + + poly.startPath(-2, 0); + poly.lineTo(-1, 0); + poly.lineTo(0, 0); + poly.lineTo(2, 0); + poly.lineTo(4, 2); + poly.lineTo(8, 2); + poly.lineTo(10, 4); + poly.lineTo(12, 4); + + return poly; + } + + public static Polyline makePolylineCutter2() { + Polyline poly = new Polyline(); + + poly.startPath(-1.5, 0); + poly.lineTo(-.75, 0); + + poly.startPath(-.5, 0); + poly.lineTo(1, 0); + poly.lineTo(1, 2); + poly.lineTo(3, -2); + poly.lineTo(4, 2); + poly.lineTo(5, -2); + poly.lineTo(5, 4); + poly.lineTo(8, 2); + poly.lineTo(6, 0); + poly.lineTo(6, 3); + + poly.startPath(9, 5); + poly.lineTo(9, 2); + poly.lineTo(10, 2); + poly.lineTo(10, 5); + poly.lineTo(10.5, 5); + poly.lineTo(10.5, 3); + + poly.startPath(11, 4); + poly.lineTo(11, 5); + + poly.startPath(12, 5); + poly.lineTo(12, 4); + + return poly; + } + + public static Polygon makePolygon5() { + Polygon poly = new Polygon(); + + poly.startPath(0, 0); + poly.lineTo(0, 30); + poly.lineTo(30, 30); + poly.lineTo(30, 0); + + return poly; + } + + public static Polyline makePolygonCutter5() { + Polyline poly = new Polyline(); + + poly.startPath(15, 0); + poly.lineTo(0, 15); + poly.lineTo(15, 30); + poly.lineTo(30, 15); + poly.lineTo(15, 0); + + return poly; + } + + public static Polygon makePolygon7() { + Polygon poly = new Polygon(); + + poly.startPath(0, 0); + poly.lineTo(0, 30); + poly.lineTo(30, 30); + poly.lineTo(30, 0); + + return poly; + } + + public static Polyline makePolygonCutter7() { + Polyline poly = new Polyline(); + + poly.startPath(10, 10); + poly.lineTo(20, 10); + poly.lineTo(20, 20); + poly.lineTo(10, 20); + poly.lineTo(10, 10); + + return poly; + } + + public static Polygon makePolygon8() { + Polygon poly = new Polygon(); + + poly.startPath(0, 0); + poly.lineTo(0, 30); + poly.lineTo(30, 30); + poly.lineTo(30, 0); + + return poly; + } + + public static Polyline makePolygonCutter8() { + Polyline poly = new Polyline(); + + poly.startPath(10, 10); + poly.lineTo(10, 20); + poly.lineTo(20, 20); + poly.lineTo(20, 10); + poly.lineTo(10, 10); + + return poly; + } + + public static Polygon makePolygon9() { + Polygon poly = new Polygon(); + + poly.startPath(0, 0); + poly.lineTo(0, 10); + poly.lineTo(10, 10); + poly.lineTo(10, 0); + + poly.startPath(0, 20); + poly.lineTo(0, 30); + poly.lineTo(10, 30); + poly.lineTo(10, 20); + + poly.startPath(0, 40); + poly.lineTo(0, 50); + poly.lineTo(10, 50); + poly.lineTo(10, 40); + + return poly; + } + + public static Polyline makePolygonCutter9() { + Polyline poly = new Polyline(); + + poly.startPath(5, -1); + poly.lineTo(5, 51); + + return poly; + } +} diff --git a/src/test/java/com/esri/core/geometry/TestFailed.java b/src/test/java/com/esri/core/geometry/TestFailed.java index 9c7a915d..5c5b6c41 100644 --- a/src/test/java/com/esri/core/geometry/TestFailed.java +++ b/src/test/java/com/esri/core/geometry/TestFailed.java @@ -1,64 +1,64 @@ -package com.esri.core.geometry; - -import junit.framework.TestCase; -import org.junit.Test; - -public class TestFailed extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void testCenterXY() { - Envelope env = new Envelope(-130, 30, -70, 50); - assertEquals(-100, env.getCenterX(), 0); - assertEquals(40, env.getCenterY(), 0); - } - - @Test - public void testGeometryOperationSupport() { - Geometry baseGeom = new Point(-130, 10); - Geometry comparisonGeom = new Point(-130, 10); - SpatialReference sr = SpatialReference.create(4326); - - @SuppressWarnings("unused") - Geometry diffGeom = null; - int noException = 1; // no exception - try { - diffGeom = GeometryEngine.difference(baseGeom, comparisonGeom, sr); - - } catch (IllegalArgumentException ex) { - noException = 0; - } catch (GeometryException ex) { - noException = 0; - } - assertEquals(noException, 1); - } - - @Test - public void TestIntersection() { - OperatorIntersects op = (OperatorIntersects) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.Intersects); - Polygon polygon = new Polygon(); - // outer ring1 - polygon.startPath(0, 0); - polygon.lineTo(10, 10); - polygon.lineTo(20, 0); - - Point point1 = new Point(15, 10); - Point point2 = new Point(2, 10); - Point point3 = new Point(5, 5); - boolean res = op.execute(polygon, point1, null, null); - assertTrue(!res); - res = op.execute(polygon, point2, null, null); - assertTrue(!res); - res = op.execute(polygon, point3, null, null); - assertTrue(res); - } -} +package com.esri.core.geometry; + +import junit.framework.TestCase; +import org.junit.Test; + +public class TestFailed extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testCenterXY() { + Envelope env = new Envelope(-130, 30, -70, 50); + assertEquals(-100, env.getCenterX(), 0); + assertEquals(40, env.getCenterY(), 0); + } + + @Test + public void testGeometryOperationSupport() { + Geometry baseGeom = new Point(-130, 10); + Geometry comparisonGeom = new Point(-130, 10); + SpatialReference sr = SpatialReference.create(4326); + + @SuppressWarnings("unused") + Geometry diffGeom = null; + int noException = 1; // no exception + try { + diffGeom = GeometryEngine.difference(baseGeom, comparisonGeom, sr); + + } catch (IllegalArgumentException ex) { + noException = 0; + } catch (GeometryException ex) { + noException = 0; + } + assertEquals(noException, 1); + } + + @Test + public void TestIntersection() { + OperatorIntersects op = (OperatorIntersects) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.Intersects); + Polygon polygon = new Polygon(); + // outer ring1 + polygon.startPath(0, 0); + polygon.lineTo(10, 10); + polygon.lineTo(20, 0); + + Point point1 = new Point(15, 10); + Point point2 = new Point(2, 10); + Point point3 = new Point(5, 5); + boolean res = op.execute(polygon, point1, null, null); + assertTrue(!res); + res = op.execute(polygon, point2, null, null); + assertTrue(!res); + res = op.execute(polygon, point3, null, null); + assertTrue(res); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestGeodetic.java b/src/test/java/com/esri/core/geometry/TestGeodetic.java index 8777ec19..35c805ea 100644 --- a/src/test/java/com/esri/core/geometry/TestGeodetic.java +++ b/src/test/java/com/esri/core/geometry/TestGeodetic.java @@ -1,104 +1,105 @@ -package com.esri.core.geometry; - -import junit.framework.TestCase; - -import org.junit.Test; - -public class TestGeodetic extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void testTriangleLength() { - Point pt_0 = new Point(10, 10); - Point pt_1 = new Point(20, 20); - Point pt_2 = new Point(20, 10); - double length = 0.0; - length += GeometryEngine.geodesicDistanceOnWGS84(pt_0, pt_1); - length += GeometryEngine.geodesicDistanceOnWGS84(pt_1, pt_2); - length += GeometryEngine.geodesicDistanceOnWGS84(pt_2, pt_0); - assertTrue(Math.abs(length - 3744719.4094597572) < 1e-12 * 3744719.4094597572); - } - - @Test - public void testRotationInvariance() { - Point pt_0 = new Point(10, 40); - Point pt_1 = new Point(20, 60); - Point pt_2 = new Point(20, 40); - double length = 0.0; - length += GeometryEngine.geodesicDistanceOnWGS84(pt_0, pt_1); - length += GeometryEngine.geodesicDistanceOnWGS84(pt_1, pt_2); - length += GeometryEngine.geodesicDistanceOnWGS84(pt_2, pt_0); - assertTrue(Math.abs(length - 5409156.3896271614) < 1e-12 * 5409156.3896271614); - - for (int i = -540; i < 540; i += 5) { - pt_0.setXY(i + 10, 40); - pt_1.setXY(i + 20, 60); - pt_2.setXY(i + 20, 40); - length = 0.0; - length += GeometryEngine.geodesicDistanceOnWGS84(pt_0, pt_1); - length += GeometryEngine.geodesicDistanceOnWGS84(pt_1, pt_2); - length += GeometryEngine.geodesicDistanceOnWGS84(pt_2, pt_0); - assertTrue(Math.abs(length - 5409156.3896271614) < 1e-12 * 5409156.3896271614); - } - } - - @Test - public void testDistanceFailure() { - { - Point p1 = new Point(-60.668485, -31.996013333333334); - Point p2 = new Point(119.13731666666666, 32.251583333333336); - double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); - assertTrue(Math.abs(d - 19973410.50579736) < 1e-13 * 19973410.50579736); - } - - { - Point p1 = new Point(121.27343833333333, 27.467438333333334); - Point p2 = new Point(-58.55804833333333, -27.035613333333334); - double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); - assertTrue(Math.abs(d - 19954707.428360686) < 1e-13 * 19954707.428360686); - } - - { - Point p1 = new Point(-53.329865, -36.08110166666667); - Point p2 = new Point(126.52895166666667, 35.97385); - double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); - assertTrue(Math.abs(d - 19990586.700431127) < 1e-13 * 19990586.700431127); - } - - { - Point p1 = new Point(-4.7181166667, 36.1160166667); - Point p2 = new Point(175.248925, -35.7606716667); - double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); - assertTrue(Math.abs(d - 19964450.206594173) < 1e-12 * 19964450.206594173); - } - } - - @Test - public void testLengthAccurateCR191313() { - /* - * // random_test(); OperatorFactoryLocal engine = - * OperatorFactoryLocal.getInstance(); //TODO: Make this: - * OperatorShapePreservingLength geoLengthOp = - * (OperatorShapePreservingLength) - * factory.getOperator(Operator.Type.ShapePreservingLength); - * SpatialReference spatialRef = SpatialReference.create(102631); - * //[6097817.59407673 - * ,17463475.2931517],[-1168053.34617516,11199801.3734424 - * ]]],"spatialReference":{"wkid":102631} - * - * Polyline polyline = new Polyline(); - * polyline.startPath(6097817.59407673, 17463475.2931517); - * polyline.lineTo(-1168053.34617516, 11199801.3734424); double length = - * geoLengthOp.execute(polyline, spatialRef, null); - * assertTrue(Math.abs(length - 2738362.3249366437) < 2e-9 * length); - */ - } - } +package com.esri.core.geometry; + +import junit.framework.TestCase; + +import org.junit.Test; + +public class TestGeodetic extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testTriangleLength() { + Point pt_0 = new Point(10, 10); + Point pt_1 = new Point(20, 20); + Point pt_2 = new Point(20, 10); + double length = 0.0; + length += GeometryEngine.geodesicDistanceOnWGS84(pt_0, pt_1); + length += GeometryEngine.geodesicDistanceOnWGS84(pt_1, pt_2); + length += GeometryEngine.geodesicDistanceOnWGS84(pt_2, pt_0); + assertTrue(Math.abs(length - 3744719.4094597572) < 1e-12 * 3744719.4094597572); + } + + @Test + public void testRotationInvariance() { + Point pt_0 = new Point(10, 40); + Point pt_1 = new Point(20, 60); + Point pt_2 = new Point(20, 40); + double length = 0.0; + length += GeometryEngine.geodesicDistanceOnWGS84(pt_0, pt_1); + length += GeometryEngine.geodesicDistanceOnWGS84(pt_1, pt_2); + length += GeometryEngine.geodesicDistanceOnWGS84(pt_2, pt_0); + assertTrue(Math.abs(length - 5409156.3896271614) < 1e-12 * 5409156.3896271614); + + for (int i = -540; i < 540; i += 5) { + pt_0.setXY(i + 10, 40); + pt_1.setXY(i + 20, 60); + pt_2.setXY(i + 20, 40); + length = 0.0; + length += GeometryEngine.geodesicDistanceOnWGS84(pt_0, pt_1); + length += GeometryEngine.geodesicDistanceOnWGS84(pt_1, pt_2); + length += GeometryEngine.geodesicDistanceOnWGS84(pt_2, pt_0); + assertTrue(Math.abs(length - 5409156.3896271614) < 1e-12 * 5409156.3896271614); + } + } + + @Test + public void testDistanceFailure() { + { + Point p1 = new Point(-60.668485, -31.996013333333334); + Point p2 = new Point(119.13731666666666, 32.251583333333336); + double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); + assertTrue(Math.abs(d - 19973410.50579736) < 1e-13 * 19973410.50579736); + } + + { + Point p1 = new Point(121.27343833333333, 27.467438333333334); + Point p2 = new Point(-58.55804833333333, -27.035613333333334); + double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); + assertTrue(Math.abs(d - 19954707.428360686) < 1e-13 * 19954707.428360686); + } + + { + Point p1 = new Point(-53.329865, -36.08110166666667); + Point p2 = new Point(126.52895166666667, 35.97385); + double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); + assertTrue(Math.abs(d - 19990586.700431127) < 1e-13 * 19990586.700431127); + } + + { + Point p1 = new Point(-4.7181166667, 36.1160166667); + Point p2 = new Point(175.248925, -35.7606716667); + double d = GeometryEngine.geodesicDistanceOnWGS84(p1, p2); + assertTrue(Math.abs(d - 19964450.206594173) < 1e-12 * 19964450.206594173); + } + } + + @Test + public void testLengthAccurateCR191313() { + /* + * // random_test(); OperatorFactoryLocal engine = + * OperatorFactoryLocal.getInstance(); //TODO: Make this: + * OperatorShapePreservingLength geoLengthOp = + * (OperatorShapePreservingLength) + * factory.getOperator(Operator.Type.ShapePreservingLength); + * SpatialReference spatialRef = SpatialReference.create(102631); + * //[6097817.59407673 + * ,17463475.2931517],[-1168053.34617516,11199801.3734424 + * ]]],"spatialReference":{"wkid":102631} + * + * Polyline polyline = new Polyline(); + * polyline.startPath(6097817.59407673, 17463475.2931517); + * polyline.lineTo(-1168053.34617516, 11199801.3734424); double length = + * geoLengthOp.execute(polyline, spatialRef, null); + * assertTrue(Math.abs(length - 2738362.3249366437) < 2e-9 * length); + */ + } + +} diff --git a/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java b/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java index 237abb4c..498dab4b 100644 --- a/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java +++ b/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java @@ -1,565 +1,565 @@ -package com.esri.core.geometry; - -import java.io.IOException; -import junit.framework.TestCase; -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; - -public class TestGeomToJSonExportSRFromWkiOrWkt_CR181369 extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - JsonFactory factory = new JsonFactory(); - SpatialReference spatialReferenceWebMerc1 = SpatialReference.create(102100); - SpatialReference spatialReferenceWebMerc2 = SpatialReference - .create(spatialReferenceWebMerc1.getLatestID()); - SpatialReference spatialReferenceWGS84 = SpatialReference.create(4326); - - @Test - public void testLocalExport() - throws JsonParseException, IOException { - String s = OperatorExportToJson.local().execute(null, new Point(1000000.2, 2000000.3)); - //assertTrue(s.contains(".")); - //assertFalse(s.contains(",")); - Polyline line = new Polyline(); - line.startPath(1.1, 2.2); - line.lineTo(2.3, 4.5); - String s1 = OperatorExportToJson.local().execute(null, line); - assertTrue(s.contains(".")); - } - - boolean testPoint() throws JsonParseException, IOException { - boolean bAnswer = true; - Point point1 = new Point(10.0, 20.0); - Point pointEmpty = new Point(); - { - JsonParser pointWebMerc1Parser = factory - .createParser(GeometryEngine.geometryToJson( - spatialReferenceWebMerc1, point1)); - MapGeometry pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(point1.getX() == ((Point) pointWebMerc1MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWebMerc1MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWebMerc1.getID() == pointWebMerc1MP - .getSpatialReference().getID() - || pointWebMerc1MP.getSpatialReference().getID() == 3857); - - if (!checkResultSpatialRef(pointWebMerc1MP, 102100, 3857)) { - bAnswer = false; - } - - pointWebMerc1Parser = factory.createParser(GeometryEngine - .geometryToJson(null, point1)); - pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(null == pointWebMerc1MP.getSpatialReference()); - - if (pointWebMerc1MP.getSpatialReference() != null) { - if (!checkResultSpatialRef(pointWebMerc1MP, 102100, 3857)) { - bAnswer = false; - } - } - - String pointEmptyString = GeometryEngine.geometryToJson( - spatialReferenceWebMerc1, pointEmpty); - pointWebMerc1Parser = factory.createParser(pointEmptyString); - } - - JsonParser pointWebMerc2Parser = factory - .createParser(GeometryEngine.geometryToJson( - spatialReferenceWebMerc2, point1)); - MapGeometry pointWebMerc2MP = GeometryEngine - .jsonToGeometry(pointWebMerc2Parser); - assertTrue(point1.getX() == ((Point) pointWebMerc2MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWebMerc2MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWebMerc2.getLatestID() == pointWebMerc2MP - .getSpatialReference().getLatestID()); - if (!checkResultSpatialRef(pointWebMerc2MP, - spatialReferenceWebMerc2.getLatestID(), 0)) { - bAnswer = false; - } - - { - JsonParser pointWgs84Parser = factory - .createParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, point1)); - MapGeometry pointWgs84MP = GeometryEngine - .jsonToGeometry(pointWgs84Parser); - assertTrue(point1.getX() == ((Point) pointWgs84MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWgs84MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWGS84.getID() == pointWgs84MP - .getSpatialReference().getID()); - if (!checkResultSpatialRef(pointWgs84MP, 4326, 0)) { - bAnswer = false; - } - } - - { - Point p = new Point(); - String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, - p); - assertTrue(s - .equals("{\"x\":null,\"y\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - - p.addAttribute(VertexDescription.Semantics.Z); - p.addAttribute(VertexDescription.Semantics.M); - s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); - assertTrue(s - .equals("{\"x\":null,\"y\":null,\"z\":null,\"m\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - - } - - { - Point p = new Point(10.0, 20.0, 30.0); - p.addAttribute(VertexDescription.Semantics.M); - String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, - p); - assertTrue(s - .equals("{\"x\":10,\"y\":20,\"z\":30,\"m\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - } - - {// import - String s = "{\"x\":0.0,\"y\":1.0,\"z\":5.0,\"m\":11.0,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; - JsonParser parser = factory.createParser(s); - MapGeometry map_pt = GeometryEngine.jsonToGeometry(parser); - Point pt = (Point) map_pt.getGeometry(); - assertTrue(pt.getX() == 0.0); - assertTrue(pt.getY() == 1.0); - assertTrue(pt.getZ() == 5.0); - assertTrue(pt.getM() == 11.0); - } - - { - String s = "{\"x\" : 5.0, \"y\" : null, \"spatialReference\" : {\"wkid\" : 4326}} "; - JsonParser parser = factory.createParser(s); - MapGeometry map_pt = GeometryEngine.jsonToGeometry(parser); - Point pt = (Point) map_pt.getGeometry(); - assertTrue(pt.isEmpty()); - SpatialReference spatial_reference = map_pt.getSpatialReference(); - assertTrue(spatial_reference.getID() == 4326); - } - - return bAnswer; - } - - boolean testMultiPoint() throws JsonParseException, IOException { - boolean bAnswer = true; - - MultiPoint multiPoint1 = new MultiPoint(); - multiPoint1.add(-97.06138, 32.837); - multiPoint1.add(-97.06133, 32.836); - multiPoint1.add(-97.06124, 32.834); - multiPoint1.add(-97.06127, 32.832); - - { - String s = GeometryEngine.geometryToJson(spatialReferenceWGS84, - multiPoint1); - JsonParser mPointWgs84Parser = factory.createParser(s); - MapGeometry mPointWgs84MP = GeometryEngine - .jsonToGeometry(mPointWgs84Parser); - assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPointCount()); - assertTrue(multiPoint1.getPoint(0).getX() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(multiPoint1.getPoint(0).getY() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(0).getY()); - int lastIndex = multiPoint1.getPointCount() - 1; - assertTrue(multiPoint1.getPoint(lastIndex).getX() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(multiPoint1.getPoint(lastIndex).getY() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP - .getSpatialReference().getID()); - if (!checkResultSpatialRef(mPointWgs84MP, 4326, 0)) { - bAnswer = false; - } - - } - - { - MultiPoint p = new MultiPoint(); - p.addAttribute(VertexDescription.Semantics.Z); - p.addAttribute(VertexDescription.Semantics.M); - String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, - p); - assertTrue(s - .equals("{\"hasZ\":true,\"hasM\":true,\"points\":[],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - - p.add(10.0, 20.0, 30.0); - p.add(20.0, 40.0, 60.0); - s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); - assertTrue(s - .equals("{\"hasZ\":true,\"hasM\":true,\"points\":[[10,20,30,null],[20,40,60,null]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - } - { - String points = "{\"hasM\" : false, \"hasZ\" : true, \"uncle remus\" : null, \"points\" : [ [0,0,1], [0.0,10.0,1], [10.0,10.0,1], [10.0,0.0,1, 6666] ],\"spatialReference\" : {\"wkid\" : 4326}}"; - MapGeometry mp = GeometryEngine.jsonToGeometry(factory - .createParser(points)); - MultiPoint multipoint = (MultiPoint) mp.getGeometry(); - assertTrue(multipoint.getPointCount() == 4); - Point2D point2d; - point2d = multipoint.getXY(0); - assertTrue(point2d.x == 0.0 && point2d.y == 0.0); - point2d = multipoint.getXY(1); - assertTrue(point2d.x == 0.0 && point2d.y == 10.0); - point2d = multipoint.getXY(2); - assertTrue(point2d.x == 10.0 && point2d.y == 10.0); - point2d = multipoint.getXY(3); - assertTrue(point2d.x == 10.0 && point2d.y == 0.0); - assertTrue(multipoint.hasAttribute(VertexDescription.Semantics.Z)); - assertTrue(!multipoint.hasAttribute(VertexDescription.Semantics.M)); - double z = multipoint.getAttributeAsDbl( - VertexDescription.Semantics.Z, 0, 0); - assertTrue(z == 1); - SpatialReference spatial_reference = mp.getSpatialReference(); - assertTrue(spatial_reference.getID() == 4326); - } - - return bAnswer; - } - - boolean testPolyline() throws JsonParseException, IOException { - boolean bAnswer = true; - - Polyline polyline = new Polyline(); - polyline.startPath(-97.06138, 32.837); - polyline.lineTo(-97.06133, 32.836); - polyline.lineTo(-97.06124, 32.834); - polyline.lineTo(-97.06127, 32.832); - - polyline.startPath(-97.06326, 32.759); - polyline.lineTo(-97.06298, 32.755); - - { - JsonParser polylinePathsWgs84Parser = factory - .createParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, polyline)); - MapGeometry mPolylineWGS84MP = GeometryEngine - .jsonToGeometry(polylinePathsWgs84Parser); - - assertTrue(polyline.getPointCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPointCount()); - assertTrue(polyline.getPoint(0).getX() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(polyline.getPoint(0).getY() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(0).getY()); - - assertTrue(polyline.getPathCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPathCount()); - assertTrue(polyline.getSegmentCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount()); - assertTrue(polyline.getSegmentCount(0) == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount(0)); - assertTrue(polyline.getSegmentCount(1) == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount(1)); - - int lastIndex = polyline.getPointCount() - 1; - assertTrue(polyline.getPoint(lastIndex).getX() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(polyline.getPoint(lastIndex).getY() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP - .getSpatialReference().getID()); - - if (!checkResultSpatialRef(mPolylineWGS84MP, 4326, 0)) { - bAnswer = false; - } - } - - { - Polyline p = new Polyline(); - p.addAttribute(VertexDescription.Semantics.Z); - p.addAttribute(VertexDescription.Semantics.M); - String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, - p); - assertTrue(s - .equals("{\"hasZ\":true,\"hasM\":true,\"paths\":[],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - - p.startPath(0, 0); - p.lineTo(0, 1); - p.startPath(2, 2); - p.lineTo(3, 3); - - p.setAttribute(VertexDescription.Semantics.Z, 0, 0, 3); - p.setAttribute(VertexDescription.Semantics.M, 1, 0, 5); - s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); - assertTrue(s - .equals("{\"hasZ\":true,\"hasM\":true,\"paths\":[[[0,0,3,null],[0,1,0,5]],[[2,2,0,null],[3,3,0,null]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - } - - { - String paths = "{\"hasZ\" : true, \"paths\" : [ [ [0.0, 0.0,3], [0, 10.0,3], [10.0, 10.0,3, 6666], [10.0, 0.0,3, 6666] ], [ [1.0, 1,3], [1.0, 9.0,3], [9.0, 9.0,3], [1.0, 9.0,3] ] ], \"spatialReference\" : {\"wkid\" : 4326}, \"hasM\" : false}"; - MapGeometry mapGeometry = GeometryEngine.jsonToGeometry(factory - .createParser(paths)); - Polyline p = (Polyline) mapGeometry.getGeometry(); - assertTrue(p.getPathCount() == 2); - @SuppressWarnings("unused") - int count = p.getPathCount(); - assertTrue(p.getPointCount() == 8); - assertTrue(p.hasAttribute(VertexDescription.Semantics.Z)); - assertTrue(!p.hasAttribute(VertexDescription.Semantics.M)); - double z = p.getAttributeAsDbl(VertexDescription.Semantics.Z, 0, 0); - assertTrue(z == 3); - double length = p.calculateLength2D(); - assertTrue(Math.abs(length - 54.0) <= 0.001); - SpatialReference spatial_reference = mapGeometry - .getSpatialReference(); - assertTrue(spatial_reference.getID() == 4326); - } - - return bAnswer; - } - - boolean testPolygon() throws JsonParseException, IOException { - boolean bAnswer = true; - - Polygon polygon = new Polygon(); - polygon.startPath(-97.06138, 32.837); - polygon.lineTo(-97.06133, 32.836); - polygon.lineTo(-97.06124, 32.834); - polygon.lineTo(-97.06127, 32.832); - - polygon.startPath(-97.06326, 32.759); - polygon.lineTo(-97.06298, 32.755); - - { - JsonParser polygonPathsWgs84Parser = factory - .createParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, polygon)); - MapGeometry mPolygonWGS84MP = GeometryEngine - .jsonToGeometry(polygonPathsWgs84Parser); - - assertTrue(polygon.getPointCount() + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPointCount()); - assertTrue(polygon.getPoint(0).getX() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(polygon.getPoint(0).getY() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(0).getY()); - - assertTrue(polygon.getPathCount() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPathCount()); - assertTrue(polygon.getSegmentCount() + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount()); - assertTrue(polygon.getSegmentCount(0) == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount(0)); - assertTrue(polygon.getSegmentCount(1) + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount(1)); - - int lastIndex = polygon.getPointCount() - 1; - assertTrue(polygon.getPoint(lastIndex).getX() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(polygon.getPoint(lastIndex).getY() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP - .getSpatialReference().getID()); - - if (!checkResultSpatialRef(mPolygonWGS84MP, 4326, 0)) { - bAnswer = false; - } - } - - { - Polygon p = new Polygon(); - p.addAttribute(VertexDescription.Semantics.Z); - p.addAttribute(VertexDescription.Semantics.M); - String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, - p); - assertTrue(s - .equals("{\"hasZ\":true,\"hasM\":true,\"rings\":[],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - - p.startPath(0, 0); - p.lineTo(0, 1); - p.lineTo(4, 4); - p.startPath(2, 2); - p.lineTo(3, 3); - p.lineTo(7, 8); - - p.setAttribute(VertexDescription.Semantics.Z, 0, 0, 3); - p.setAttribute(VertexDescription.Semantics.M, 1, 0, 7); - p.setAttribute(VertexDescription.Semantics.M, 2, 0, 5); - p.setAttribute(VertexDescription.Semantics.M, 5, 0, 5); - s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); - assertTrue(s - .equals("{\"hasZ\":true,\"hasM\":true,\"rings\":[[[0,0,3,null],[0,1,0,7],[4,4,0,5],[0,0,3,null]],[[2,2,0,null],[3,3,0,null],[7,8,0,5],[2,2,0,null]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - } - - { - // Test Import Polygon from Polygon - String rings = "{\"hasZ\": true, \"rings\" : [ [ [0,0, 5], [0.0, 10.0, 5], [10.0,10.0, 5, 66666], [10.0,0.0, 5] ], [ [12, 12] ], [ [13 , 17], [13 , 17] ], [ [1.0, 1.0, 5, 66666], [9.0,1.0, 5], [9.0,9.0, 5], [1.0,9.0, 5], [1.0, 1.0, 5] ] ] }"; - MapGeometry mapGeometry = GeometryEngine.jsonToGeometry(factory - .createParser(rings)); - Polygon p = (Polygon) mapGeometry.getGeometry(); - @SuppressWarnings("unused") - double area = p.calculateArea2D(); - @SuppressWarnings("unused") - double length = p.calculateLength2D(); - assertTrue(p.getPathCount() == 4); - int count = p.getPointCount(); - assertTrue(count == 15); - assertTrue(p.hasAttribute(VertexDescription.Semantics.Z)); - assertTrue(!p.hasAttribute(VertexDescription.Semantics.M)); - } - - return bAnswer; - } - - boolean testEnvelope() throws JsonParseException, IOException { - boolean bAnswer = true; - - Envelope envelope = new Envelope(); - envelope.setCoords(-109.55, 25.76, -86.39, 49.94); - - { - JsonParser envelopeWGS84Parser = factory - .createParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, envelope)); - MapGeometry envelopeWGS84MP = GeometryEngine - .jsonToGeometry(envelopeWGS84Parser); - assertTrue(envelope.isEmpty() == envelopeWGS84MP.getGeometry() - .isEmpty()); - assertTrue(envelope.getXMax() == ((Envelope) envelopeWGS84MP - .getGeometry()).getXMax()); - assertTrue(envelope.getYMax() == ((Envelope) envelopeWGS84MP - .getGeometry()).getYMax()); - assertTrue(envelope.getXMin() == ((Envelope) envelopeWGS84MP - .getGeometry()).getXMin()); - assertTrue(envelope.getYMin() == ((Envelope) envelopeWGS84MP - .getGeometry()).getYMin()); - assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP - .getSpatialReference().getID()); - if (!checkResultSpatialRef(envelopeWGS84MP, 4326, 0)) { - bAnswer = false; - } - } - - {// export - Envelope e = new Envelope(); - e.addAttribute(VertexDescription.Semantics.Z); - e.addAttribute(VertexDescription.Semantics.M); - String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, - e); - assertTrue(s - .equals("{\"xmin\":null,\"ymin\":null,\"xmax\":null,\"ymax\":null,\"zmin\":null,\"zmax\":null,\"mmin\":null,\"mmax\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - - e.setCoords(0, 1, 2, 3); - - Envelope1D z = new Envelope1D(); - Envelope1D m = new Envelope1D(); - z.setCoords(5, 7); - m.setCoords(11, 13); - - e.setInterval(VertexDescription.Semantics.Z, 0, z); - e.setInterval(VertexDescription.Semantics.M, 0, m); - s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, e); - assertTrue(s - .equals("{\"xmin\":0,\"ymin\":1,\"xmax\":2,\"ymax\":3,\"zmin\":5,\"zmax\":7,\"mmin\":11,\"mmax\":13,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); - } - - {// import - String s = "{\"xmin\":0.0,\"ymin\":1.0,\"xmax\":2.0,\"ymax\":3.0,\"zmin\":5.0,\"zmax\":7.0,\"mmin\":11.0,\"mmax\":13.0,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; - JsonParser parser = factory.createParser(s); - MapGeometry map_env = GeometryEngine.jsonToGeometry(parser); - Envelope env = (Envelope) map_env.getGeometry(); - Envelope1D z = env.queryInterval(VertexDescription.Semantics.Z, 0); - Envelope1D m = env.queryInterval(VertexDescription.Semantics.M, 0); - assertTrue(z.vmin == 5.0); - assertTrue(z.vmax == 7.0); - assertTrue(m.vmin == 11.0); - assertTrue(m.vmax == 13.0); - } - - { - String s = "{ \"zmin\" : 33, \"xmin\" : -109.55, \"zmax\" : 53, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94, \"mmax\" : 13}"; - JsonParser parser = factory.createParser(s); - MapGeometry map_env = GeometryEngine.jsonToGeometry(parser); - Envelope env = (Envelope) map_env.getGeometry(); - Envelope2D e = new Envelope2D(); - env.queryEnvelope2D(e); - assertTrue(e.xmin == -109.55 && e.ymin == 25.76 && e.xmax == -86.39 - && e.ymax == 49.94); - - Envelope1D e1D; - assertTrue(env.hasAttribute(VertexDescription.Semantics.Z)); - e1D = env.queryInterval(VertexDescription.Semantics.Z, 0); - assertTrue(e1D.vmin == 33 && e1D.vmax == 53); - - assertTrue(!env.hasAttribute(VertexDescription.Semantics.M)); - } - - return bAnswer; - } - - boolean testCR181369() throws JsonParseException, IOException { - // CR181369 - boolean bAnswer = true; - - String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; - JsonParser jsonParserPointAndWKT = factory - .createParser(jsonStringPointAndWKT); - MapGeometry mapGeom2 = GeometryEngine - .jsonToGeometry(jsonParserPointAndWKT); - String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson( - mapGeom2.getSpatialReference(), mapGeom2.getGeometry()); - JsonParser jsonParserPointAndWKT2 = factory - .createParser(jsonStringPointAndWKT2); - MapGeometry mapGeom3 = GeometryEngine - .jsonToGeometry(jsonParserPointAndWKT2); - assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3 - .getGeometry()).getX()); - assertTrue(((Point) mapGeom2.getGeometry()).getY() == ((Point) mapGeom3 - .getGeometry()).getY()); - - String s1 = mapGeom2.getSpatialReference().getText(); - String s2 = mapGeom3.getSpatialReference().getText(); - assertTrue(s1.equals(s2)); - - int id2 = mapGeom2.getSpatialReference().getID(); - int id3 = mapGeom3.getSpatialReference().getID(); - assertTrue(id2 == id3); - if (!checkResultSpatialRef(mapGeom3, mapGeom2.getSpatialReference() - .getID(), 0)) { - bAnswer = false; - } - return bAnswer; - } - - boolean checkResultSpatialRef(MapGeometry mapGeometry, int expectWki1, - int expectWki2) { - SpatialReference sr = mapGeometry.getSpatialReference(); - String Wkt = sr.getText(); - int wki1 = sr.getLatestID(); - if (!(wki1 == expectWki1 || wki1 == expectWki2)) - return false; - if (!(Wkt != null && Wkt.length() > 0)) - return false; - SpatialReference sr2 = SpatialReference.create(Wkt); - int wki2 = sr2.getID(); - if (expectWki2 > 0) { - if (!(wki2 == expectWki1 || wki2 == expectWki2)) - return false; - } else { - if (!(wki2 == expectWki1)) - return false; - } - return true; - } -} +package com.esri.core.geometry; + +import java.io.IOException; +import junit.framework.TestCase; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; + +public class TestGeomToJSonExportSRFromWkiOrWkt_CR181369 extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + JsonFactory factory = new JsonFactory(); + SpatialReference spatialReferenceWebMerc1 = SpatialReference.create(102100); + SpatialReference spatialReferenceWebMerc2 = SpatialReference + .create(spatialReferenceWebMerc1.getLatestID()); + SpatialReference spatialReferenceWGS84 = SpatialReference.create(4326); + + @Test + public void testLocalExport() + throws JsonParseException, IOException { + String s = OperatorExportToJson.local().execute(null, new Point(1000000.2, 2000000.3)); + //assertTrue(s.contains(".")); + //assertFalse(s.contains(",")); + Polyline line = new Polyline(); + line.startPath(1.1, 2.2); + line.lineTo(2.3, 4.5); + String s1 = OperatorExportToJson.local().execute(null, line); + assertTrue(s.contains(".")); + } + + boolean testPoint() throws JsonParseException, IOException { + boolean bAnswer = true; + Point point1 = new Point(10.0, 20.0); + Point pointEmpty = new Point(); + { + JsonParser pointWebMerc1Parser = factory + .createParser(GeometryEngine.geometryToJson( + spatialReferenceWebMerc1, point1)); + MapGeometry pointWebMerc1MP = GeometryEngine + .jsonToGeometry(pointWebMerc1Parser); + assertTrue(point1.getX() == ((Point) pointWebMerc1MP.getGeometry()) + .getX()); + assertTrue(point1.getY() == ((Point) pointWebMerc1MP.getGeometry()) + .getY()); + assertTrue(spatialReferenceWebMerc1.getID() == pointWebMerc1MP + .getSpatialReference().getID() + || pointWebMerc1MP.getSpatialReference().getID() == 3857); + + if (!checkResultSpatialRef(pointWebMerc1MP, 102100, 3857)) { + bAnswer = false; + } + + pointWebMerc1Parser = factory.createParser(GeometryEngine + .geometryToJson(null, point1)); + pointWebMerc1MP = GeometryEngine + .jsonToGeometry(pointWebMerc1Parser); + assertTrue(null == pointWebMerc1MP.getSpatialReference()); + + if (pointWebMerc1MP.getSpatialReference() != null) { + if (!checkResultSpatialRef(pointWebMerc1MP, 102100, 3857)) { + bAnswer = false; + } + } + + String pointEmptyString = GeometryEngine.geometryToJson( + spatialReferenceWebMerc1, pointEmpty); + pointWebMerc1Parser = factory.createParser(pointEmptyString); + } + + JsonParser pointWebMerc2Parser = factory + .createParser(GeometryEngine.geometryToJson( + spatialReferenceWebMerc2, point1)); + MapGeometry pointWebMerc2MP = GeometryEngine + .jsonToGeometry(pointWebMerc2Parser); + assertTrue(point1.getX() == ((Point) pointWebMerc2MP.getGeometry()) + .getX()); + assertTrue(point1.getY() == ((Point) pointWebMerc2MP.getGeometry()) + .getY()); + assertTrue(spatialReferenceWebMerc2.getLatestID() == pointWebMerc2MP + .getSpatialReference().getLatestID()); + if (!checkResultSpatialRef(pointWebMerc2MP, + spatialReferenceWebMerc2.getLatestID(), 0)) { + bAnswer = false; + } + + { + JsonParser pointWgs84Parser = factory + .createParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, point1)); + MapGeometry pointWgs84MP = GeometryEngine + .jsonToGeometry(pointWgs84Parser); + assertTrue(point1.getX() == ((Point) pointWgs84MP.getGeometry()) + .getX()); + assertTrue(point1.getY() == ((Point) pointWgs84MP.getGeometry()) + .getY()); + assertTrue(spatialReferenceWGS84.getID() == pointWgs84MP + .getSpatialReference().getID()); + if (!checkResultSpatialRef(pointWgs84MP, 4326, 0)) { + bAnswer = false; + } + } + + { + Point p = new Point(); + String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, + p); + assertTrue(s + .equals("{\"x\":null,\"y\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + + p.addAttribute(VertexDescription.Semantics.Z); + p.addAttribute(VertexDescription.Semantics.M); + s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); + assertTrue(s + .equals("{\"x\":null,\"y\":null,\"z\":null,\"m\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + + } + + { + Point p = new Point(10.0, 20.0, 30.0); + p.addAttribute(VertexDescription.Semantics.M); + String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, + p); + assertTrue(s + .equals("{\"x\":10,\"y\":20,\"z\":30,\"m\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + } + + {// import + String s = "{\"x\":0.0,\"y\":1.0,\"z\":5.0,\"m\":11.0,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; + JsonParser parser = factory.createParser(s); + MapGeometry map_pt = GeometryEngine.jsonToGeometry(parser); + Point pt = (Point) map_pt.getGeometry(); + assertTrue(pt.getX() == 0.0); + assertTrue(pt.getY() == 1.0); + assertTrue(pt.getZ() == 5.0); + assertTrue(pt.getM() == 11.0); + } + + { + String s = "{\"x\" : 5.0, \"y\" : null, \"spatialReference\" : {\"wkid\" : 4326}} "; + JsonParser parser = factory.createParser(s); + MapGeometry map_pt = GeometryEngine.jsonToGeometry(parser); + Point pt = (Point) map_pt.getGeometry(); + assertTrue(pt.isEmpty()); + SpatialReference spatial_reference = map_pt.getSpatialReference(); + assertTrue(spatial_reference.getID() == 4326); + } + + return bAnswer; + } + + boolean testMultiPoint() throws JsonParseException, IOException { + boolean bAnswer = true; + + MultiPoint multiPoint1 = new MultiPoint(); + multiPoint1.add(-97.06138, 32.837); + multiPoint1.add(-97.06133, 32.836); + multiPoint1.add(-97.06124, 32.834); + multiPoint1.add(-97.06127, 32.832); + + { + String s = GeometryEngine.geometryToJson(spatialReferenceWGS84, + multiPoint1); + JsonParser mPointWgs84Parser = factory.createParser(s); + MapGeometry mPointWgs84MP = GeometryEngine + .jsonToGeometry(mPointWgs84Parser); + assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPointCount()); + assertTrue(multiPoint1.getPoint(0).getX() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(0).getX()); + assertTrue(multiPoint1.getPoint(0).getY() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(0).getY()); + int lastIndex = multiPoint1.getPointCount() - 1; + assertTrue(multiPoint1.getPoint(lastIndex).getX() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(lastIndex).getX()); + assertTrue(multiPoint1.getPoint(lastIndex).getY() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP + .getSpatialReference().getID()); + if (!checkResultSpatialRef(mPointWgs84MP, 4326, 0)) { + bAnswer = false; + } + + } + + { + MultiPoint p = new MultiPoint(); + p.addAttribute(VertexDescription.Semantics.Z); + p.addAttribute(VertexDescription.Semantics.M); + String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, + p); + assertTrue(s + .equals("{\"hasZ\":true,\"hasM\":true,\"points\":[],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + + p.add(10.0, 20.0, 30.0); + p.add(20.0, 40.0, 60.0); + s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); + assertTrue(s + .equals("{\"hasZ\":true,\"hasM\":true,\"points\":[[10,20,30,null],[20,40,60,null]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + } + { + String points = "{\"hasM\" : false, \"hasZ\" : true, \"uncle remus\" : null, \"points\" : [ [0,0,1], [0.0,10.0,1], [10.0,10.0,1], [10.0,0.0,1, 6666] ],\"spatialReference\" : {\"wkid\" : 4326}}"; + MapGeometry mp = GeometryEngine.jsonToGeometry(factory + .createParser(points)); + MultiPoint multipoint = (MultiPoint) mp.getGeometry(); + assertTrue(multipoint.getPointCount() == 4); + Point2D point2d; + point2d = multipoint.getXY(0); + assertTrue(point2d.x == 0.0 && point2d.y == 0.0); + point2d = multipoint.getXY(1); + assertTrue(point2d.x == 0.0 && point2d.y == 10.0); + point2d = multipoint.getXY(2); + assertTrue(point2d.x == 10.0 && point2d.y == 10.0); + point2d = multipoint.getXY(3); + assertTrue(point2d.x == 10.0 && point2d.y == 0.0); + assertTrue(multipoint.hasAttribute(VertexDescription.Semantics.Z)); + assertTrue(!multipoint.hasAttribute(VertexDescription.Semantics.M)); + double z = multipoint.getAttributeAsDbl( + VertexDescription.Semantics.Z, 0, 0); + assertTrue(z == 1); + SpatialReference spatial_reference = mp.getSpatialReference(); + assertTrue(spatial_reference.getID() == 4326); + } + + return bAnswer; + } + + boolean testPolyline() throws JsonParseException, IOException { + boolean bAnswer = true; + + Polyline polyline = new Polyline(); + polyline.startPath(-97.06138, 32.837); + polyline.lineTo(-97.06133, 32.836); + polyline.lineTo(-97.06124, 32.834); + polyline.lineTo(-97.06127, 32.832); + + polyline.startPath(-97.06326, 32.759); + polyline.lineTo(-97.06298, 32.755); + + { + JsonParser polylinePathsWgs84Parser = factory + .createParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, polyline)); + MapGeometry mPolylineWGS84MP = GeometryEngine + .jsonToGeometry(polylinePathsWgs84Parser); + + assertTrue(polyline.getPointCount() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPointCount()); + assertTrue(polyline.getPoint(0).getX() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(0).getX()); + assertTrue(polyline.getPoint(0).getY() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(0).getY()); + + assertTrue(polyline.getPathCount() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPathCount()); + assertTrue(polyline.getSegmentCount() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getSegmentCount()); + assertTrue(polyline.getSegmentCount(0) == ((Polyline) mPolylineWGS84MP + .getGeometry()).getSegmentCount(0)); + assertTrue(polyline.getSegmentCount(1) == ((Polyline) mPolylineWGS84MP + .getGeometry()).getSegmentCount(1)); + + int lastIndex = polyline.getPointCount() - 1; + assertTrue(polyline.getPoint(lastIndex).getX() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(lastIndex).getX()); + assertTrue(polyline.getPoint(lastIndex).getY() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP + .getSpatialReference().getID()); + + if (!checkResultSpatialRef(mPolylineWGS84MP, 4326, 0)) { + bAnswer = false; + } + } + + { + Polyline p = new Polyline(); + p.addAttribute(VertexDescription.Semantics.Z); + p.addAttribute(VertexDescription.Semantics.M); + String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, + p); + assertTrue(s + .equals("{\"hasZ\":true,\"hasM\":true,\"paths\":[],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + + p.startPath(0, 0); + p.lineTo(0, 1); + p.startPath(2, 2); + p.lineTo(3, 3); + + p.setAttribute(VertexDescription.Semantics.Z, 0, 0, 3); + p.setAttribute(VertexDescription.Semantics.M, 1, 0, 5); + s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); + assertTrue(s + .equals("{\"hasZ\":true,\"hasM\":true,\"paths\":[[[0,0,3,null],[0,1,0,5]],[[2,2,0,null],[3,3,0,null]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + } + + { + String paths = "{\"hasZ\" : true, \"paths\" : [ [ [0.0, 0.0,3], [0, 10.0,3], [10.0, 10.0,3, 6666], [10.0, 0.0,3, 6666] ], [ [1.0, 1,3], [1.0, 9.0,3], [9.0, 9.0,3], [1.0, 9.0,3] ] ], \"spatialReference\" : {\"wkid\" : 4326}, \"hasM\" : false}"; + MapGeometry mapGeometry = GeometryEngine.jsonToGeometry(factory + .createParser(paths)); + Polyline p = (Polyline) mapGeometry.getGeometry(); + assertTrue(p.getPathCount() == 2); + @SuppressWarnings("unused") + int count = p.getPathCount(); + assertTrue(p.getPointCount() == 8); + assertTrue(p.hasAttribute(VertexDescription.Semantics.Z)); + assertTrue(!p.hasAttribute(VertexDescription.Semantics.M)); + double z = p.getAttributeAsDbl(VertexDescription.Semantics.Z, 0, 0); + assertTrue(z == 3); + double length = p.calculateLength2D(); + assertTrue(Math.abs(length - 54.0) <= 0.001); + SpatialReference spatial_reference = mapGeometry + .getSpatialReference(); + assertTrue(spatial_reference.getID() == 4326); + } + + return bAnswer; + } + + boolean testPolygon() throws JsonParseException, IOException { + boolean bAnswer = true; + + Polygon polygon = new Polygon(); + polygon.startPath(-97.06138, 32.837); + polygon.lineTo(-97.06133, 32.836); + polygon.lineTo(-97.06124, 32.834); + polygon.lineTo(-97.06127, 32.832); + + polygon.startPath(-97.06326, 32.759); + polygon.lineTo(-97.06298, 32.755); + + { + JsonParser polygonPathsWgs84Parser = factory + .createParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, polygon)); + MapGeometry mPolygonWGS84MP = GeometryEngine + .jsonToGeometry(polygonPathsWgs84Parser); + + assertTrue(polygon.getPointCount() + 1 == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPointCount()); + assertTrue(polygon.getPoint(0).getX() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(0).getX()); + assertTrue(polygon.getPoint(0).getY() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(0).getY()); + + assertTrue(polygon.getPathCount() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPathCount()); + assertTrue(polygon.getSegmentCount() + 1 == ((Polygon) mPolygonWGS84MP + .getGeometry()).getSegmentCount()); + assertTrue(polygon.getSegmentCount(0) == ((Polygon) mPolygonWGS84MP + .getGeometry()).getSegmentCount(0)); + assertTrue(polygon.getSegmentCount(1) + 1 == ((Polygon) mPolygonWGS84MP + .getGeometry()).getSegmentCount(1)); + + int lastIndex = polygon.getPointCount() - 1; + assertTrue(polygon.getPoint(lastIndex).getX() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(lastIndex).getX()); + assertTrue(polygon.getPoint(lastIndex).getY() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP + .getSpatialReference().getID()); + + if (!checkResultSpatialRef(mPolygonWGS84MP, 4326, 0)) { + bAnswer = false; + } + } + + { + Polygon p = new Polygon(); + p.addAttribute(VertexDescription.Semantics.Z); + p.addAttribute(VertexDescription.Semantics.M); + String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, + p); + assertTrue(s + .equals("{\"hasZ\":true,\"hasM\":true,\"rings\":[],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + + p.startPath(0, 0); + p.lineTo(0, 1); + p.lineTo(4, 4); + p.startPath(2, 2); + p.lineTo(3, 3); + p.lineTo(7, 8); + + p.setAttribute(VertexDescription.Semantics.Z, 0, 0, 3); + p.setAttribute(VertexDescription.Semantics.M, 1, 0, 7); + p.setAttribute(VertexDescription.Semantics.M, 2, 0, 5); + p.setAttribute(VertexDescription.Semantics.M, 5, 0, 5); + s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, p); + assertTrue(s + .equals("{\"hasZ\":true,\"hasM\":true,\"rings\":[[[0,0,3,null],[0,1,0,7],[4,4,0,5],[0,0,3,null]],[[2,2,0,null],[3,3,0,null],[7,8,0,5],[2,2,0,null]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + } + + { + // Test Import Polygon from Polygon + String rings = "{\"hasZ\": true, \"rings\" : [ [ [0,0, 5], [0.0, 10.0, 5], [10.0,10.0, 5, 66666], [10.0,0.0, 5] ], [ [12, 12] ], [ [13 , 17], [13 , 17] ], [ [1.0, 1.0, 5, 66666], [9.0,1.0, 5], [9.0,9.0, 5], [1.0,9.0, 5], [1.0, 1.0, 5] ] ] }"; + MapGeometry mapGeometry = GeometryEngine.jsonToGeometry(factory + .createParser(rings)); + Polygon p = (Polygon) mapGeometry.getGeometry(); + @SuppressWarnings("unused") + double area = p.calculateArea2D(); + @SuppressWarnings("unused") + double length = p.calculateLength2D(); + assertTrue(p.getPathCount() == 4); + int count = p.getPointCount(); + assertTrue(count == 15); + assertTrue(p.hasAttribute(VertexDescription.Semantics.Z)); + assertTrue(!p.hasAttribute(VertexDescription.Semantics.M)); + } + + return bAnswer; + } + + boolean testEnvelope() throws JsonParseException, IOException { + boolean bAnswer = true; + + Envelope envelope = new Envelope(); + envelope.setCoords(-109.55, 25.76, -86.39, 49.94); + + { + JsonParser envelopeWGS84Parser = factory + .createParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, envelope)); + MapGeometry envelopeWGS84MP = GeometryEngine + .jsonToGeometry(envelopeWGS84Parser); + assertTrue(envelope.isEmpty() == envelopeWGS84MP.getGeometry() + .isEmpty()); + assertTrue(envelope.getXMax() == ((Envelope) envelopeWGS84MP + .getGeometry()).getXMax()); + assertTrue(envelope.getYMax() == ((Envelope) envelopeWGS84MP + .getGeometry()).getYMax()); + assertTrue(envelope.getXMin() == ((Envelope) envelopeWGS84MP + .getGeometry()).getXMin()); + assertTrue(envelope.getYMin() == ((Envelope) envelopeWGS84MP + .getGeometry()).getYMin()); + assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP + .getSpatialReference().getID()); + if (!checkResultSpatialRef(envelopeWGS84MP, 4326, 0)) { + bAnswer = false; + } + } + + {// export + Envelope e = new Envelope(); + e.addAttribute(VertexDescription.Semantics.Z); + e.addAttribute(VertexDescription.Semantics.M); + String s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, + e); + assertTrue(s + .equals("{\"xmin\":null,\"ymin\":null,\"xmax\":null,\"ymax\":null,\"zmin\":null,\"zmax\":null,\"mmin\":null,\"mmax\":null,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + + e.setCoords(0, 1, 2, 3); + + Envelope1D z = new Envelope1D(); + Envelope1D m = new Envelope1D(); + z.setCoords(5, 7); + m.setCoords(11, 13); + + e.setInterval(VertexDescription.Semantics.Z, 0, z); + e.setInterval(VertexDescription.Semantics.M, 0, m); + s = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, e); + assertTrue(s + .equals("{\"xmin\":0,\"ymin\":1,\"xmax\":2,\"ymax\":3,\"zmin\":5,\"zmax\":7,\"mmin\":11,\"mmax\":13,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}")); + } + + {// import + String s = "{\"xmin\":0.0,\"ymin\":1.0,\"xmax\":2.0,\"ymax\":3.0,\"zmin\":5.0,\"zmax\":7.0,\"mmin\":11.0,\"mmax\":13.0,\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; + JsonParser parser = factory.createParser(s); + MapGeometry map_env = GeometryEngine.jsonToGeometry(parser); + Envelope env = (Envelope) map_env.getGeometry(); + Envelope1D z = env.queryInterval(VertexDescription.Semantics.Z, 0); + Envelope1D m = env.queryInterval(VertexDescription.Semantics.M, 0); + assertTrue(z.vmin == 5.0); + assertTrue(z.vmax == 7.0); + assertTrue(m.vmin == 11.0); + assertTrue(m.vmax == 13.0); + } + + { + String s = "{ \"zmin\" : 33, \"xmin\" : -109.55, \"zmax\" : 53, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94, \"mmax\" : 13}"; + JsonParser parser = factory.createParser(s); + MapGeometry map_env = GeometryEngine.jsonToGeometry(parser); + Envelope env = (Envelope) map_env.getGeometry(); + Envelope2D e = new Envelope2D(); + env.queryEnvelope2D(e); + assertTrue(e.xmin == -109.55 && e.ymin == 25.76 && e.xmax == -86.39 + && e.ymax == 49.94); + + Envelope1D e1D; + assertTrue(env.hasAttribute(VertexDescription.Semantics.Z)); + e1D = env.queryInterval(VertexDescription.Semantics.Z, 0); + assertTrue(e1D.vmin == 33 && e1D.vmax == 53); + + assertTrue(!env.hasAttribute(VertexDescription.Semantics.M)); + } + + return bAnswer; + } + + boolean testCR181369() throws JsonParseException, IOException { + // CR181369 + boolean bAnswer = true; + + String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; + JsonParser jsonParserPointAndWKT = factory + .createParser(jsonStringPointAndWKT); + MapGeometry mapGeom2 = GeometryEngine + .jsonToGeometry(jsonParserPointAndWKT); + String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson( + mapGeom2.getSpatialReference(), mapGeom2.getGeometry()); + JsonParser jsonParserPointAndWKT2 = factory + .createParser(jsonStringPointAndWKT2); + MapGeometry mapGeom3 = GeometryEngine + .jsonToGeometry(jsonParserPointAndWKT2); + assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3 + .getGeometry()).getX()); + assertTrue(((Point) mapGeom2.getGeometry()).getY() == ((Point) mapGeom3 + .getGeometry()).getY()); + + String s1 = mapGeom2.getSpatialReference().getText(); + String s2 = mapGeom3.getSpatialReference().getText(); + assertTrue(s1.equals(s2)); + + int id2 = mapGeom2.getSpatialReference().getID(); + int id3 = mapGeom3.getSpatialReference().getID(); + assertTrue(id2 == id3); + if (!checkResultSpatialRef(mapGeom3, mapGeom2.getSpatialReference() + .getID(), 0)) { + bAnswer = false; + } + return bAnswer; + } + + boolean checkResultSpatialRef(MapGeometry mapGeometry, int expectWki1, + int expectWki2) { + SpatialReference sr = mapGeometry.getSpatialReference(); + String Wkt = sr.getText(); + int wki1 = sr.getLatestID(); + if (!(wki1 == expectWki1 || wki1 == expectWki2)) + return false; + if (!(Wkt != null && Wkt.length() > 0)) + return false; + SpatialReference sr2 = SpatialReference.create(Wkt); + int wki2 = sr2.getID(); + if (expectWki2 > 0) { + if (!(wki2 == expectWki1 || wki2 == expectWki2)) + return false; + } else { + if (!(wki2 == expectWki1)) + return false; + } + return true; + } +} diff --git a/src/test/java/com/esri/core/geometry/TestJSonGeometry.java b/src/test/java/com/esri/core/geometry/TestJSonGeometry.java index 571a103e..a996575f 100644 --- a/src/test/java/com/esri/core/geometry/TestJSonGeometry.java +++ b/src/test/java/com/esri/core/geometry/TestJSonGeometry.java @@ -1,47 +1,48 @@ -package com.esri.core.geometry; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import junit.framework.TestCase; -import org.junit.Test; - -public class TestJSonGeometry extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void testGetSpatialReferenceFor4326() { - String completeStr = "GEOGCS[\"GCS_Sphere\",DATUM[\"D_Sphere\"," - + "SPHEROID[\"Sphere\",6371000.0,0.0]],PRIMEM[\"Greenwich\",0.0]," - + "UNIT[\"Degree\",0.0174532925199433]]"; - - // 4326 GCS_WGS_1984 - SpatialReference sr = SpatialReference.create(completeStr); - assertNotNull(sr); - } - } - -final class HashMapClassForTesting { - static Map SR_WKI_WKTs = new HashMap() { - /** - * added to get rid of warning - */ - private static final long serialVersionUID = 8630934425353750539L; - - { - put(4035, - "GEOGCS[\"GCS_Sphere\",DATUM[\"D_Sphere\"," - + "SPHEROID[\"Sphere\",6371000.0,0.0]],PRIMEM[\"Greenwich\",0.0]," - + "UNIT[\"Degree\",0.0174532925199433]]"); - } - }; -} +package com.esri.core.geometry; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import junit.framework.TestCase; +import org.junit.Test; + +public class TestJSonGeometry extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testGetSpatialReferenceFor4326() { + String completeStr = "GEOGCS[\"GCS_Sphere\",DATUM[\"D_Sphere\"," + + "SPHEROID[\"Sphere\",6371000.0,0.0]],PRIMEM[\"Greenwich\",0.0]," + + "UNIT[\"Degree\",0.0174532925199433]]"; + + // 4326 GCS_WGS_1984 + SpatialReference sr = SpatialReference.create(completeStr); + assertNotNull(sr); + } + +} + +final class HashMapClassForTesting { + static Map SR_WKI_WKTs = new HashMap() { + /** + * added to get rid of warning + */ + private static final long serialVersionUID = 8630934425353750539L; + + { + put(4035, + "GEOGCS[\"GCS_Sphere\",DATUM[\"D_Sphere\"," + + "SPHEROID[\"Sphere\",6371000.0,0.0]],PRIMEM[\"Greenwich\",0.0]," + + "UNIT[\"Degree\",0.0174532925199433]]"); + } + }; +} diff --git a/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java b/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java index 8abd75cf..8b036785 100644 --- a/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java +++ b/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java @@ -1,124 +1,124 @@ -package com.esri.core.geometry; - -import java.io.IOException; -import junit.framework.TestCase; -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; - -public class TestJSonToGeomFromWkiOrWkt_CR177613 extends TestCase { - JsonFactory factory = new JsonFactory(); - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void testPolygonWithEmptyWKT_NoWKI() throws JsonParseException, - IOException { - String jsonStringPg = "{ \"rings\" :[ [ [-97.06138,32.837], [-97.06133,32.836], " - + "[-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], " - + "[ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], " - + "\"spatialReference\" : {\"wkt\" : \"\"}}"; - JsonParser jsonParserPg = factory.createParser(jsonStringPg); - jsonParserPg.nextToken(); - - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); - Utils.showProjectedGeometryInfo(mapGeom); - SpatialReference sr = mapGeom.getSpatialReference(); - assertTrue(sr == null); - } - - @Test - public void testOnlyWKI() throws JsonParseException, IOException { - String jsonStringSR = "{\"wkid\" : 4326}"; - JsonParser jsonParserSR = factory.createJsonParser(jsonStringSR); - jsonParserSR.nextToken(); - - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserSR); - Utils.showProjectedGeometryInfo(mapGeom); - SpatialReference sr = mapGeom.getSpatialReference(); - assertTrue(sr == null); - } - - @Test - public void testMP2onCR175871() throws Exception { - Polygon pg = new Polygon(); - pg.startPath(-50, 10); - pg.lineTo(-50, 12); - pg.lineTo(-45, 12); - pg.lineTo(-45, 10); - - Polygon pg1 = new Polygon(); - pg1.startPath(-45, 10); - pg1.lineTo(-40, 10); - pg1.lineTo(-40, 8); - pg.add(pg1, false); - - try { - String jSonStr = GeometryEngine.geometryToJson(4326, pg); - JsonFactory jf = new JsonFactory(); - - JsonParser jp = jf.createJsonParser(jSonStr); - jp.nextToken(); - MapGeometry mg = GeometryEngine.jsonToGeometry(jp); - Geometry gm = mg.getGeometry(); - assertEquals(Geometry.Type.Polygon, gm.getType()); - - Polygon pgNew = (Polygon) gm; - - assertEquals(pgNew.getPathCount(), pg.getPathCount()); - assertEquals(pgNew.getPointCount(), pg.getPointCount()); - assertEquals(pgNew.getSegmentCount(), pg.getSegmentCount()); - - assertEquals(pgNew.getPoint(0).getX(), pg.getPoint(0).getX(), - 0.000000001); - assertEquals(pgNew.getPoint(1).getX(), pg.getPoint(1).getX(), - 0.000000001); - assertEquals(pgNew.getPoint(2).getX(), pg.getPoint(2).getX(), - 0.000000001); - assertEquals(pgNew.getPoint(3).getX(), pg.getPoint(3).getX(), - 0.000000001); - - assertEquals(pgNew.getPoint(0).getY(), pg.getPoint(0).getY(), - 0.000000001); - assertEquals(pgNew.getPoint(1).getY(), pg.getPoint(1).getY(), - 0.000000001); - assertEquals(pgNew.getPoint(2).getY(), pg.getPoint(2).getY(), - 0.000000001); - assertEquals(pgNew.getPoint(3).getY(), pg.getPoint(3).getY(), - 0.000000001); - } catch (Exception ex) { - String err = ex.getMessage(); - System.out.print(err); - throw ex; - } - } - - public static int fromJsonToWkid(JsonParser parser) - throws JsonParseException, IOException { - int wkid = 0; - if (parser.getCurrentToken() != JsonToken.START_OBJECT) { - return 0; - } - - while (parser.nextToken() != JsonToken.END_OBJECT) { - String fieldName = parser.getCurrentName(); - - if ("wkid".equals(fieldName)) { - parser.nextToken(); - wkid = parser.getIntValue(); - } - } - return wkid; - } -} +package com.esri.core.geometry; + +import java.io.IOException; +import junit.framework.TestCase; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + +public class TestJSonToGeomFromWkiOrWkt_CR177613 extends TestCase { + JsonFactory factory = new JsonFactory(); + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testPolygonWithEmptyWKT_NoWKI() throws JsonParseException, + IOException { + String jsonStringPg = "{ \"rings\" :[ [ [-97.06138,32.837], [-97.06133,32.836], " + + "[-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], " + + "[ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], " + + "\"spatialReference\" : {\"wkt\" : \"\"}}"; + JsonParser jsonParserPg = factory.createParser(jsonStringPg); + jsonParserPg.nextToken(); + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); + Utils.showProjectedGeometryInfo(mapGeom); + SpatialReference sr = mapGeom.getSpatialReference(); + assertTrue(sr == null); + } + + @Test + public void testOnlyWKI() throws JsonParseException, IOException { + String jsonStringSR = "{\"wkid\" : 4326}"; + JsonParser jsonParserSR = factory.createJsonParser(jsonStringSR); + jsonParserSR.nextToken(); + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserSR); + Utils.showProjectedGeometryInfo(mapGeom); + SpatialReference sr = mapGeom.getSpatialReference(); + assertTrue(sr == null); + } + + @Test + public void testMP2onCR175871() throws Exception { + Polygon pg = new Polygon(); + pg.startPath(-50, 10); + pg.lineTo(-50, 12); + pg.lineTo(-45, 12); + pg.lineTo(-45, 10); + + Polygon pg1 = new Polygon(); + pg1.startPath(-45, 10); + pg1.lineTo(-40, 10); + pg1.lineTo(-40, 8); + pg.add(pg1, false); + + try { + String jSonStr = GeometryEngine.geometryToJson(4326, pg); + JsonFactory jf = new JsonFactory(); + + JsonParser jp = jf.createJsonParser(jSonStr); + jp.nextToken(); + MapGeometry mg = GeometryEngine.jsonToGeometry(jp); + Geometry gm = mg.getGeometry(); + assertEquals(Geometry.Type.Polygon, gm.getType()); + + Polygon pgNew = (Polygon) gm; + + assertEquals(pgNew.getPathCount(), pg.getPathCount()); + assertEquals(pgNew.getPointCount(), pg.getPointCount()); + assertEquals(pgNew.getSegmentCount(), pg.getSegmentCount()); + + assertEquals(pgNew.getPoint(0).getX(), pg.getPoint(0).getX(), + 0.000000001); + assertEquals(pgNew.getPoint(1).getX(), pg.getPoint(1).getX(), + 0.000000001); + assertEquals(pgNew.getPoint(2).getX(), pg.getPoint(2).getX(), + 0.000000001); + assertEquals(pgNew.getPoint(3).getX(), pg.getPoint(3).getX(), + 0.000000001); + + assertEquals(pgNew.getPoint(0).getY(), pg.getPoint(0).getY(), + 0.000000001); + assertEquals(pgNew.getPoint(1).getY(), pg.getPoint(1).getY(), + 0.000000001); + assertEquals(pgNew.getPoint(2).getY(), pg.getPoint(2).getY(), + 0.000000001); + assertEquals(pgNew.getPoint(3).getY(), pg.getPoint(3).getY(), + 0.000000001); + } catch (Exception ex) { + String err = ex.getMessage(); + System.out.print(err); + throw ex; + } + } + + public static int fromJsonToWkid(JsonParser parser) + throws JsonParseException, IOException { + int wkid = 0; + if (parser.getCurrentToken() != JsonToken.START_OBJECT) { + return 0; + } + + while (parser.nextToken() != JsonToken.END_OBJECT) { + String fieldName = parser.getCurrentName(); + + if ("wkid".equals(fieldName)) { + parser.nextToken(); + wkid = parser.getIntValue(); + } + } + return wkid; + } +} diff --git a/src/test/java/com/esri/core/geometry/TestJsonParser.java b/src/test/java/com/esri/core/geometry/TestJsonParser.java index d6593115..9f2d887f 100644 --- a/src/test/java/com/esri/core/geometry/TestJsonParser.java +++ b/src/test/java/com/esri/core/geometry/TestJsonParser.java @@ -1,664 +1,664 @@ -package com.esri.core.geometry; - -import java.util.Hashtable; -import java.io.IOException; -import java.util.Map; -import junit.framework.TestCase; -import org.junit.Assert; -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParseException; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonToken; - -public class TestJsonParser extends TestCase { - - JsonFactory factory = new JsonFactory(); - SpatialReference spatialReferenceWebMerc1 = SpatialReference.create(102100); - SpatialReference spatialReferenceWebMerc2 = SpatialReference - .create(spatialReferenceWebMerc1.getLatestID()); - SpatialReference spatialReferenceWGS84 = SpatialReference.create(4326); - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void test3DPoint() throws JsonParseException, IOException { - String jsonString3DPt = "{\"x\" : -118.15, \"y\" : 33.80, \"z\" : 10.0, \"spatialReference\" : {\"wkid\" : 4326}}"; - - JsonParser jsonParser3DPt = factory.createParser(jsonString3DPt); - MapGeometry point3DMP = GeometryEngine.jsonToGeometry(jsonParser3DPt); - assertTrue(-118.15 == ((Point) point3DMP.getGeometry()).getX()); - assertTrue(33.80 == ((Point) point3DMP.getGeometry()).getY()); - assertTrue(spatialReferenceWGS84.getID() == point3DMP - .getSpatialReference().getID()); - } - - @Test - public void test3DPoint1() throws JsonParseException, IOException { - Point point1 = new Point(10.0, 20.0); - Point pointEmpty = new Point(); - { - JsonParser pointWebMerc1Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWebMerc1, point1)); - MapGeometry pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(point1.getX() == ((Point) pointWebMerc1MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWebMerc1MP.getGeometry()) - .getY()); - int srIdOri = spatialReferenceWebMerc1.getID(); - int srIdAfter = pointWebMerc1MP.getSpatialReference().getID(); - assertTrue(srIdOri == srIdAfter || srIdAfter == 3857); - - pointWebMerc1Parser = factory.createJsonParser(GeometryEngine - .geometryToJson(null, point1)); - pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(null == pointWebMerc1MP.getSpatialReference()); - - String pointEmptyString = GeometryEngine.geometryToJson( - spatialReferenceWebMerc1, pointEmpty); - pointWebMerc1Parser = factory.createJsonParser(pointEmptyString); - - pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(pointWebMerc1MP.getGeometry().isEmpty()); - int srIdOri2 = spatialReferenceWebMerc1.getID(); - int srIdAfter2 = pointWebMerc1MP.getSpatialReference().getID(); - assertTrue(srIdOri2 == srIdAfter2 || srIdAfter2 == 3857); - } - } - - @Test - public void test3DPoint2() throws JsonParseException, IOException { - { - Point point1 = new Point(10.0, 20.0); - JsonParser pointWebMerc2Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWebMerc2, point1)); - MapGeometry pointWebMerc2MP = GeometryEngine - .jsonToGeometry(pointWebMerc2Parser); - assertTrue(point1.getX() == ((Point) pointWebMerc2MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWebMerc2MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWebMerc2.getLatestID() == pointWebMerc2MP - .getSpatialReference().getLatestID()); - } - } - - @Test - public void test3DPoint3() throws JsonParseException, IOException { - { - Point point1 = new Point(10.0, 20.0); - JsonParser pointWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, point1)); - MapGeometry pointWgs84MP = GeometryEngine - .jsonToGeometry(pointWgs84Parser); - assertTrue(point1.getX() == ((Point) pointWgs84MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWgs84MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWGS84.getID() == pointWgs84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testMultiPoint() throws JsonParseException, IOException { - MultiPoint multiPoint1 = new MultiPoint(); - multiPoint1.add(-97.06138, 32.837); - multiPoint1.add(-97.06133, 32.836); - multiPoint1.add(-97.06124, 32.834); - multiPoint1.add(-97.06127, 32.832); - - { - JsonParser mPointWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, multiPoint1)); - MapGeometry mPointWgs84MP = GeometryEngine - .jsonToGeometry(mPointWgs84Parser); - assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPointCount()); - assertTrue(multiPoint1.getPoint(0).getX() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(multiPoint1.getPoint(0).getY() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(0).getY()); - int lastIndex = multiPoint1.getPointCount() - 1; - assertTrue(multiPoint1.getPoint(lastIndex).getX() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(multiPoint1.getPoint(lastIndex).getY() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP - .getSpatialReference().getID()); - - MultiPoint mPointEmpty = new MultiPoint(); - String mPointEmptyString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, mPointEmpty); - mPointWgs84Parser = factory.createJsonParser(mPointEmptyString); - - mPointWgs84MP = GeometryEngine.jsonToGeometry(mPointWgs84Parser); - assertTrue(mPointWgs84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP - .getSpatialReference().getID()); - - } - } - - @Test - public void testPolyline() throws JsonParseException, IOException { - Polyline polyline = new Polyline(); - polyline.startPath(-97.06138, 32.837); - polyline.lineTo(-97.06133, 32.836); - polyline.lineTo(-97.06124, 32.834); - polyline.lineTo(-97.06127, 32.832); - - polyline.startPath(-97.06326, 32.759); - polyline.lineTo(-97.06298, 32.755); - - { - JsonParser polylinePathsWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, polyline)); - MapGeometry mPolylineWGS84MP = GeometryEngine - .jsonToGeometry(polylinePathsWgs84Parser); - - assertTrue(polyline.getPointCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPointCount()); - assertTrue(polyline.getPoint(0).getX() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(polyline.getPoint(0).getY() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(0).getY()); - - assertTrue(polyline.getPathCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPathCount()); - assertTrue(polyline.getSegmentCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount()); - assertTrue(polyline.getSegmentCount(0) == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount(0)); - assertTrue(polyline.getSegmentCount(1) == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount(1)); - - int lastIndex = polyline.getPointCount() - 1; - assertTrue(polyline.getPoint(lastIndex).getX() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(polyline.getPoint(lastIndex).getY() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP - .getSpatialReference().getID()); - - Polyline emptyPolyline = new Polyline(); - String emptyString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, emptyPolyline); - mPolylineWGS84MP = GeometryEngine.jsonToGeometry(factory - .createJsonParser(emptyString)); - assertTrue(mPolylineWGS84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testPolygon() throws JsonParseException, IOException { - Polygon polygon = new Polygon(); - polygon.startPath(-97.06138, 32.837); - polygon.lineTo(-97.06133, 32.836); - polygon.lineTo(-97.06124, 32.834); - polygon.lineTo(-97.06127, 32.832); - - polygon.startPath(-97.06326, 32.759); - polygon.lineTo(-97.06298, 32.755); - - { - JsonParser polygonPathsWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, polygon)); - MapGeometry mPolygonWGS84MP = GeometryEngine - .jsonToGeometry(polygonPathsWgs84Parser); - - assertTrue(polygon.getPointCount() + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPointCount()); - assertTrue(polygon.getPoint(0).getX() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(polygon.getPoint(0).getY() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(0).getY()); - - assertTrue(polygon.getPathCount() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPathCount()); - assertTrue(polygon.getSegmentCount() + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount()); - assertTrue(polygon.getSegmentCount(0) == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount(0)); - assertTrue(polygon.getSegmentCount(1) + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount(1)); - - int lastIndex = polygon.getPointCount() - 1; - assertTrue(polygon.getPoint(lastIndex).getX() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(polygon.getPoint(lastIndex).getY() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP - .getSpatialReference().getID()); - - Polygon emptyPolygon = new Polygon(); - String emptyPolygonString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, emptyPolygon); - polygonPathsWgs84Parser = factory - .createJsonParser(emptyPolygonString); - mPolygonWGS84MP = GeometryEngine - .jsonToGeometry(polygonPathsWgs84Parser); - - assertTrue(mPolygonWGS84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testEnvelope() throws JsonParseException, IOException { - Envelope envelope = new Envelope(); - envelope.setCoords(-109.55, 25.76, -86.39, 49.94); - - { - JsonParser envelopeWGS84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, envelope)); - MapGeometry envelopeWGS84MP = GeometryEngine - .jsonToGeometry(envelopeWGS84Parser); - assertTrue(envelope.isEmpty() == envelopeWGS84MP.getGeometry() - .isEmpty()); - assertTrue(envelope.getXMax() == ((Envelope) envelopeWGS84MP - .getGeometry()).getXMax()); - assertTrue(envelope.getYMax() == ((Envelope) envelopeWGS84MP - .getGeometry()).getYMax()); - assertTrue(envelope.getXMin() == ((Envelope) envelopeWGS84MP - .getGeometry()).getXMin()); - assertTrue(envelope.getYMin() == ((Envelope) envelopeWGS84MP - .getGeometry()).getYMin()); - assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP - .getSpatialReference().getID()); - - Envelope emptyEnvelope = new Envelope(); - String emptyEnvString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, emptyEnvelope); - envelopeWGS84Parser = factory.createJsonParser(emptyEnvString); - envelopeWGS84MP = GeometryEngine - .jsonToGeometry(envelopeWGS84Parser); - - assertTrue(envelopeWGS84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testCR181369() throws JsonParseException, IOException { - // CR181369 - { - String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; - JsonParser jsonParserPointAndWKT = factory - .createJsonParser(jsonStringPointAndWKT); - MapGeometry mapGeom2 = GeometryEngine - .jsonToGeometry(jsonParserPointAndWKT); - String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson( - mapGeom2.getSpatialReference(), mapGeom2.getGeometry()); - JsonParser jsonParserPointAndWKT2 = factory - .createJsonParser(jsonStringPointAndWKT2); - MapGeometry mapGeom3 = GeometryEngine - .jsonToGeometry(jsonParserPointAndWKT2); - assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3 - .getGeometry()).getX()); - assertTrue(((Point) mapGeom2.getGeometry()).getY() == ((Point) mapGeom3 - .getGeometry()).getY()); - assertTrue(mapGeom2.getSpatialReference().getText() - .equals(mapGeom3.getSpatialReference().getText())); - assertTrue(mapGeom2.getSpatialReference().getID() == mapGeom3 - .getSpatialReference().getID()); - } - } - - @Test - public void testSpatialRef() throws JsonParseException, IOException { - // String jsonStringPt = - // "{\"x\":-20037508.342787,\"y\":20037508.342787},\"spatialReference\":{\"wkid\":102100}}"; - String jsonStringPt = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\": 102100}}";// 102100 - @SuppressWarnings("unused") - String jsonStringPt2 = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\":4326}}"; - String jsonStringMpt = "{ \"points\" : [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], \"spatialReference\" : {\"wkid\" : 4326}}";// 4326 - String jsonStringMpt3D = "{\"hasZs\" : true,\"points\" : [ [-97.06138,32.837,35.0], [-97.06133,32.836,35.1], [-97.06124,32.834,35.2], [-97.06127,32.832,35.3] ],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPl = "{\"paths\" : [ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], [ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPl3D = "{\"hasMs\" : true,\"paths\" : [[ [-97.06138,32.837,5], [-97.06133,32.836,6], [-97.06124,32.834,7], [-97.06127,32.832,8] ],[ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPg = "{ \"rings\" :[ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], [ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], \"spatialReference\" : {\"wkt\" : \"\"}}"; - String jsonStringPg3D = "{\"hasZs\" : true,\"hasMs\" : true,\"rings\" : [ [ [-97.06138, 32.837, 35.1, 4], [-97.06133, 32.836, 35.2, 4.1], [-97.06124, 32.834, 35.3, 4.2], [-97.06127, 32.832, 35.2, 44.3], [-97.06138, 32.837, 35.1, 4] ],[ [-97.06326, 32.759, 35.4], [-97.06298, 32.755, 35.5], [-97.06153, 32.749, 35.6], [-97.06326, 32.759, 35.4] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPg2 = "{ \"spatialReference\" : {\"wkid\" : 4326}, \"rings\" : [[[-118.35,32.81],[-118.42,32.806],[-118.511,32.892],[-118.35,32.81]]]}"; - String jsonStringPg3 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":null}}"; - String jsonString2SpatialReferences = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; - String jsonString2SpatialReferences2 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":10,\"wkid\":10,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; - String jsonStringSR = "{\"wkid\" : 4326}"; - String jsonStringEnv = "{\"xmin\" : -109.55, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94,\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringHongKon = "{\"xmin\" : -122.55, \"ymin\" : 37.65, \"xmax\" : -122.28, \"ymax\" : 37.84,\"spatialReference\" : {\"wkid\" : 4326}}"; - @SuppressWarnings("unused") - String jsonStringWKT = " {\"wkt\" : \"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}"; - String jsonStringInvalidWKID = "{\"x\":10.0,\"y\":20.0},\"spatialReference\":{\"wkid\":35253523}}"; - String jsonStringOregon = "{\"xmin\":7531831.219849482,\"ymin\":585702.9799639136,\"xmax\":7750143.589982405,\"ymax\":733289.6299999952,\"spatialReference\":{\"wkid\":102726}}"; - - JsonParser jsonParserPt = factory.createJsonParser(jsonStringPt); - JsonParser jsonParserMpt = factory.createJsonParser(jsonStringMpt); - JsonParser jsonParserMpt3D = factory.createJsonParser(jsonStringMpt3D); - JsonParser jsonParserPl = factory.createJsonParser(jsonStringPl); - JsonParser jsonParserPl3D = factory.createJsonParser(jsonStringPl3D); - JsonParser jsonParserPg = factory.createJsonParser(jsonStringPg); - JsonParser jsonParserPg3D = factory.createJsonParser(jsonStringPg3D); - JsonParser jsonParserPg2 = factory.createJsonParser(jsonStringPg2); - @SuppressWarnings("unused") - JsonParser jsonParserSR = factory.createJsonParser(jsonStringSR); - JsonParser jsonParserEnv = factory.createJsonParser(jsonStringEnv); - JsonParser jsonParserPg3 = factory.createJsonParser(jsonStringPg3); - @SuppressWarnings("unused") - JsonParser jsonParserCrazy1 = factory - .createJsonParser(jsonString2SpatialReferences); - @SuppressWarnings("unused") - JsonParser jsonParserCrazy2 = factory - .createJsonParser(jsonString2SpatialReferences2); - JsonParser jsonParserInvalidWKID = factory - .createJsonParser(jsonStringInvalidWKID); - @SuppressWarnings("unused") - JsonParser jsonParseHongKon = factory - .createJsonParser(jsonStringHongKon); - JsonParser jsonParseOregon = factory.createJsonParser(jsonStringOregon); - - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPt); - // showProjectedGeometryInfo(mapGeom); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); - - MapGeometry mapGeomOregon = GeometryEngine - .jsonToGeometry(jsonParseOregon); - Assert.assertTrue(mapGeomOregon.getSpatialReference().getID() == 102726); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt3D); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - { - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0) - .getX() == -97.06138); - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0) - .getY() == 32.837); - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3) - .getX() == -97.06127); - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3) - .getY() == 32.832); - } - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl3D); - { - // [[ [-97.06138,32.837,5], [-97.06133,32.836,6], - // [-97.06124,32.834,7], [-97.06127,32.832,8] ], - // [ [-97.06326,32.759], [-97.06298,32.755] ]]"; - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0) - .getX() == -97.06138); - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0) - .getY() == 32.837); - int lastIndex = ((Polyline) mapGeom.getGeometry()).getPointCount() - 1; - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndex).getX() == -97.06298);// -97.06153, 32.749 - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndex).getY() == 32.755); - int lastIndexFirstLine = ((Polyline) mapGeom.getGeometry()) - .getPathEnd(0) - 1; - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndexFirstLine).getX() == -97.06127);// -97.06153, - // 32.749 - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndexFirstLine).getY() == 32.832); - } - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); - Assert.assertTrue(mapGeom.getSpatialReference() == null); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3D); - { - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0) - .getX() == -97.06138); - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0) - .getY() == 32.837); - int lastIndex = ((Polygon) mapGeom.getGeometry()).getPointCount() - 1; - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint( - lastIndex).getX() == -97.06153);// -97.06153, 32.749 - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint( - lastIndex).getY() == 32.749); - } - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg2); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); - // showProjectedGeometryInfo(mapGeom); - - // mapGeom = GeometryEngine.jsonToGeometry(jsonParserCrazy1); - // Assert.assertTrue(mapGeom.getSpatialReference().getText().equals("")); - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserEnv); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - // showProjectedGeometryInfo(mapGeom); - - try { - GeometryEngine.jsonToGeometry(jsonParserInvalidWKID); - } catch (Exception ex) { - Assert.assertTrue("Should not throw for invalid wkid", false); - } - } - - @Test - public void testMP2onCR175871() throws Exception { - Polygon pg = new Polygon(); - pg.startPath(-50, 10); - pg.lineTo(-50, 12); - pg.lineTo(-45, 12); - pg.lineTo(-45, 10); - - Polygon pg1 = new Polygon(); - pg1.startPath(-45, 10); - pg1.lineTo(-40, 10); - pg1.lineTo(-40, 8); - pg.add(pg1, false); - - SpatialReference spatialReference = SpatialReference.create(4326); - - try { - String jSonStr = GeometryEngine - .geometryToJson(spatialReference, pg); - JsonFactory jf = new JsonFactory(); - - JsonParser jp = jf.createJsonParser(jSonStr); - jp.nextToken(); - MapGeometry mg = GeometryEngine.jsonToGeometry(jp); - Geometry gm = mg.getGeometry(); - Assert.assertEquals(Geometry.Type.Polygon, gm.getType()); - Assert.assertTrue(mg.getSpatialReference().getID() == 4326); - - Polygon pgNew = (Polygon) gm; - - Assert.assertEquals(pgNew.getPathCount(), pg.getPathCount()); - Assert.assertEquals(pgNew.getPointCount(), pg.getPointCount()); - Assert.assertEquals(pgNew.getSegmentCount(), pg.getSegmentCount()); - - Assert.assertEquals(pgNew.getPoint(0).getX(), - pg.getPoint(0).getX(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(1).getX(), - pg.getPoint(1).getX(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(2).getX(), - pg.getPoint(2).getX(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(3).getX(), - pg.getPoint(3).getX(), 0.000000001); - - Assert.assertEquals(pgNew.getPoint(0).getY(), - pg.getPoint(0).getY(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(1).getY(), - pg.getPoint(1).getY(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(2).getY(), - pg.getPoint(2).getY(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(3).getY(), - pg.getPoint(3).getY(), 0.000000001); - } catch (Exception ex) { - String err = ex.getMessage(); - System.out.print(err); - throw ex; - } - } - - @Test - public static int fromJsonToWkid(JsonParser parser) - throws JsonParseException, IOException { - int wkid = 0; - if (parser.getCurrentToken() != JsonToken.START_OBJECT) { - return 0; - } - - while (parser.nextToken() != JsonToken.END_OBJECT) { - String fieldName = parser.getCurrentName(); - - if ("wkid".equals(fieldName)) { - parser.nextToken(); - wkid = parser.getIntValue(); - } - } - return wkid; - } - - @SuppressWarnings("unused") - private static void showProjectedGeometryInfo(MapGeometry mapGeom) { - System.out.println("\n"); - MapGeometry geom = mapGeom; - // while ((geom = geomCursor.next()) != null) { - - if (geom.getGeometry() instanceof Point) { - Point pnt = (Point) geom.getGeometry(); - System.out - .println("Point(" + pnt.getX() + " , " + pnt.getY() + ")"); - if (geom.getSpatialReference() == null) { - System.out.println("No spatial reference"); - } else { - System.out.println("wkid: " - + geom.getSpatialReference().getID()); - } - - } else if (geom.getGeometry() instanceof MultiPoint) { - MultiPoint mp = (MultiPoint) geom.getGeometry(); - System.out.println("Multipoint has " + mp.getPointCount() - + " points."); - - System.out.println("wkid: " + geom.getSpatialReference().getID()); - - } else if (geom.getGeometry() instanceof Polygon) { - Polygon mp = (Polygon) geom.getGeometry(); - System.out.println("Polygon has " + mp.getPointCount() - + " points and " + mp.getPathCount() + " parts."); - if (mp.getPathCount() > 1) { - System.out.println("Part start of 2nd segment : " - + mp.getPathStart(1)); - System.out.println("Part end of 2nd segment : " - + mp.getPathEnd(1)); - System.out.println("Part size of 2nd segment : " - + mp.getPathSize(1)); - - int start = mp.getPathStart(1); - int end = mp.getPathEnd(1); - for (int i = start; i < end; i++) { - Point pp = mp.getPoint(i); - System.out.println("Point(" + i + ") = (" + pp.getX() - + ", " + pp.getY() + ")"); - } - } - System.out.println("wkid: " + geom.getSpatialReference().getID()); - - } else if (geom.getGeometry() instanceof Polyline) { - Polyline mp = (Polyline) geom.getGeometry(); - System.out.println("Polyline has " + mp.getPointCount() - + " points and " + mp.getPathCount() + " parts."); - System.out.println("Part start of 2nd segment : " - + mp.getPathStart(1)); - System.out.println("Part end of 2nd segment : " - + mp.getPathEnd(1)); - System.out.println("Part size of 2nd segment : " - + mp.getPathSize(1)); - int start = mp.getPathStart(1); - int end = mp.getPathEnd(1); - for (int i = start; i < end; i++) { - Point pp = mp.getPoint(i); - System.out.println("Point(" + i + ") = (" + pp.getX() + ", " - + pp.getY() + ")"); - } - - System.out.println("wkid: " + geom.getSpatialReference().getID()); - } - } - - @Test - public void testGeometryToJSON() { - Polygon geom = new Polygon(); - geom.startPath(new Point(-113, 34)); - geom.lineTo(new Point(-105, 34)); - geom.lineTo(new Point(-108, 40)); - - String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom);// Test - // WKID - // == -1 - //System.out.println("Geom JSON STRING is" + outputPolygon1); - String correctPolygon1 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]]}"; - - assertEquals(correctPolygon1, outputPolygon1); - - String outputPolygon2 = GeometryEngine.geometryToJson(4326, geom); - //System.out.println("Geom JSON STRING is" + outputPolygon2); - - String correctPolygon2 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":4326}}"; - assertEquals(correctPolygon2, outputPolygon2); - } - - @Test - public void testGeometryToJSONOldID() throws Exception {// CR - Polygon geom = new Polygon(); - geom.startPath(new Point(-113, 34)); - geom.lineTo(new Point(-105, 34)); - geom.lineTo(new Point(-108, 40)); - String outputPolygon = GeometryEngine.geometryToJson( - SpatialReference.create(3857), geom);// Test WKID == -1 - String correctPolygon = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; - assertTrue(outputPolygon.equals(correctPolygon)); - JsonFactory jf = new JsonFactory(); - JsonParser jp = jf.createJsonParser(outputPolygon); - jp.nextToken(); - MapGeometry mg = GeometryEngine.jsonToGeometry(jp); - @SuppressWarnings("unused") - int srId = mg.getSpatialReference().getID(); - @SuppressWarnings("unused") - int srOldId = mg.getSpatialReference().getOldID(); - Assert.assertTrue(mg.getSpatialReference().getID() == 3857); - Assert.assertTrue(mg.getSpatialReference().getLatestID() == 3857); - Assert.assertTrue(mg.getSpatialReference().getOldID() == 102100); - } -} +package com.esri.core.geometry; + +import java.util.Hashtable; +import java.io.IOException; +import java.util.Map; +import junit.framework.TestCase; +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + +public class TestJsonParser extends TestCase { + + JsonFactory factory = new JsonFactory(); + SpatialReference spatialReferenceWebMerc1 = SpatialReference.create(102100); + SpatialReference spatialReferenceWebMerc2 = SpatialReference + .create(spatialReferenceWebMerc1.getLatestID()); + SpatialReference spatialReferenceWGS84 = SpatialReference.create(4326); + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void test3DPoint() throws JsonParseException, IOException { + String jsonString3DPt = "{\"x\" : -118.15, \"y\" : 33.80, \"z\" : 10.0, \"spatialReference\" : {\"wkid\" : 4326}}"; + + JsonParser jsonParser3DPt = factory.createParser(jsonString3DPt); + MapGeometry point3DMP = GeometryEngine.jsonToGeometry(jsonParser3DPt); + assertTrue(-118.15 == ((Point) point3DMP.getGeometry()).getX()); + assertTrue(33.80 == ((Point) point3DMP.getGeometry()).getY()); + assertTrue(spatialReferenceWGS84.getID() == point3DMP + .getSpatialReference().getID()); + } + + @Test + public void test3DPoint1() throws JsonParseException, IOException { + Point point1 = new Point(10.0, 20.0); + Point pointEmpty = new Point(); + { + JsonParser pointWebMerc1Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWebMerc1, point1)); + MapGeometry pointWebMerc1MP = GeometryEngine + .jsonToGeometry(pointWebMerc1Parser); + assertTrue(point1.getX() == ((Point) pointWebMerc1MP.getGeometry()) + .getX()); + assertTrue(point1.getY() == ((Point) pointWebMerc1MP.getGeometry()) + .getY()); + int srIdOri = spatialReferenceWebMerc1.getID(); + int srIdAfter = pointWebMerc1MP.getSpatialReference().getID(); + assertTrue(srIdOri == srIdAfter || srIdAfter == 3857); + + pointWebMerc1Parser = factory.createJsonParser(GeometryEngine + .geometryToJson(null, point1)); + pointWebMerc1MP = GeometryEngine + .jsonToGeometry(pointWebMerc1Parser); + assertTrue(null == pointWebMerc1MP.getSpatialReference()); + + String pointEmptyString = GeometryEngine.geometryToJson( + spatialReferenceWebMerc1, pointEmpty); + pointWebMerc1Parser = factory.createJsonParser(pointEmptyString); + + pointWebMerc1MP = GeometryEngine + .jsonToGeometry(pointWebMerc1Parser); + assertTrue(pointWebMerc1MP.getGeometry().isEmpty()); + int srIdOri2 = spatialReferenceWebMerc1.getID(); + int srIdAfter2 = pointWebMerc1MP.getSpatialReference().getID(); + assertTrue(srIdOri2 == srIdAfter2 || srIdAfter2 == 3857); + } + } + + @Test + public void test3DPoint2() throws JsonParseException, IOException { + { + Point point1 = new Point(10.0, 20.0); + JsonParser pointWebMerc2Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWebMerc2, point1)); + MapGeometry pointWebMerc2MP = GeometryEngine + .jsonToGeometry(pointWebMerc2Parser); + assertTrue(point1.getX() == ((Point) pointWebMerc2MP.getGeometry()) + .getX()); + assertTrue(point1.getY() == ((Point) pointWebMerc2MP.getGeometry()) + .getY()); + assertTrue(spatialReferenceWebMerc2.getLatestID() == pointWebMerc2MP + .getSpatialReference().getLatestID()); + } + } + + @Test + public void test3DPoint3() throws JsonParseException, IOException { + { + Point point1 = new Point(10.0, 20.0); + JsonParser pointWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, point1)); + MapGeometry pointWgs84MP = GeometryEngine + .jsonToGeometry(pointWgs84Parser); + assertTrue(point1.getX() == ((Point) pointWgs84MP.getGeometry()) + .getX()); + assertTrue(point1.getY() == ((Point) pointWgs84MP.getGeometry()) + .getY()); + assertTrue(spatialReferenceWGS84.getID() == pointWgs84MP + .getSpatialReference().getID()); + } + } + + @Test + public void testMultiPoint() throws JsonParseException, IOException { + MultiPoint multiPoint1 = new MultiPoint(); + multiPoint1.add(-97.06138, 32.837); + multiPoint1.add(-97.06133, 32.836); + multiPoint1.add(-97.06124, 32.834); + multiPoint1.add(-97.06127, 32.832); + + { + JsonParser mPointWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, multiPoint1)); + MapGeometry mPointWgs84MP = GeometryEngine + .jsonToGeometry(mPointWgs84Parser); + assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPointCount()); + assertTrue(multiPoint1.getPoint(0).getX() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(0).getX()); + assertTrue(multiPoint1.getPoint(0).getY() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(0).getY()); + int lastIndex = multiPoint1.getPointCount() - 1; + assertTrue(multiPoint1.getPoint(lastIndex).getX() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(lastIndex).getX()); + assertTrue(multiPoint1.getPoint(lastIndex).getY() == ((MultiPoint) mPointWgs84MP + .getGeometry()).getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP + .getSpatialReference().getID()); + + MultiPoint mPointEmpty = new MultiPoint(); + String mPointEmptyString = GeometryEngine.geometryToJson( + spatialReferenceWGS84, mPointEmpty); + mPointWgs84Parser = factory.createJsonParser(mPointEmptyString); + + mPointWgs84MP = GeometryEngine.jsonToGeometry(mPointWgs84Parser); + assertTrue(mPointWgs84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP + .getSpatialReference().getID()); + + } + } + + @Test + public void testPolyline() throws JsonParseException, IOException { + Polyline polyline = new Polyline(); + polyline.startPath(-97.06138, 32.837); + polyline.lineTo(-97.06133, 32.836); + polyline.lineTo(-97.06124, 32.834); + polyline.lineTo(-97.06127, 32.832); + + polyline.startPath(-97.06326, 32.759); + polyline.lineTo(-97.06298, 32.755); + + { + JsonParser polylinePathsWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, polyline)); + MapGeometry mPolylineWGS84MP = GeometryEngine + .jsonToGeometry(polylinePathsWgs84Parser); + + assertTrue(polyline.getPointCount() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPointCount()); + assertTrue(polyline.getPoint(0).getX() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(0).getX()); + assertTrue(polyline.getPoint(0).getY() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(0).getY()); + + assertTrue(polyline.getPathCount() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPathCount()); + assertTrue(polyline.getSegmentCount() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getSegmentCount()); + assertTrue(polyline.getSegmentCount(0) == ((Polyline) mPolylineWGS84MP + .getGeometry()).getSegmentCount(0)); + assertTrue(polyline.getSegmentCount(1) == ((Polyline) mPolylineWGS84MP + .getGeometry()).getSegmentCount(1)); + + int lastIndex = polyline.getPointCount() - 1; + assertTrue(polyline.getPoint(lastIndex).getX() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(lastIndex).getX()); + assertTrue(polyline.getPoint(lastIndex).getY() == ((Polyline) mPolylineWGS84MP + .getGeometry()).getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP + .getSpatialReference().getID()); + + Polyline emptyPolyline = new Polyline(); + String emptyString = GeometryEngine.geometryToJson( + spatialReferenceWGS84, emptyPolyline); + mPolylineWGS84MP = GeometryEngine.jsonToGeometry(factory + .createJsonParser(emptyString)); + assertTrue(mPolylineWGS84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP + .getSpatialReference().getID()); + } + } + + @Test + public void testPolygon() throws JsonParseException, IOException { + Polygon polygon = new Polygon(); + polygon.startPath(-97.06138, 32.837); + polygon.lineTo(-97.06133, 32.836); + polygon.lineTo(-97.06124, 32.834); + polygon.lineTo(-97.06127, 32.832); + + polygon.startPath(-97.06326, 32.759); + polygon.lineTo(-97.06298, 32.755); + + { + JsonParser polygonPathsWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, polygon)); + MapGeometry mPolygonWGS84MP = GeometryEngine + .jsonToGeometry(polygonPathsWgs84Parser); + + assertTrue(polygon.getPointCount() + 1 == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPointCount()); + assertTrue(polygon.getPoint(0).getX() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(0).getX()); + assertTrue(polygon.getPoint(0).getY() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(0).getY()); + + assertTrue(polygon.getPathCount() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPathCount()); + assertTrue(polygon.getSegmentCount() + 1 == ((Polygon) mPolygonWGS84MP + .getGeometry()).getSegmentCount()); + assertTrue(polygon.getSegmentCount(0) == ((Polygon) mPolygonWGS84MP + .getGeometry()).getSegmentCount(0)); + assertTrue(polygon.getSegmentCount(1) + 1 == ((Polygon) mPolygonWGS84MP + .getGeometry()).getSegmentCount(1)); + + int lastIndex = polygon.getPointCount() - 1; + assertTrue(polygon.getPoint(lastIndex).getX() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(lastIndex).getX()); + assertTrue(polygon.getPoint(lastIndex).getY() == ((Polygon) mPolygonWGS84MP + .getGeometry()).getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP + .getSpatialReference().getID()); + + Polygon emptyPolygon = new Polygon(); + String emptyPolygonString = GeometryEngine.geometryToJson( + spatialReferenceWGS84, emptyPolygon); + polygonPathsWgs84Parser = factory + .createJsonParser(emptyPolygonString); + mPolygonWGS84MP = GeometryEngine + .jsonToGeometry(polygonPathsWgs84Parser); + + assertTrue(mPolygonWGS84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP + .getSpatialReference().getID()); + } + } + + @Test + public void testEnvelope() throws JsonParseException, IOException { + Envelope envelope = new Envelope(); + envelope.setCoords(-109.55, 25.76, -86.39, 49.94); + + { + JsonParser envelopeWGS84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson( + spatialReferenceWGS84, envelope)); + MapGeometry envelopeWGS84MP = GeometryEngine + .jsonToGeometry(envelopeWGS84Parser); + assertTrue(envelope.isEmpty() == envelopeWGS84MP.getGeometry() + .isEmpty()); + assertTrue(envelope.getXMax() == ((Envelope) envelopeWGS84MP + .getGeometry()).getXMax()); + assertTrue(envelope.getYMax() == ((Envelope) envelopeWGS84MP + .getGeometry()).getYMax()); + assertTrue(envelope.getXMin() == ((Envelope) envelopeWGS84MP + .getGeometry()).getXMin()); + assertTrue(envelope.getYMin() == ((Envelope) envelopeWGS84MP + .getGeometry()).getYMin()); + assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP + .getSpatialReference().getID()); + + Envelope emptyEnvelope = new Envelope(); + String emptyEnvString = GeometryEngine.geometryToJson( + spatialReferenceWGS84, emptyEnvelope); + envelopeWGS84Parser = factory.createJsonParser(emptyEnvString); + envelopeWGS84MP = GeometryEngine + .jsonToGeometry(envelopeWGS84Parser); + + assertTrue(envelopeWGS84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP + .getSpatialReference().getID()); + } + } + + @Test + public void testCR181369() throws JsonParseException, IOException { + // CR181369 + { + String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; + JsonParser jsonParserPointAndWKT = factory + .createJsonParser(jsonStringPointAndWKT); + MapGeometry mapGeom2 = GeometryEngine + .jsonToGeometry(jsonParserPointAndWKT); + String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson( + mapGeom2.getSpatialReference(), mapGeom2.getGeometry()); + JsonParser jsonParserPointAndWKT2 = factory + .createJsonParser(jsonStringPointAndWKT2); + MapGeometry mapGeom3 = GeometryEngine + .jsonToGeometry(jsonParserPointAndWKT2); + assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3 + .getGeometry()).getX()); + assertTrue(((Point) mapGeom2.getGeometry()).getY() == ((Point) mapGeom3 + .getGeometry()).getY()); + assertTrue(mapGeom2.getSpatialReference().getText() + .equals(mapGeom3.getSpatialReference().getText())); + assertTrue(mapGeom2.getSpatialReference().getID() == mapGeom3 + .getSpatialReference().getID()); + } + } + + @Test + public void testSpatialRef() throws JsonParseException, IOException { + // String jsonStringPt = + // "{\"x\":-20037508.342787,\"y\":20037508.342787},\"spatialReference\":{\"wkid\":102100}}"; + String jsonStringPt = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\": 102100}}";// 102100 + @SuppressWarnings("unused") + String jsonStringPt2 = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\":4326}}"; + String jsonStringMpt = "{ \"points\" : [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], \"spatialReference\" : {\"wkid\" : 4326}}";// 4326 + String jsonStringMpt3D = "{\"hasZs\" : true,\"points\" : [ [-97.06138,32.837,35.0], [-97.06133,32.836,35.1], [-97.06124,32.834,35.2], [-97.06127,32.832,35.3] ],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPl = "{\"paths\" : [ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], [ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPl3D = "{\"hasMs\" : true,\"paths\" : [[ [-97.06138,32.837,5], [-97.06133,32.836,6], [-97.06124,32.834,7], [-97.06127,32.832,8] ],[ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPg = "{ \"rings\" :[ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], [ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], \"spatialReference\" : {\"wkt\" : \"\"}}"; + String jsonStringPg3D = "{\"hasZs\" : true,\"hasMs\" : true,\"rings\" : [ [ [-97.06138, 32.837, 35.1, 4], [-97.06133, 32.836, 35.2, 4.1], [-97.06124, 32.834, 35.3, 4.2], [-97.06127, 32.832, 35.2, 44.3], [-97.06138, 32.837, 35.1, 4] ],[ [-97.06326, 32.759, 35.4], [-97.06298, 32.755, 35.5], [-97.06153, 32.749, 35.6], [-97.06326, 32.759, 35.4] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPg2 = "{ \"spatialReference\" : {\"wkid\" : 4326}, \"rings\" : [[[-118.35,32.81],[-118.42,32.806],[-118.511,32.892],[-118.35,32.81]]]}"; + String jsonStringPg3 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":null}}"; + String jsonString2SpatialReferences = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; + String jsonString2SpatialReferences2 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":10,\"wkid\":10,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; + String jsonStringSR = "{\"wkid\" : 4326}"; + String jsonStringEnv = "{\"xmin\" : -109.55, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94,\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringHongKon = "{\"xmin\" : -122.55, \"ymin\" : 37.65, \"xmax\" : -122.28, \"ymax\" : 37.84,\"spatialReference\" : {\"wkid\" : 4326}}"; + @SuppressWarnings("unused") + String jsonStringWKT = " {\"wkt\" : \"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}"; + String jsonStringInvalidWKID = "{\"x\":10.0,\"y\":20.0},\"spatialReference\":{\"wkid\":35253523}}"; + String jsonStringOregon = "{\"xmin\":7531831.219849482,\"ymin\":585702.9799639136,\"xmax\":7750143.589982405,\"ymax\":733289.6299999952,\"spatialReference\":{\"wkid\":102726}}"; + + JsonParser jsonParserPt = factory.createJsonParser(jsonStringPt); + JsonParser jsonParserMpt = factory.createJsonParser(jsonStringMpt); + JsonParser jsonParserMpt3D = factory.createJsonParser(jsonStringMpt3D); + JsonParser jsonParserPl = factory.createJsonParser(jsonStringPl); + JsonParser jsonParserPl3D = factory.createJsonParser(jsonStringPl3D); + JsonParser jsonParserPg = factory.createJsonParser(jsonStringPg); + JsonParser jsonParserPg3D = factory.createJsonParser(jsonStringPg3D); + JsonParser jsonParserPg2 = factory.createJsonParser(jsonStringPg2); + @SuppressWarnings("unused") + JsonParser jsonParserSR = factory.createJsonParser(jsonStringSR); + JsonParser jsonParserEnv = factory.createJsonParser(jsonStringEnv); + JsonParser jsonParserPg3 = factory.createJsonParser(jsonStringPg3); + @SuppressWarnings("unused") + JsonParser jsonParserCrazy1 = factory + .createJsonParser(jsonString2SpatialReferences); + @SuppressWarnings("unused") + JsonParser jsonParserCrazy2 = factory + .createJsonParser(jsonString2SpatialReferences2); + JsonParser jsonParserInvalidWKID = factory + .createJsonParser(jsonStringInvalidWKID); + @SuppressWarnings("unused") + JsonParser jsonParseHongKon = factory + .createJsonParser(jsonStringHongKon); + JsonParser jsonParseOregon = factory.createJsonParser(jsonStringOregon); + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPt); + // showProjectedGeometryInfo(mapGeom); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); + + MapGeometry mapGeomOregon = GeometryEngine + .jsonToGeometry(jsonParseOregon); + Assert.assertTrue(mapGeomOregon.getSpatialReference().getID() == 102726); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt3D); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + { + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0) + .getX() == -97.06138); + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0) + .getY() == 32.837); + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3) + .getX() == -97.06127); + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3) + .getY() == 32.832); + } + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl3D); + { + // [[ [-97.06138,32.837,5], [-97.06133,32.836,6], + // [-97.06124,32.834,7], [-97.06127,32.832,8] ], + // [ [-97.06326,32.759], [-97.06298,32.755] ]]"; + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0) + .getX() == -97.06138); + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0) + .getY() == 32.837); + int lastIndex = ((Polyline) mapGeom.getGeometry()).getPointCount() - 1; + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( + lastIndex).getX() == -97.06298);// -97.06153, 32.749 + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( + lastIndex).getY() == 32.755); + int lastIndexFirstLine = ((Polyline) mapGeom.getGeometry()) + .getPathEnd(0) - 1; + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( + lastIndexFirstLine).getX() == -97.06127);// -97.06153, + // 32.749 + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( + lastIndexFirstLine).getY() == 32.832); + } + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); + Assert.assertTrue(mapGeom.getSpatialReference() == null); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3D); + { + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0) + .getX() == -97.06138); + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0) + .getY() == 32.837); + int lastIndex = ((Polygon) mapGeom.getGeometry()).getPointCount() - 1; + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint( + lastIndex).getX() == -97.06153);// -97.06153, 32.749 + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint( + lastIndex).getY() == 32.749); + } + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg2); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); + // showProjectedGeometryInfo(mapGeom); + + // mapGeom = GeometryEngine.jsonToGeometry(jsonParserCrazy1); + // Assert.assertTrue(mapGeom.getSpatialReference().getText().equals("")); + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserEnv); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + // showProjectedGeometryInfo(mapGeom); + + try { + GeometryEngine.jsonToGeometry(jsonParserInvalidWKID); + } catch (Exception ex) { + Assert.assertTrue("Should not throw for invalid wkid", false); + } + } + + @Test + public void testMP2onCR175871() throws Exception { + Polygon pg = new Polygon(); + pg.startPath(-50, 10); + pg.lineTo(-50, 12); + pg.lineTo(-45, 12); + pg.lineTo(-45, 10); + + Polygon pg1 = new Polygon(); + pg1.startPath(-45, 10); + pg1.lineTo(-40, 10); + pg1.lineTo(-40, 8); + pg.add(pg1, false); + + SpatialReference spatialReference = SpatialReference.create(4326); + + try { + String jSonStr = GeometryEngine + .geometryToJson(spatialReference, pg); + JsonFactory jf = new JsonFactory(); + + JsonParser jp = jf.createJsonParser(jSonStr); + jp.nextToken(); + MapGeometry mg = GeometryEngine.jsonToGeometry(jp); + Geometry gm = mg.getGeometry(); + Assert.assertEquals(Geometry.Type.Polygon, gm.getType()); + Assert.assertTrue(mg.getSpatialReference().getID() == 4326); + + Polygon pgNew = (Polygon) gm; + + Assert.assertEquals(pgNew.getPathCount(), pg.getPathCount()); + Assert.assertEquals(pgNew.getPointCount(), pg.getPointCount()); + Assert.assertEquals(pgNew.getSegmentCount(), pg.getSegmentCount()); + + Assert.assertEquals(pgNew.getPoint(0).getX(), + pg.getPoint(0).getX(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(1).getX(), + pg.getPoint(1).getX(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(2).getX(), + pg.getPoint(2).getX(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(3).getX(), + pg.getPoint(3).getX(), 0.000000001); + + Assert.assertEquals(pgNew.getPoint(0).getY(), + pg.getPoint(0).getY(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(1).getY(), + pg.getPoint(1).getY(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(2).getY(), + pg.getPoint(2).getY(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(3).getY(), + pg.getPoint(3).getY(), 0.000000001); + } catch (Exception ex) { + String err = ex.getMessage(); + System.out.print(err); + throw ex; + } + } + + @Test + public static int fromJsonToWkid(JsonParser parser) + throws JsonParseException, IOException { + int wkid = 0; + if (parser.getCurrentToken() != JsonToken.START_OBJECT) { + return 0; + } + + while (parser.nextToken() != JsonToken.END_OBJECT) { + String fieldName = parser.getCurrentName(); + + if ("wkid".equals(fieldName)) { + parser.nextToken(); + wkid = parser.getIntValue(); + } + } + return wkid; + } + + @SuppressWarnings("unused") + private static void showProjectedGeometryInfo(MapGeometry mapGeom) { + System.out.println("\n"); + MapGeometry geom = mapGeom; + // while ((geom = geomCursor.next()) != null) { + + if (geom.getGeometry() instanceof Point) { + Point pnt = (Point) geom.getGeometry(); + System.out + .println("Point(" + pnt.getX() + " , " + pnt.getY() + ")"); + if (geom.getSpatialReference() == null) { + System.out.println("No spatial reference"); + } else { + System.out.println("wkid: " + + geom.getSpatialReference().getID()); + } + + } else if (geom.getGeometry() instanceof MultiPoint) { + MultiPoint mp = (MultiPoint) geom.getGeometry(); + System.out.println("Multipoint has " + mp.getPointCount() + + " points."); + + System.out.println("wkid: " + geom.getSpatialReference().getID()); + + } else if (geom.getGeometry() instanceof Polygon) { + Polygon mp = (Polygon) geom.getGeometry(); + System.out.println("Polygon has " + mp.getPointCount() + + " points and " + mp.getPathCount() + " parts."); + if (mp.getPathCount() > 1) { + System.out.println("Part start of 2nd segment : " + + mp.getPathStart(1)); + System.out.println("Part end of 2nd segment : " + + mp.getPathEnd(1)); + System.out.println("Part size of 2nd segment : " + + mp.getPathSize(1)); + + int start = mp.getPathStart(1); + int end = mp.getPathEnd(1); + for (int i = start; i < end; i++) { + Point pp = mp.getPoint(i); + System.out.println("Point(" + i + ") = (" + pp.getX() + + ", " + pp.getY() + ")"); + } + } + System.out.println("wkid: " + geom.getSpatialReference().getID()); + + } else if (geom.getGeometry() instanceof Polyline) { + Polyline mp = (Polyline) geom.getGeometry(); + System.out.println("Polyline has " + mp.getPointCount() + + " points and " + mp.getPathCount() + " parts."); + System.out.println("Part start of 2nd segment : " + + mp.getPathStart(1)); + System.out.println("Part end of 2nd segment : " + + mp.getPathEnd(1)); + System.out.println("Part size of 2nd segment : " + + mp.getPathSize(1)); + int start = mp.getPathStart(1); + int end = mp.getPathEnd(1); + for (int i = start; i < end; i++) { + Point pp = mp.getPoint(i); + System.out.println("Point(" + i + ") = (" + pp.getX() + ", " + + pp.getY() + ")"); + } + + System.out.println("wkid: " + geom.getSpatialReference().getID()); + } + } + + @Test + public void testGeometryToJSON() { + Polygon geom = new Polygon(); + geom.startPath(new Point(-113, 34)); + geom.lineTo(new Point(-105, 34)); + geom.lineTo(new Point(-108, 40)); + + String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom);// Test + // WKID + // == -1 + //System.out.println("Geom JSON STRING is" + outputPolygon1); + String correctPolygon1 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]]}"; + + assertEquals(correctPolygon1, outputPolygon1); + + String outputPolygon2 = GeometryEngine.geometryToJson(4326, geom); + //System.out.println("Geom JSON STRING is" + outputPolygon2); + + String correctPolygon2 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":4326}}"; + assertEquals(correctPolygon2, outputPolygon2); + } + + @Test + public void testGeometryToJSONOldID() throws Exception {// CR + Polygon geom = new Polygon(); + geom.startPath(new Point(-113, 34)); + geom.lineTo(new Point(-105, 34)); + geom.lineTo(new Point(-108, 40)); + String outputPolygon = GeometryEngine.geometryToJson( + SpatialReference.create(3857), geom);// Test WKID == -1 + String correctPolygon = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; + assertTrue(outputPolygon.equals(correctPolygon)); + JsonFactory jf = new JsonFactory(); + JsonParser jp = jf.createJsonParser(outputPolygon); + jp.nextToken(); + MapGeometry mg = GeometryEngine.jsonToGeometry(jp); + @SuppressWarnings("unused") + int srId = mg.getSpatialReference().getID(); + @SuppressWarnings("unused") + int srOldId = mg.getSpatialReference().getOldID(); + Assert.assertTrue(mg.getSpatialReference().getID() == 3857); + Assert.assertTrue(mg.getSpatialReference().getLatestID() == 3857); + Assert.assertTrue(mg.getSpatialReference().getOldID() == 102100); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestSerialization.java b/src/test/java/com/esri/core/geometry/TestSerialization.java index 4d736a8c..269b0879 100644 --- a/src/test/java/com/esri/core/geometry/TestSerialization.java +++ b/src/test/java/com/esri/core/geometry/TestSerialization.java @@ -1,380 +1,380 @@ -package com.esri.core.geometry; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import junit.framework.TestCase; -import org.junit.Test; - -public class TestSerialization extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void testSerializePoint() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Point pt = new Point(10, 40); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Point ptRes = (Point) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - fail("Point serialization failure"); - - } - - //try - //{ - //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedPoint1.txt"); - //ObjectOutputStream oo = new ObjectOutputStream(streamOut); - //Point pt = new Point(10, 40, 2); - //oo.writeObject(pt); - //} - //catch(Exception ex) - //{ - //fail("Point serialization failure"); - //} - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedPoint.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Point ptRes = (Point) ii.readObject(); - assertTrue(ptRes.getX() == 10 && ptRes.getY() == 40); - } catch (Exception ex) { - fail("Point serialization failure"); - } - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedPoint1.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Point ptRes = (Point) ii.readObject(); - assertTrue(ptRes.getX() == 10 && ptRes.getY() == 40 && ptRes.getZ() == 2); - } catch (Exception ex) { - fail("Point serialization failure"); - } - - } - - @Test - public void testSerializePolygon() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Polygon pt = new Polygon(); - pt.startPath(10, 10); - pt.lineTo(100, 100); - pt.lineTo(200, 100); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Polygon ptRes = (Polygon) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - fail("Polygon serialization failure"); - } - - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Polygon pt = new Polygon(); - pt.startPath(10, 10); - pt.lineTo(100, 100); - pt.lineTo(200, 100); - pt = (Polygon) GeometryEngine.simplify(pt, null); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Polygon ptRes = (Polygon) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - fail("Polygon serialization failure"); - } - - //try - //{ - //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedPolygon1.txt"); - //ObjectOutputStream oo = new ObjectOutputStream(streamOut); - //Polygon pt = new Polygon(); - //pt.startPath(10, 10); - //pt.lineTo(100, 100); - //pt.lineTo(200, 100); - //pt = (Polygon)GeometryEngine.simplify(pt, null); - //oo.writeObject(pt); - //} - //catch(Exception ex) - //{ - //fail("Polygon serialization failure"); - //} - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedPolygon.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Polygon ptRes = (Polygon) ii.readObject(); - assertTrue(ptRes != null); - } catch (Exception ex) { - fail("Polygon serialization failure"); - } - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedPolygon1.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Polygon ptRes = (Polygon) ii.readObject(); - assertTrue(ptRes != null); - } catch (Exception ex) { - fail("Polygon serialization failure"); - } - } - - @Test - public void testSerializePolyline() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Polyline pt = new Polyline(); - pt.startPath(10, 10); - pt.lineTo(100, 100); - pt.lineTo(200, 100); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Polyline ptRes = (Polyline) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - fail("Polyline serialization failure"); - } - - //try - //{ - //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedPolyline1.txt"); - //ObjectOutputStream oo = new ObjectOutputStream(streamOut); - //Polyline pt = new Polyline(); - //pt.startPath(10, 10); - //pt.lineTo(100, 100); - //pt.lineTo(200, 100); - //oo.writeObject(pt); - //} - //catch(Exception ex) - //{ - //fail("Polyline serialization failure"); - //} - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedPolyline.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Polyline ptRes = (Polyline) ii.readObject(); - assertTrue(ptRes != null); - } catch (Exception ex) { - fail("Polyline serialization failure"); - } - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedPolyline1.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Polyline ptRes = (Polyline) ii.readObject(); - assertTrue(ptRes != null); - } catch (Exception ex) { - fail("Polyline serialization failure"); - } - } - - @Test - public void testSerializeEnvelope() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Envelope pt = new Envelope(10, 10, 400, 300); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Envelope ptRes = (Envelope) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - fail("Envelope serialization failure"); - } - - //try - //{ - //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedEnvelope1.txt"); - //ObjectOutputStream oo = new ObjectOutputStream(streamOut); - //Envelope pt = new Envelope(10, 10, 400, 300); - //oo.writeObject(pt); - //} - //catch(Exception ex) - //{ - //fail("Envelope serialization failure"); - //} - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedEnvelope.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Envelope ptRes = (Envelope) ii.readObject(); - assertTrue(ptRes.getXMax() == 400); - } catch (Exception ex) { - fail("Envelope serialization failure"); - } - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedEnvelope1.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Envelope ptRes = (Envelope) ii.readObject(); - assertTrue(ptRes.getXMax() == 400); - } catch (Exception ex) { - fail("Envelope serialization failure"); - } - } - - @Test - public void testSerializeMultiPoint() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - MultiPoint pt = new MultiPoint(); - pt.add(10, 30); - pt.add(120, 40); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - MultiPoint ptRes = (MultiPoint) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - fail("MultiPoint serialization failure"); - } - - //try - //{ - //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedMultiPoint1.txt"); - //ObjectOutputStream oo = new ObjectOutputStream(streamOut); - //MultiPoint pt = new MultiPoint(); - //pt.add(10, 30); - //pt.add(120, 40); - //oo.writeObject(pt); - //} - //catch(Exception ex) - //{ - //fail("MultiPoint serialization failure"); - //} - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedMultiPoint.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - MultiPoint ptRes = (MultiPoint) ii.readObject(); - assertTrue(ptRes.getPoint(1).getY() == 40); - } catch (Exception ex) { - fail("MultiPoint serialization failure"); - } - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedMultiPoint1.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - MultiPoint ptRes = (MultiPoint) ii.readObject(); - assertTrue(ptRes.getPoint(1).getY() == 40); - } catch (Exception ex) { - fail("MultiPoint serialization failure"); - } - } - - @Test - public void testSerializeLine() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Line pt = new Line(); - pt.setStart(new Point(10, 30)); - pt.setEnd(new Point(120, 40)); - oo.writeObject(pt); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Line ptRes = (Line) ii.readObject(); - assertTrue(ptRes.equals(pt)); - } catch (Exception ex) { - // fail("Line serialization failure"); - assertEquals(ex.getMessage(), "Cannot serialize this geometry"); - } - } - - @Test - public void testSerializeSR() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - SpatialReference sr = SpatialReference.create(102100); - oo.writeObject(sr); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - SpatialReference ptRes = (SpatialReference) ii.readObject(); - assertTrue(ptRes.equals(sr)); - } catch (Exception ex) { - fail("Spatial Reference serialization failure"); - } - } - - @Test - public void testSerializeEnvelope2D() { - try { - ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(streamOut); - Envelope2D env = new Envelope2D(1.213948734, 2.213948734, 11.213948734, 12.213948734); - oo.writeObject(env); - ByteArrayInputStream streamIn = new ByteArrayInputStream( - streamOut.toByteArray()); - ObjectInputStream ii = new ObjectInputStream(streamIn); - Envelope2D envRes = (Envelope2D)ii.readObject(); - assertTrue(envRes.equals(env)); - } catch (Exception ex) { - fail("Envelope2D serialization failure"); - } - -// try -// { -// FileOutputStream streamOut = new FileOutputStream( -// "c:/temp/savedEnvelope2D.txt"); -// ObjectOutputStream oo = new ObjectOutputStream(streamOut); -// Envelope2D e = new Envelope2D(177.123, 188.234, 999.122, 888.999); -// oo.writeObject(e); -// } -// catch(Exception ex) -// { -// fail("Envelope2D serialization failure"); -// } - - try { - InputStream s = TestSerialization.class - .getResourceAsStream("savedEnvelope2D.txt"); - ObjectInputStream ii = new ObjectInputStream(s); - Envelope2D e = (Envelope2D) ii - .readObject(); - assertTrue(e != null); - assertTrue(e.equals(new Envelope2D(177.123, 188.234, 999.122, 888.999))); - } catch (Exception ex) { - fail("Envelope2D serialization failure"); - } - } - -} +package com.esri.core.geometry; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import junit.framework.TestCase; +import org.junit.Test; + +public class TestSerialization extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testSerializePoint() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Point pt = new Point(10, 40); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Point ptRes = (Point) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + fail("Point serialization failure"); + + } + + //try + //{ + //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedPoint1.txt"); + //ObjectOutputStream oo = new ObjectOutputStream(streamOut); + //Point pt = new Point(10, 40, 2); + //oo.writeObject(pt); + //} + //catch(Exception ex) + //{ + //fail("Point serialization failure"); + //} + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedPoint.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Point ptRes = (Point) ii.readObject(); + assertTrue(ptRes.getX() == 10 && ptRes.getY() == 40); + } catch (Exception ex) { + fail("Point serialization failure"); + } + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedPoint1.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Point ptRes = (Point) ii.readObject(); + assertTrue(ptRes.getX() == 10 && ptRes.getY() == 40 && ptRes.getZ() == 2); + } catch (Exception ex) { + fail("Point serialization failure"); + } + + } + + @Test + public void testSerializePolygon() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Polygon pt = new Polygon(); + pt.startPath(10, 10); + pt.lineTo(100, 100); + pt.lineTo(200, 100); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Polygon ptRes = (Polygon) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + fail("Polygon serialization failure"); + } + + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Polygon pt = new Polygon(); + pt.startPath(10, 10); + pt.lineTo(100, 100); + pt.lineTo(200, 100); + pt = (Polygon) GeometryEngine.simplify(pt, null); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Polygon ptRes = (Polygon) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + fail("Polygon serialization failure"); + } + + //try + //{ + //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedPolygon1.txt"); + //ObjectOutputStream oo = new ObjectOutputStream(streamOut); + //Polygon pt = new Polygon(); + //pt.startPath(10, 10); + //pt.lineTo(100, 100); + //pt.lineTo(200, 100); + //pt = (Polygon)GeometryEngine.simplify(pt, null); + //oo.writeObject(pt); + //} + //catch(Exception ex) + //{ + //fail("Polygon serialization failure"); + //} + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedPolygon.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Polygon ptRes = (Polygon) ii.readObject(); + assertTrue(ptRes != null); + } catch (Exception ex) { + fail("Polygon serialization failure"); + } + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedPolygon1.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Polygon ptRes = (Polygon) ii.readObject(); + assertTrue(ptRes != null); + } catch (Exception ex) { + fail("Polygon serialization failure"); + } + } + + @Test + public void testSerializePolyline() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Polyline pt = new Polyline(); + pt.startPath(10, 10); + pt.lineTo(100, 100); + pt.lineTo(200, 100); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Polyline ptRes = (Polyline) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + fail("Polyline serialization failure"); + } + + //try + //{ + //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedPolyline1.txt"); + //ObjectOutputStream oo = new ObjectOutputStream(streamOut); + //Polyline pt = new Polyline(); + //pt.startPath(10, 10); + //pt.lineTo(100, 100); + //pt.lineTo(200, 100); + //oo.writeObject(pt); + //} + //catch(Exception ex) + //{ + //fail("Polyline serialization failure"); + //} + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedPolyline.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Polyline ptRes = (Polyline) ii.readObject(); + assertTrue(ptRes != null); + } catch (Exception ex) { + fail("Polyline serialization failure"); + } + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedPolyline1.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Polyline ptRes = (Polyline) ii.readObject(); + assertTrue(ptRes != null); + } catch (Exception ex) { + fail("Polyline serialization failure"); + } + } + + @Test + public void testSerializeEnvelope() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Envelope pt = new Envelope(10, 10, 400, 300); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Envelope ptRes = (Envelope) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + fail("Envelope serialization failure"); + } + + //try + //{ + //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedEnvelope1.txt"); + //ObjectOutputStream oo = new ObjectOutputStream(streamOut); + //Envelope pt = new Envelope(10, 10, 400, 300); + //oo.writeObject(pt); + //} + //catch(Exception ex) + //{ + //fail("Envelope serialization failure"); + //} + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedEnvelope.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Envelope ptRes = (Envelope) ii.readObject(); + assertTrue(ptRes.getXMax() == 400); + } catch (Exception ex) { + fail("Envelope serialization failure"); + } + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedEnvelope1.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Envelope ptRes = (Envelope) ii.readObject(); + assertTrue(ptRes.getXMax() == 400); + } catch (Exception ex) { + fail("Envelope serialization failure"); + } + } + + @Test + public void testSerializeMultiPoint() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + MultiPoint pt = new MultiPoint(); + pt.add(10, 30); + pt.add(120, 40); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + MultiPoint ptRes = (MultiPoint) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + fail("MultiPoint serialization failure"); + } + + //try + //{ + //FileOutputStream streamOut = new FileOutputStream("c:/temp/savedMultiPoint1.txt"); + //ObjectOutputStream oo = new ObjectOutputStream(streamOut); + //MultiPoint pt = new MultiPoint(); + //pt.add(10, 30); + //pt.add(120, 40); + //oo.writeObject(pt); + //} + //catch(Exception ex) + //{ + //fail("MultiPoint serialization failure"); + //} + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedMultiPoint.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + MultiPoint ptRes = (MultiPoint) ii.readObject(); + assertTrue(ptRes.getPoint(1).getY() == 40); + } catch (Exception ex) { + fail("MultiPoint serialization failure"); + } + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedMultiPoint1.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + MultiPoint ptRes = (MultiPoint) ii.readObject(); + assertTrue(ptRes.getPoint(1).getY() == 40); + } catch (Exception ex) { + fail("MultiPoint serialization failure"); + } + } + + @Test + public void testSerializeLine() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Line pt = new Line(); + pt.setStart(new Point(10, 30)); + pt.setEnd(new Point(120, 40)); + oo.writeObject(pt); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Line ptRes = (Line) ii.readObject(); + assertTrue(ptRes.equals(pt)); + } catch (Exception ex) { + // fail("Line serialization failure"); + assertEquals(ex.getMessage(), "Cannot serialize this geometry"); + } + } + + @Test + public void testSerializeSR() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + SpatialReference sr = SpatialReference.create(102100); + oo.writeObject(sr); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + SpatialReference ptRes = (SpatialReference) ii.readObject(); + assertTrue(ptRes.equals(sr)); + } catch (Exception ex) { + fail("Spatial Reference serialization failure"); + } + } + + @Test + public void testSerializeEnvelope2D() { + try { + ByteArrayOutputStream streamOut = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(streamOut); + Envelope2D env = new Envelope2D(1.213948734, 2.213948734, 11.213948734, 12.213948734); + oo.writeObject(env); + ByteArrayInputStream streamIn = new ByteArrayInputStream( + streamOut.toByteArray()); + ObjectInputStream ii = new ObjectInputStream(streamIn); + Envelope2D envRes = (Envelope2D)ii.readObject(); + assertTrue(envRes.equals(env)); + } catch (Exception ex) { + fail("Envelope2D serialization failure"); + } + +// try +// { +// FileOutputStream streamOut = new FileOutputStream( +// "c:/temp/savedEnvelope2D.txt"); +// ObjectOutputStream oo = new ObjectOutputStream(streamOut); +// Envelope2D e = new Envelope2D(177.123, 188.234, 999.122, 888.999); +// oo.writeObject(e); +// } +// catch(Exception ex) +// { +// fail("Envelope2D serialization failure"); +// } + + try { + InputStream s = TestSerialization.class + .getResourceAsStream("savedEnvelope2D.txt"); + ObjectInputStream ii = new ObjectInputStream(s); + Envelope2D e = (Envelope2D) ii + .readObject(); + assertTrue(e != null); + assertTrue(e.equals(new Envelope2D(177.123, 188.234, 999.122, 888.999))); + } catch (Exception ex) { + fail("Envelope2D serialization failure"); + } + } + +} diff --git a/src/test/java/com/esri/core/geometry/TestSimplify.java b/src/test/java/com/esri/core/geometry/TestSimplify.java index b7380851..47a741c1 100644 --- a/src/test/java/com/esri/core/geometry/TestSimplify.java +++ b/src/test/java/com/esri/core/geometry/TestSimplify.java @@ -1,1344 +1,1344 @@ -package com.esri.core.geometry; - -//import java.io.FileOutputStream; -//import java.io.PrintStream; -//import java.util.ArrayList; -//import java.util.List; -//import java.util.Random; -import java.io.IOException; - -import junit.framework.TestCase; - -import org.junit.Test; - -import com.fasterxml.jackson.core.JsonFactory; - -public class TestSimplify extends TestCase { - OperatorFactoryLocal factory = null; - OperatorSimplify simplifyOp = null; - OperatorSimplifyOGC simplifyOpOGC = null; - SpatialReference sr102100 = null; - SpatialReference sr4326 = null; - SpatialReference sr3857 = null; - - @Override - protected void setUp() throws Exception { - super.setUp(); - factory = OperatorFactoryLocal.getInstance(); - simplifyOp = (OperatorSimplify) factory - .getOperator(Operator.Type.Simplify); - simplifyOpOGC = (OperatorSimplifyOGC) factory - .getOperator(Operator.Type.SimplifyOGC); - sr102100 = SpatialReference.create(102100); - sr3857 = SpatialReference.create(3857);// PE_PCS_WGS_1984_WEB_MERCATOR_AUXSPHERE); - sr4326 = SpatialReference.create(4326);// enum_value2(SpatialReference, - // Code, GCS_WGS_1984)); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - public Polygon makeNonSimplePolygon2() { - //MapGeometry mg = OperatorFactoryLocal.loadGeometryFromJSONFileDbg("c:/temp/simplify_polygon_gnomonic.txt"); - //Geometry res = OperatorSimplify.local().execute(mg.getGeometry(), mg.getSpatialReference(), true, null); - - - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 15); - poly.lineTo(15, 15); - poly.lineTo(15, 0); - - // This is an interior ring but it is clockwise - poly.startPath(5, 5); - poly.lineTo(5, 6); - poly.lineTo(6, 6); - poly.lineTo(6, 5); - - return poly; - }// done - - /* - * ------------>---------------->--------------- | | | (1) | | | | --->--- - * ------->------- | | | | | (5) | | | | | | --<-- | | | | (2) | | | | | | | - * | | | | (4) | | | | | | | -->-- | | --<-- | ---<--- | | | | | | - * -------<------- | | (3) | -------------<---------------<--------------- - * -->-- - */ - - // Bowtie case with vertices at intersection - - public Polygon makeNonSimplePolygon5() { - Polygon poly = new Polygon(); - poly.startPath(10, 0); - poly.lineTo(0, 0); - poly.lineTo(5, 5); - poly.lineTo(10, 10); - poly.lineTo(0, 10); - poly.lineTo(5, 5); - - return poly; - }// done - - @Test - public void test0() { - Polygon poly1 = new Polygon(); - poly1.addEnvelope(new Envelope(10, 10, 40, 20), false); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - boolean res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, - null); - assertTrue(res); - // assertTrue(poly1.equals(poly2)); - }// done - - @Test - public void test0Poly() {// simple - Polygon poly1 = new Polygon(); - poly1.addEnvelope(new Envelope(10, 10, 40, 20), false); - poly1.addEnvelope(new Envelope(50, 10, 100, 20), false); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - boolean res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, - null); - assertTrue(res); - // assertTrue(poly1.equals(poly2)); - }// done - - @Test - public void test0Polygon_Spike1() {// non-simple (spike) - Polygon poly1 = new Polygon(); - poly1.startPath(10, 10); - poly1.lineTo(10, 20); - poly1.lineTo(40, 20); - poly1.lineTo(40, 10); - poly1.lineTo(60, 10); - poly1.lineTo(70, 10); - - boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, - null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(poly2.getPointCount() == 4); - }// done - - @Test - public void test0Polygon_Spike2() {// non-simple (spikes) - Polygon poly1 = new Polygon(); - // rectangle with a spike - poly1.startPath(10, 10); - poly1.lineTo(10, 20); - poly1.lineTo(40, 20); - poly1.lineTo(40, 10); - poly1.lineTo(60, 10); - poly1.lineTo(70, 10); - - // degenerate - poly1.startPath(100, 100); - poly1.lineTo(100, 120); - poly1.lineTo(100, 130); - - boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, - null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(poly2.getPointCount() == 4); - }// done - - @Test - public void test0Polygon_Spike3() {// non-simple (spikes) - Polygon poly1 = new Polygon(); - // degenerate - poly1.startPath(100, 100); - poly1.lineTo(100, 120); - poly1.lineTo(100, 130); - - boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, - null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(poly2.isEmpty()); - }// done - - @Test - public void test0PolygonSelfIntersect1() {// non-simple (self-intersection) - Polygon poly1 = new Polygon(); - // touch uncracked - poly1.startPath(0, 0); - poly1.lineTo(0, 100); - poly1.lineTo(100, 100); - poly1.lineTo(0, 50); - poly1.lineTo(100, 0); - - boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, - null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void test0PolygonSelfIntersect2() {// non-simple (self-intersection) - Polygon poly1 = new Polygon(); - poly1.startPath(0, 0); - poly1.lineTo(0, 100); - poly1.lineTo(100, 100); - poly1.lineTo(-100, 0); - // poly1.lineTo(100, 0); - - boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, - null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void test0PolygonSelfIntersect3() { - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 15); - poly.lineTo(15, 15); - poly.lineTo(15, 0); - - // This part intersects with the first part - poly.startPath(10, 10); - poly.lineTo(10, 20); - poly.lineTo(20, 20); - poly.lineTo(20, 10); - - boolean res = simplifyOp - .isSimpleAsFeature(poly, null, true, null, null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void test0PolygonInteriorRing1() { - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 15); - poly.lineTo(15, 15); - poly.lineTo(15, 0); - - // This is an interior ring but it is clockwise - poly.startPath(5, 5); - poly.lineTo(5, 6); - poly.lineTo(6, 6); - poly.lineTo(6, 5); - - boolean res = simplifyOp - .isSimpleAsFeature(poly, null, true, null, null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void test0PolygonInteriorRing2() { - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 15); - poly.lineTo(15, 15); - poly.lineTo(15, 0); - - // This is an interior ring but it is clockwise - poly.startPath(5, 5); - poly.lineTo(5, 6); - poly.lineTo(6, 6); - poly.lineTo(6, 5); - - // This part intersects with the first part - poly.startPath(10, 10); - poly.lineTo(10, 20); - poly.lineTo(20, 20); - poly.lineTo(20, 10); - - boolean res = simplifyOp - .isSimpleAsFeature(poly, null, true, null, null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void test0PolygonInteriorRingWithCommonBoundary1() { - // Two rings have common boundary - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 10); - poly.lineTo(10, 10); - poly.lineTo(10, 0); - - poly.startPath(10, 0); - poly.lineTo(10, 10); - poly.lineTo(20, 10); - poly.lineTo(20, 0); - - boolean res = simplifyOp - .isSimpleAsFeature(poly, null, true, null, null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void test0PolygonInteriorRingWithCommonBoundary2() { - // Two rings have common boundary - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 10); - poly.lineTo(10, 10); - poly.lineTo(10, 0); - - poly.startPath(10, 5); - poly.lineTo(10, 6); - poly.lineTo(20, 6); - poly.lineTo(20, 5); - - boolean res = simplifyOp - .isSimpleAsFeature(poly, null, true, null, null); - assertTrue(!res); - Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); - res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); - assertTrue(res); - assertTrue(!poly2.isEmpty()); - }// done - - @Test - public void testPolygon() { - Polygon nonSimplePolygon = makeNonSimplePolygon(); - Polygon simplePolygon = (Polygon) simplifyOp.execute(nonSimplePolygon, - sr3857, false, null); - - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon, sr3857, true, - null, null); - assertTrue(res); - - @SuppressWarnings("unused") - int partCount = simplePolygon.getPathCount(); - // assertTrue(partCount == 2); - - double area = simplePolygon.calculateRingArea2D(0); - assertTrue(Math.abs(area - 300) <= 0.0001); - - area = simplePolygon.calculateRingArea2D(1); - assertTrue(Math.abs(area - (-25.0)) <= 0.0001); - }// done - - @Test - public void testPolygon2() { - Polygon nonSimplePolygon2 = makeNonSimplePolygon2(); - double area = nonSimplePolygon2.calculateRingArea2D(1); - assertTrue(Math.abs(area - 1.0) <= 0.0001); - - Polygon simplePolygon2 = (Polygon) simplifyOp.execute( - nonSimplePolygon2, sr3857, false, null); - - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon2, sr3857, - true, null, null); - assertTrue(res); - - area = simplePolygon2.calculateRingArea2D(0); - assertTrue(Math.abs(area - 225) <= 0.0001); - - area = simplePolygon2.calculateRingArea2D(1); - assertTrue(Math.abs(area - (-1.0)) <= 0.0001); - }// done - - @Test - public void testPolygon3() { - Polygon nonSimplePolygon3 = makeNonSimplePolygon3(); - Polygon simplePolygon3 = (Polygon) simplifyOp.execute( - nonSimplePolygon3, sr3857, false, null); - - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon3, sr3857, - true, null, null); - assertTrue(res); - - double area = simplePolygon3.calculateRingArea2D(0); - assertTrue(Math.abs(area - 875) <= 0.0001); - - area = simplePolygon3.calculateRingArea2D(1); - assertTrue(Math.abs(area - (-225)) <= 0.0001 - || Math.abs(area - (-50.0)) <= 0.0001); - - area = simplePolygon3.calculateRingArea2D(2); - assertTrue(Math.abs(area - (-225)) <= 0.0001 - || Math.abs(area - (-50.0)) <= 0.0001); - - area = simplePolygon3.calculateRingArea2D(3); - assertTrue(Math.abs(area - 25) <= 0.0001); - - area = simplePolygon3.calculateRingArea2D(4); - assertTrue(Math.abs(area - 25) <= 0.0001); - }// done - - @Test - public void testPolyline() { - Polyline nonSimplePolyline = makeNonSimplePolyline(); - Polyline simplePolyline = (Polyline) simplifyOp.execute( - nonSimplePolyline, sr3857, false, null); - - int segmentCount = simplePolyline.getSegmentCount(); - assertTrue(segmentCount == 4); - }// done - - @Test - public void testPolygon4() { - Polygon nonSimplePolygon4 = makeNonSimplePolygon4(); - Polygon simplePolygon4 = (Polygon) simplifyOp.execute( - nonSimplePolygon4, sr3857, false, null); - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon4, sr3857, - true, null, null); - assertTrue(res); - - assertTrue(simplePolygon4.getPointCount() == 5); - Point point = nonSimplePolygon4.getPoint(0); - assertTrue(point.getX() == 0.0 && point.getY() == 0.0); - point = nonSimplePolygon4.getPoint(1); - assertTrue(point.getX() == 0.0 && point.getY() == 10.0); - point = nonSimplePolygon4.getPoint(2); - assertTrue(point.getX() == 10.0 && point.getY() == 10.0); - point = nonSimplePolygon4.getPoint(3); - assertTrue(point.getX() == 10.0 && point.getY() == 0.0); - point = nonSimplePolygon4.getPoint(4); - assertTrue(point.getX() == 5.0 && point.getY() == 0.0); - }// done - - @Test - public void testPolygon5() { - Polygon nonSimplePolygon5 = makeNonSimplePolygon5(); - Polygon simplePolygon5 = (Polygon) simplifyOp.execute( - nonSimplePolygon5, sr3857, false, null); - assertTrue(simplePolygon5 != null); - - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon5, sr3857, - true, null, null); - assertTrue(res); - - int pointCount = simplePolygon5.getPointCount(); - assertTrue(pointCount == 6); - - double area = simplePolygon5.calculateArea2D(); - assertTrue(Math.abs(area - 50.0) <= 0.001); - - }// done - - @Test - public void testPolygon6() { - Polygon nonSimplePolygon6 = makeNonSimplePolygon6(); - Polygon simplePolygon6 = (Polygon) simplifyOp.execute( - nonSimplePolygon6, sr3857, false, null); - - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon6, sr3857, - true, null, null); - assertTrue(res); - } - - @Test - public void testPolygon7() { - Polygon nonSimplePolygon7 = makeNonSimplePolygon7(); - Polygon simplePolygon7 = (Polygon) simplifyOp.execute( - nonSimplePolygon7, sr3857, false, null); - - boolean res = simplifyOp.isSimpleAsFeature(simplePolygon7, sr3857, - true, null, null); - assertTrue(res); - } - - public Polygon makeNonSimplePolygon() { - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 15); - poly.lineTo(15, 15); - poly.lineTo(15, 0); - - // This is an interior ring but it is clockwise - poly.startPath(5, 5); - poly.lineTo(5, 6); - poly.lineTo(6, 6); - poly.lineTo(6, 5); - - // This part intersects with the first part - poly.startPath(10, 10); - poly.lineTo(10, 20); - poly.lineTo(20, 20); - poly.lineTo(20, 10); - - return poly; - }// done - - /* - * ------------>---------------->--------------- | | | (1) | | | | --->--- - * ------->------- | | | | | (5) | | | | | | --<-- | | | | (2) | | | | | | | - * | | | | (4) | | | | | | | -->-- | | --<-- | ---<--- | | | | | | - * -------<------- | | (3) | -------------<---------------<--------------- - * -->-- - */ - - public Polygon makeNonSimplePolygon3() { - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 25); - poly.lineTo(35, 25); - poly.lineTo(35, 0); - - poly.startPath(5, 5); - poly.lineTo(5, 15); - poly.lineTo(10, 15); - poly.lineTo(10, 5); - - poly.startPath(40, 0); - poly.lineTo(45, 0); - poly.lineTo(45, 5); - poly.lineTo(40, 5); - - poly.startPath(20, 10); - poly.lineTo(25, 10); - poly.lineTo(25, 15); - poly.lineTo(20, 15); - - poly.startPath(15, 5); - poly.lineTo(15, 20); - poly.lineTo(30, 20); - poly.lineTo(30, 5); - - return poly; - }// done - - public Polygon makeNonSimplePolygon4() { - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(0, 10); - poly.lineTo(10, 10); - poly.lineTo(10, 0); - poly.lineTo(5, 0); - poly.lineTo(5, 5); - poly.lineTo(5, 0); - - return poly; - }// done - - public Polygon makeNonSimplePolygon6() { - Polygon poly = new Polygon(); - poly.startPath(35.34407570857744, 54.00551247713412); - poly.lineTo(41.07663499357954, 20.0); - poly.lineTo(40.66372033705177, 26.217432321849017); - - poly.startPath(42.81936574509338, 20.0); - poly.lineTo(43.58226670584747, 20.0); - poly.lineTo(39.29611825817084, 22.64634933678729); - poly.lineTo(44.369873312241346, 25.81893670527215); - poly.lineTo(42.68845660737179, 20.0); - poly.lineTo(38.569549792944244, 56.47456192829393); - poly.lineTo(42.79274114188401, 45.45117792578003); - poly.lineTo(41.09512147544657, 70.0); - - return poly; - } - - public Polygon makeNonSimplePolygon7() { - Polygon poly = new Polygon(); - - poly.startPath(41.987895433319686, 53.75822619011542); - poly.lineTo(41.98789542535497, 53.75822618803151); - poly.lineTo(40.15120412113667, 68.12604154722113); - poly.lineTo(37.72272697311022, 67.92767094118877); - poly.lineTo(37.147347454283086, 49.497473094145505); - poly.lineTo(38.636627026664385, 51.036687142232736); - - poly.startPath(39.00920080789793, 62.063425518369016); - poly.lineTo(38.604912643136885, 70.0); - poly.lineTo(40.71826863485308, 43.60337143116787); - poly.lineTo(35.34407570857744, 54.005512477134126); - poly.lineTo(39.29611825817084, 22.64634933678729); - - return poly; - } - - public Polyline makeNonSimplePolyline() { - // This polyline has a short segment - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(10, 0); - poly.lineTo(10, 10); - poly.lineTo(10, 5); - poly.lineTo(-5, 5); - - return poly; - }// done - - @Test - public void testIsSimpleBasicsPoint() { - boolean result; - // point is always simple - Point pt = new Point(); - result = simplifyOp.isSimpleAsFeature(pt, sr4326, false, null, null); - assertTrue(result); - pt.setXY(0, 0); - result = simplifyOp.isSimpleAsFeature(pt, sr4326, false, null, null); - assertTrue(result); - pt.setXY(100000, 10000); - result = simplifyOp.isSimpleAsFeature(pt, sr4326, false, null, null); - assertTrue(result); - }// done - - @Test - public void testIsSimpleBasicsEnvelope() { - // Envelope is simple, when it's width and height are not degenerate - Envelope env = new Envelope(); - boolean result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, - null); // Empty is simple - assertTrue(result); - env.setCoords(0, 0, 10, 10); - result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, null); - assertTrue(result); - // sliver but still simple - env.setCoords(0, 0, 0 + sr4326.getTolerance() * 2, 10); - result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, null); - assertTrue(result); - // sliver and not simple - env.setCoords(0, 0, 0 + sr4326.getTolerance() * 0.5, 10); - result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, null); - assertTrue(!result); - }// done - - @Test - public void testIsSimpleBasicsLine() { - Line line = new Line(); - boolean result = simplifyOp.isSimpleAsFeature(line, sr4326, false, - null, null); - assertTrue(!result); - - line.setStart(new Point(0, 0)); - // line.setEndXY(0, 0); - result = simplifyOp.isSimpleAsFeature(line, sr4326, false, null, null); - assertTrue(!result); - line.setEnd(new Point(1, 0)); - result = simplifyOp.isSimpleAsFeature(line, sr4326, false, null, null); - assertTrue(result); - }// done - - @Test - public void testIsSimpleMultiPoint1() { - MultiPoint mp = new MultiPoint(); - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(result);// empty is simple - result = simplifyOp.isSimpleAsFeature( - simplifyOp.execute(mp, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - }// done - - @Test - public void testIsSimpleMultiPoint2FarApart() { - // Two point test: far apart - MultiPoint mp = new MultiPoint(); - mp.add(20, 10); - mp.add(100, 100); - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(result); - result = simplifyOp.isSimpleAsFeature( - simplifyOp.execute(mp, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - assertTrue(mp.getPointCount() == 2); - }// done - - @Test - public void testIsSimpleMultiPointCoincident() { - // Two point test: coincident - MultiPoint mp = new MultiPoint(); - mp.add(100, 100); - mp.add(100, 100); - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(!result); - MultiPoint mpS; - result = simplifyOp.isSimpleAsFeature( - mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), - sr4326, false, null, null); - assertTrue(result); - assertTrue(mpS.getPointCount() == 1); - }// done - - @Test - public void testMultiPointSR4326_CR184439() { - OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); - OperatorSimplify simpOp = (OperatorSimplify) engine - .getOperator(Operator.Type.Simplify); - NonSimpleResult nonSimpResult = new NonSimpleResult(); - nonSimpResult.m_reason = NonSimpleResult.Reason.NotDetermined; - MultiPoint multiPoint = new MultiPoint(); - multiPoint.add(0, 0); - multiPoint.add(0, 1); - multiPoint.add(0, 0); - Boolean multiPointIsSimple = simpOp.isSimpleAsFeature(multiPoint, - SpatialReference.create(4326), true, nonSimpResult, null); - assertFalse(multiPointIsSimple); - assertTrue(nonSimpResult.m_reason == NonSimpleResult.Reason.Clustering); - assertTrue(nonSimpResult.m_vertexIndex1 == 0); - assertTrue(nonSimpResult.m_vertexIndex2 == 2); - } - - @Test - public void testIsSimpleMultiPointCloserThanTolerance() { - // Two point test: closer than tolerance - MultiPoint mp = new MultiPoint(); - MultiPoint mpS; - mp.add(100, 100); - mp.add(100, 100 + sr4326.getTolerance() * .5); - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(result); - result = simplifyOp.isSimpleAsFeature( - mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), - sr4326, false, null, null); - assertTrue(result); - assertTrue(mpS.getPointCount() == 2); - }// done - - @Test - public void testIsSimpleMultiPointFarApart2() { - // 5 point test: far apart - MultiPoint mp = new MultiPoint(); - mp.add(100, 100); - mp.add(100, 101); - mp.add(101, 101); - mp.add(11, 1); - mp.add(11, 14); - MultiPoint mpS; - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(result); - result = simplifyOp.isSimpleAsFeature( - mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), - sr4326, false, null, null); - assertTrue(result); - assertTrue(mpS.getPointCount() == 5); - }// done - - @Test - public void testIsSimpleMultiPoint_coincident2() { - // 5 point test: coincident - MultiPoint mp = new MultiPoint(); - mp.add(100, 100); - mp.add(100, 101); - mp.add(100, 100); - mp.add(11, 1); - mp.add(11, 14); - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(!result); - MultiPoint mpS; - result = simplifyOp.isSimpleAsFeature( - mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), - sr4326, false, null, null); - assertTrue(result); - assertTrue(mpS.getPointCount() == 4); - assertEquals(mpS.getPoint(0).getX(), 100, 1e-7); - assertEquals(mpS.getPoint(0).getY(), 100, 1e-7); - assertEquals(mpS.getPoint(1).getX(), 100, 1e-7); - assertEquals(mpS.getPoint(1).getY(), 101, 1e-7); - assertEquals(mpS.getPoint(2).getX(), 11, 1e-7); - assertEquals(mpS.getPoint(2).getY(), 1, 1e-7); - assertEquals(mpS.getPoint(3).getX(), 11, 1e-7); - assertEquals(mpS.getPoint(3).getY(), 14, 1e-7); - }// done - - @Test - public void testIsSimpleMultiPointCloserThanTolerance2() { - // 5 point test: closer than tolerance - MultiPoint mp = new MultiPoint(); - mp.add(100, 100); - mp.add(100, 101); - mp.add(100, 100 + sr4326.getTolerance() / 2); - mp.add(11, 1); - mp.add(11, 14); - MultiPoint mpS; - boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, - null); - assertTrue(result); - result = simplifyOp.isSimpleAsFeature( - mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), - sr4326, false, null, null); - assertTrue(result); - assertTrue(mpS.getPointCount() == 5); - }// done - - @Test - public void testIsSimplePolyline() { - Polyline poly = new Polyline(); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// empty is simple - } - - @Test - public void testIsSimplePolylineFarApart() { - // Two point test: far apart - Polyline poly = new Polyline(); - poly.startPath(20, 10); - poly.lineTo(100, 100); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - } - - @Test - public void testIsSimplePolylineCoincident() { - // Two point test: coincident - Polyline poly = new Polyline(); - poly.startPath(100, 100); - poly.lineTo(100, 100); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - @SuppressWarnings("unused") - Polyline polyS; - result = simplifyOp.isSimpleAsFeature( - polyS = (Polyline) simplifyOp - .execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - } - - @Test - public void testIsSimplePolylineCloserThanTolerance() { - // Two point test: closer than tolerance - Polyline poly = new Polyline(); - poly.startPath(100, 100); - poly.lineTo(100, 100 + sr4326.getTolerance() / 2); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - @SuppressWarnings("unused") - Polyline polyS; - result = simplifyOp.isSimpleAsFeature( - polyS = (Polyline) simplifyOp - .execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - } - - @Test - public void testIsSimplePolylineFarApartSelfOverlap0() { - // 3 point test: far apart, self overlapping - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(0, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// TO CONFIRM should be false - } - - @Test - public void testIsSimplePolylineSelfIntersect() { - // 4 point test: far apart, self intersecting - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(0, 100); - poly.lineTo(100, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// TO CONFIRM should be false - } - - @Test - public void testIsSimplePolylineDegenerateSegment() { - // 4 point test: degenerate segment - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(100, 100 + sr4326.getTolerance() / 2); - poly.lineTo(100, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - @SuppressWarnings("unused") - Polyline polyS; - result = simplifyOp.isSimpleAsFeature( - polyS = (Polyline) simplifyOp - .execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - { - Polyline other = new Polyline(); - other.startPath(0, 0); - other.lineTo(100, 100); - other.lineTo(100, 0); - other.equals(poly); - } - } - - @Test - public void testIsSimplePolylineFarApartSelfOverlap() { - // 3 point test: far apart, self overlapping - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(0, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// TO CONFIRM should be false - } - - @Test - public void testIsSimplePolylineFarApartIntersect() { - // 4 point 2 parts test: far apart, intersecting parts - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.startPath(100, 0); - poly.lineTo(0, 100); - - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// TO CONFIRM should be false - } - - @Test - public void testIsSimplePolylineFarApartOverlap2() { - // 4 point 2 parts test: far apart, overlapping parts. second part - // starts where first one ends - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.startPath(100, 100); - poly.lineTo(0, 100); - - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// TO CONFIRM should be false - } - - @Test - public void testIsSimplePolylineDegenerateVertical() { - // 3 point test: degenerate vertical line - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(new Point(100, 100)); - poly.lineTo(new Point(100, 100)); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - Polyline polyS; - result = simplifyOp.isSimpleAsFeature( - polyS = (Polyline) simplifyOp - .execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - assertTrue(polyS.getPointCount() == 2); - } - - @Test - public void testIsSimplePolylineEmptyPath() { - // TODO: any way to test this? - // Empty path - // Polyline poly = new Polyline(); - // assertTrue(poly.isEmpty()); - // poly.addPath(new Polyline(), 0, true); - // assertTrue(poly.isEmpty()); - // boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - // null, null); - // assertTrue(result); - } - - @Test - public void testIsSimplePolylineSinglePointInPath() { - // Single point in path - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.removePoint(0, 1); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - Polyline polyS; - result = simplifyOp.isSimpleAsFeature( - polyS = (Polyline) simplifyOp - .execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - assertTrue(polyS.isEmpty()); - } - - @Test - public void testIsSimplePolygon() { - Polygon poly = new Polygon(); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result);// empty is simple - result = simplifyOp.isSimpleAsFeature( - simplifyOp.execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result);// empty is simple - } - - @Test - public void testIsSimplePolygonEmptyPath() { - // TODO: - // Empty path - // Polygon poly = new Polygon(); - // poly.addPath(new Polyline(), 0, true); - // assertTrue(poly.getPathCount() == 1); - // boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - // null, - // null); - // assertTrue(result); - // result = simplifyOp.isSimpleAsFeature(simplifyOp.execute(poly, - // sr4326, false, null), sr4326, false, null, null); - // assertTrue(result);// empty is simple - // assertTrue(poly.getPathCount() == 1); - } - - @Test - public void testIsSimplePolygonIncomplete1() { - // Incomplete polygon 1 - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - // poly.removePoint(0, 1);//TO CONFIRM no removePoint method in Java - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonIncomplete2() { - // Incomplete polygon 2 - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonDegenerateTriangle() { - // Degenerate triangle (self overlap) - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(0, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonSelfIntersect() { - // Self intersection - cracking is needed - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(0, 100); - poly.lineTo(100, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonRectangleHole() { - // Rectangle and rectangular hole that has one segment overlapping - // with the with the exterior ring. Cracking is needed. - Polygon poly = new Polygon(); - poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); - poly.addEnvelope(new Envelope(-100, -100, 100, 50), true); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonRectangleHole2() { - // Rectangle and rectangular hole - Polygon poly = new Polygon(); - poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); - poly.addEnvelope(new Envelope(-100, -50, 100, 50), true); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonSelfIntersectAtVertex() { - // Self intersection at vertex - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(50, 50); - poly.lineTo(100, 100); - poly.lineTo(0, 100); - poly.lineTo(50, 50); - poly.lineTo(100, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - result = simplifyOp.isSimpleAsFeature( - simplifyOp.execute(poly, sr4326, false, null), sr4326, false, - null, null); - assertTrue(result); - } - - @Test - public void testIsSimplePolygon_2EdgesTouchAtVertex() { - // No self-intersection, but more than two edges touch at the same - // vertex. Simple for ArcGIS, not simple for OGC - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(50, 50); - poly.lineTo(0, 100); - poly.lineTo(100, 100); - poly.lineTo(50, 50); - poly.lineTo(100, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - } - - @Test - public void testIsSimplePolygonTriangle() { - // Triangle - Polygon poly = new Polygon(); - poly.startPath(0, 0); - poly.lineTo(100, 100); - poly.lineTo(100, 0); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonRectangle() { - // Rectangle - Polygon poly = new Polygon(); - poly.addEnvelope(new Envelope(-200, -100, 100, 200), false); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonRectangleHoleWrongDirection() { - // Rectangle and rectangular hole that has wrong direction - Polygon poly = new Polygon(); - poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); - poly.addEnvelope(new Envelope(-100, -50, 100, 50), false); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(!result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygon_2RectanglesSideBySide() { - // Two rectangles side by side, simple - Polygon poly = new Polygon(); - poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); - poly.addEnvelope(new Envelope(220, -50, 300, 50), false); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testIsSimplePolygonRectangleOneBelow() { - // Two rectangles one below another, simple - Polygon poly = new Polygon(); - poly.addEnvelope(new Envelope(50, 50, 100, 100), false); - poly.addEnvelope(new Envelope(50, 200, 100, 250), false); - boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, - null, null); - assertTrue(result); - poly.reverseAllPaths(); - result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); - assertTrue(!result); - } - - @Test - public void testisSimpleOGC() { - Polyline poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(10, 0); - boolean result = simplifyOpOGC.isSimpleOGC(poly, sr4326, true, null, - null); - assertTrue(result); - - poly = new Polyline(); - poly.startPath(0, 0); - poly.lineTo(10, 10); - poly.lineTo(0, 10); - poly.lineTo(10, 0); - NonSimpleResult nsr = new NonSimpleResult(); - result = simplifyOpOGC.isSimpleOGC(poly, sr4326, true, nsr, null); - assertTrue(!result); - assertTrue(nsr.m_reason == NonSimpleResult.Reason.Cracking); - - MultiPoint mp = new MultiPoint(); - mp.add(0, 0); - mp.add(10, 0); - result = simplifyOpOGC.isSimpleOGC(mp, sr4326, true, null, null); - assertTrue(result); - - mp = new MultiPoint(); - mp.add(10, 0); - mp.add(10, 0); - nsr = new NonSimpleResult(); - result = simplifyOpOGC.isSimpleOGC(mp, sr4326, true, nsr, null); - assertTrue(!result); - assertTrue(nsr.m_reason == NonSimpleResult.Reason.Clustering); - } - - @Test - public void testPolylineIsSimpleForOGC() { - OperatorImportFromJson importerJson = (OperatorImportFromJson) factory - .getOperator(Operator.Type.ImportFromJson); - OperatorSimplify simplify = (OperatorSimplify) factory - .getOperator(Operator.Type.Simplify); - - { - String s = "{\"paths\":[[[0, 10], [8, 5], [5, 2], [6, 0]]]}"; - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(res); - } - { - String s = "{\"paths\":[[[0, 10], [6, 0], [7, 5], [0, 3]]]}";// self - // intersection - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(!res); - } - - { - String s = "{\"paths\":[[[0, 10], [6, 0], [0, 3], [0, 10]]]}"; // closed - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(res); - } - - { - String s = "{\"paths\":[[[0, 10], [5, 5], [6, 0], [0, 3], [5, 5], [0, 9], [0, 10]]]}"; // closed - // with - // self - // tangent - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(!res); - } - - { - String s = "{\"paths\":[[[0, 10], [5, 2]], [[5, 2], [6, 0]]]}";// two - // paths - // connected - // at - // a - // point - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(res); - } - - { - String s = "{\"paths\":[[[0, 0], [3, 3], [5, 0], [0, 0]], [[0, 10], [3, 3], [10, 10], [0, 10]]]}";// two - // closed - // rings - // touch - // at - // one - // point - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(!res); - } - - { - String s = "{\"paths\":[[[0, 0], [10, 10]], [[0, 10], [10, 0]]]}";// two - // lines - // intersect - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(!res); - } - - { - String s = "{\"paths\":[[[0, 0], [5, 5], [0, 10]], [[10, 10], [5, 5], [10, 0]]]}";// two - // paths - // share - // mid - // point. - Geometry g = importerJson.execute(Geometry.Type.Unknown, - JsonParserReader.createFromString(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(!res); - } - - } - - @Test - public void testFillRule() { - //self intersecting star shape - MapGeometry mg = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"rings\":[[[0,0], [5,10], [10, 0], [0, 7], [10, 7], [0, 0]]]}"); - Polygon poly = (Polygon)mg.getGeometry(); - assertTrue(poly.getFillRule() == Polygon.FillRule.enumFillRuleOddEven); - poly.setFillRule(Polygon.FillRule.enumFillRuleWinding); - assertTrue(poly.getFillRule() == Polygon.FillRule.enumFillRuleWinding); - Geometry simpleResult = OperatorSimplify.local().execute(poly, null, true, null); - assertTrue(((Polygon)simpleResult).getFillRule() == Polygon.FillRule.enumFillRuleOddEven); - //solid start without holes: - MapGeometry mg1 = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"rings\":[[[0,0],[2.5925925925925926,5.185185185185185],[0,7],[3.5,7],[5,10],[6.5,7],[10,7],[7.407407407407407,5.185185185185185],[10,0],[5,3.5],[0,0]]]}"); - boolean equals = OperatorEquals.local().execute(mg1.getGeometry(), simpleResult, null, null); - assertTrue(equals); - } - -} +package com.esri.core.geometry; + +//import java.io.FileOutputStream; +//import java.io.PrintStream; +//import java.util.ArrayList; +//import java.util.List; +//import java.util.Random; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonFactory; + +public class TestSimplify extends TestCase { + OperatorFactoryLocal factory = null; + OperatorSimplify simplifyOp = null; + OperatorSimplifyOGC simplifyOpOGC = null; + SpatialReference sr102100 = null; + SpatialReference sr4326 = null; + SpatialReference sr3857 = null; + + @Override + protected void setUp() throws Exception { + super.setUp(); + factory = OperatorFactoryLocal.getInstance(); + simplifyOp = (OperatorSimplify) factory + .getOperator(Operator.Type.Simplify); + simplifyOpOGC = (OperatorSimplifyOGC) factory + .getOperator(Operator.Type.SimplifyOGC); + sr102100 = SpatialReference.create(102100); + sr3857 = SpatialReference.create(3857);// PE_PCS_WGS_1984_WEB_MERCATOR_AUXSPHERE); + sr4326 = SpatialReference.create(4326);// enum_value2(SpatialReference, + // Code, GCS_WGS_1984)); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public Polygon makeNonSimplePolygon2() { + //MapGeometry mg = OperatorFactoryLocal.loadGeometryFromJSONFileDbg("c:/temp/simplify_polygon_gnomonic.txt"); + //Geometry res = OperatorSimplify.local().execute(mg.getGeometry(), mg.getSpatialReference(), true, null); + + + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 15); + poly.lineTo(15, 15); + poly.lineTo(15, 0); + + // This is an interior ring but it is clockwise + poly.startPath(5, 5); + poly.lineTo(5, 6); + poly.lineTo(6, 6); + poly.lineTo(6, 5); + + return poly; + }// done + + /* + * ------------>---------------->--------------- | | | (1) | | | | --->--- + * ------->------- | | | | | (5) | | | | | | --<-- | | | | (2) | | | | | | | + * | | | | (4) | | | | | | | -->-- | | --<-- | ---<--- | | | | | | + * -------<------- | | (3) | -------------<---------------<--------------- + * -->-- + */ + + // Bowtie case with vertices at intersection + + public Polygon makeNonSimplePolygon5() { + Polygon poly = new Polygon(); + poly.startPath(10, 0); + poly.lineTo(0, 0); + poly.lineTo(5, 5); + poly.lineTo(10, 10); + poly.lineTo(0, 10); + poly.lineTo(5, 5); + + return poly; + }// done + + @Test + public void test0() { + Polygon poly1 = new Polygon(); + poly1.addEnvelope(new Envelope(10, 10, 40, 20), false); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + boolean res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, + null); + assertTrue(res); + // assertTrue(poly1.equals(poly2)); + }// done + + @Test + public void test0Poly() {// simple + Polygon poly1 = new Polygon(); + poly1.addEnvelope(new Envelope(10, 10, 40, 20), false); + poly1.addEnvelope(new Envelope(50, 10, 100, 20), false); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + boolean res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, + null); + assertTrue(res); + // assertTrue(poly1.equals(poly2)); + }// done + + @Test + public void test0Polygon_Spike1() {// non-simple (spike) + Polygon poly1 = new Polygon(); + poly1.startPath(10, 10); + poly1.lineTo(10, 20); + poly1.lineTo(40, 20); + poly1.lineTo(40, 10); + poly1.lineTo(60, 10); + poly1.lineTo(70, 10); + + boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, + null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(poly2.getPointCount() == 4); + }// done + + @Test + public void test0Polygon_Spike2() {// non-simple (spikes) + Polygon poly1 = new Polygon(); + // rectangle with a spike + poly1.startPath(10, 10); + poly1.lineTo(10, 20); + poly1.lineTo(40, 20); + poly1.lineTo(40, 10); + poly1.lineTo(60, 10); + poly1.lineTo(70, 10); + + // degenerate + poly1.startPath(100, 100); + poly1.lineTo(100, 120); + poly1.lineTo(100, 130); + + boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, + null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(poly2.getPointCount() == 4); + }// done + + @Test + public void test0Polygon_Spike3() {// non-simple (spikes) + Polygon poly1 = new Polygon(); + // degenerate + poly1.startPath(100, 100); + poly1.lineTo(100, 120); + poly1.lineTo(100, 130); + + boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, + null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(poly2.isEmpty()); + }// done + + @Test + public void test0PolygonSelfIntersect1() {// non-simple (self-intersection) + Polygon poly1 = new Polygon(); + // touch uncracked + poly1.startPath(0, 0); + poly1.lineTo(0, 100); + poly1.lineTo(100, 100); + poly1.lineTo(0, 50); + poly1.lineTo(100, 0); + + boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, + null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void test0PolygonSelfIntersect2() {// non-simple (self-intersection) + Polygon poly1 = new Polygon(); + poly1.startPath(0, 0); + poly1.lineTo(0, 100); + poly1.lineTo(100, 100); + poly1.lineTo(-100, 0); + // poly1.lineTo(100, 0); + + boolean res = simplifyOp.isSimpleAsFeature(poly1, null, true, null, + null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly1, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void test0PolygonSelfIntersect3() { + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 15); + poly.lineTo(15, 15); + poly.lineTo(15, 0); + + // This part intersects with the first part + poly.startPath(10, 10); + poly.lineTo(10, 20); + poly.lineTo(20, 20); + poly.lineTo(20, 10); + + boolean res = simplifyOp + .isSimpleAsFeature(poly, null, true, null, null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void test0PolygonInteriorRing1() { + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 15); + poly.lineTo(15, 15); + poly.lineTo(15, 0); + + // This is an interior ring but it is clockwise + poly.startPath(5, 5); + poly.lineTo(5, 6); + poly.lineTo(6, 6); + poly.lineTo(6, 5); + + boolean res = simplifyOp + .isSimpleAsFeature(poly, null, true, null, null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void test0PolygonInteriorRing2() { + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 15); + poly.lineTo(15, 15); + poly.lineTo(15, 0); + + // This is an interior ring but it is clockwise + poly.startPath(5, 5); + poly.lineTo(5, 6); + poly.lineTo(6, 6); + poly.lineTo(6, 5); + + // This part intersects with the first part + poly.startPath(10, 10); + poly.lineTo(10, 20); + poly.lineTo(20, 20); + poly.lineTo(20, 10); + + boolean res = simplifyOp + .isSimpleAsFeature(poly, null, true, null, null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void test0PolygonInteriorRingWithCommonBoundary1() { + // Two rings have common boundary + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 10); + poly.lineTo(10, 10); + poly.lineTo(10, 0); + + poly.startPath(10, 0); + poly.lineTo(10, 10); + poly.lineTo(20, 10); + poly.lineTo(20, 0); + + boolean res = simplifyOp + .isSimpleAsFeature(poly, null, true, null, null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void test0PolygonInteriorRingWithCommonBoundary2() { + // Two rings have common boundary + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 10); + poly.lineTo(10, 10); + poly.lineTo(10, 0); + + poly.startPath(10, 5); + poly.lineTo(10, 6); + poly.lineTo(20, 6); + poly.lineTo(20, 5); + + boolean res = simplifyOp + .isSimpleAsFeature(poly, null, true, null, null); + assertTrue(!res); + Polygon poly2 = (Polygon) simplifyOp.execute(poly, null, false, null); + res = simplifyOp.isSimpleAsFeature(poly2, null, true, null, null); + assertTrue(res); + assertTrue(!poly2.isEmpty()); + }// done + + @Test + public void testPolygon() { + Polygon nonSimplePolygon = makeNonSimplePolygon(); + Polygon simplePolygon = (Polygon) simplifyOp.execute(nonSimplePolygon, + sr3857, false, null); + + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon, sr3857, true, + null, null); + assertTrue(res); + + @SuppressWarnings("unused") + int partCount = simplePolygon.getPathCount(); + // assertTrue(partCount == 2); + + double area = simplePolygon.calculateRingArea2D(0); + assertTrue(Math.abs(area - 300) <= 0.0001); + + area = simplePolygon.calculateRingArea2D(1); + assertTrue(Math.abs(area - (-25.0)) <= 0.0001); + }// done + + @Test + public void testPolygon2() { + Polygon nonSimplePolygon2 = makeNonSimplePolygon2(); + double area = nonSimplePolygon2.calculateRingArea2D(1); + assertTrue(Math.abs(area - 1.0) <= 0.0001); + + Polygon simplePolygon2 = (Polygon) simplifyOp.execute( + nonSimplePolygon2, sr3857, false, null); + + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon2, sr3857, + true, null, null); + assertTrue(res); + + area = simplePolygon2.calculateRingArea2D(0); + assertTrue(Math.abs(area - 225) <= 0.0001); + + area = simplePolygon2.calculateRingArea2D(1); + assertTrue(Math.abs(area - (-1.0)) <= 0.0001); + }// done + + @Test + public void testPolygon3() { + Polygon nonSimplePolygon3 = makeNonSimplePolygon3(); + Polygon simplePolygon3 = (Polygon) simplifyOp.execute( + nonSimplePolygon3, sr3857, false, null); + + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon3, sr3857, + true, null, null); + assertTrue(res); + + double area = simplePolygon3.calculateRingArea2D(0); + assertTrue(Math.abs(area - 875) <= 0.0001); + + area = simplePolygon3.calculateRingArea2D(1); + assertTrue(Math.abs(area - (-225)) <= 0.0001 + || Math.abs(area - (-50.0)) <= 0.0001); + + area = simplePolygon3.calculateRingArea2D(2); + assertTrue(Math.abs(area - (-225)) <= 0.0001 + || Math.abs(area - (-50.0)) <= 0.0001); + + area = simplePolygon3.calculateRingArea2D(3); + assertTrue(Math.abs(area - 25) <= 0.0001); + + area = simplePolygon3.calculateRingArea2D(4); + assertTrue(Math.abs(area - 25) <= 0.0001); + }// done + + @Test + public void testPolyline() { + Polyline nonSimplePolyline = makeNonSimplePolyline(); + Polyline simplePolyline = (Polyline) simplifyOp.execute( + nonSimplePolyline, sr3857, false, null); + + int segmentCount = simplePolyline.getSegmentCount(); + assertTrue(segmentCount == 4); + }// done + + @Test + public void testPolygon4() { + Polygon nonSimplePolygon4 = makeNonSimplePolygon4(); + Polygon simplePolygon4 = (Polygon) simplifyOp.execute( + nonSimplePolygon4, sr3857, false, null); + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon4, sr3857, + true, null, null); + assertTrue(res); + + assertTrue(simplePolygon4.getPointCount() == 5); + Point point = nonSimplePolygon4.getPoint(0); + assertTrue(point.getX() == 0.0 && point.getY() == 0.0); + point = nonSimplePolygon4.getPoint(1); + assertTrue(point.getX() == 0.0 && point.getY() == 10.0); + point = nonSimplePolygon4.getPoint(2); + assertTrue(point.getX() == 10.0 && point.getY() == 10.0); + point = nonSimplePolygon4.getPoint(3); + assertTrue(point.getX() == 10.0 && point.getY() == 0.0); + point = nonSimplePolygon4.getPoint(4); + assertTrue(point.getX() == 5.0 && point.getY() == 0.0); + }// done + + @Test + public void testPolygon5() { + Polygon nonSimplePolygon5 = makeNonSimplePolygon5(); + Polygon simplePolygon5 = (Polygon) simplifyOp.execute( + nonSimplePolygon5, sr3857, false, null); + assertTrue(simplePolygon5 != null); + + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon5, sr3857, + true, null, null); + assertTrue(res); + + int pointCount = simplePolygon5.getPointCount(); + assertTrue(pointCount == 6); + + double area = simplePolygon5.calculateArea2D(); + assertTrue(Math.abs(area - 50.0) <= 0.001); + + }// done + + @Test + public void testPolygon6() { + Polygon nonSimplePolygon6 = makeNonSimplePolygon6(); + Polygon simplePolygon6 = (Polygon) simplifyOp.execute( + nonSimplePolygon6, sr3857, false, null); + + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon6, sr3857, + true, null, null); + assertTrue(res); + } + + @Test + public void testPolygon7() { + Polygon nonSimplePolygon7 = makeNonSimplePolygon7(); + Polygon simplePolygon7 = (Polygon) simplifyOp.execute( + nonSimplePolygon7, sr3857, false, null); + + boolean res = simplifyOp.isSimpleAsFeature(simplePolygon7, sr3857, + true, null, null); + assertTrue(res); + } + + public Polygon makeNonSimplePolygon() { + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 15); + poly.lineTo(15, 15); + poly.lineTo(15, 0); + + // This is an interior ring but it is clockwise + poly.startPath(5, 5); + poly.lineTo(5, 6); + poly.lineTo(6, 6); + poly.lineTo(6, 5); + + // This part intersects with the first part + poly.startPath(10, 10); + poly.lineTo(10, 20); + poly.lineTo(20, 20); + poly.lineTo(20, 10); + + return poly; + }// done + + /* + * ------------>---------------->--------------- | | | (1) | | | | --->--- + * ------->------- | | | | | (5) | | | | | | --<-- | | | | (2) | | | | | | | + * | | | | (4) | | | | | | | -->-- | | --<-- | ---<--- | | | | | | + * -------<------- | | (3) | -------------<---------------<--------------- + * -->-- + */ + + public Polygon makeNonSimplePolygon3() { + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 25); + poly.lineTo(35, 25); + poly.lineTo(35, 0); + + poly.startPath(5, 5); + poly.lineTo(5, 15); + poly.lineTo(10, 15); + poly.lineTo(10, 5); + + poly.startPath(40, 0); + poly.lineTo(45, 0); + poly.lineTo(45, 5); + poly.lineTo(40, 5); + + poly.startPath(20, 10); + poly.lineTo(25, 10); + poly.lineTo(25, 15); + poly.lineTo(20, 15); + + poly.startPath(15, 5); + poly.lineTo(15, 20); + poly.lineTo(30, 20); + poly.lineTo(30, 5); + + return poly; + }// done + + public Polygon makeNonSimplePolygon4() { + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 10); + poly.lineTo(10, 10); + poly.lineTo(10, 0); + poly.lineTo(5, 0); + poly.lineTo(5, 5); + poly.lineTo(5, 0); + + return poly; + }// done + + public Polygon makeNonSimplePolygon6() { + Polygon poly = new Polygon(); + poly.startPath(35.34407570857744, 54.00551247713412); + poly.lineTo(41.07663499357954, 20.0); + poly.lineTo(40.66372033705177, 26.217432321849017); + + poly.startPath(42.81936574509338, 20.0); + poly.lineTo(43.58226670584747, 20.0); + poly.lineTo(39.29611825817084, 22.64634933678729); + poly.lineTo(44.369873312241346, 25.81893670527215); + poly.lineTo(42.68845660737179, 20.0); + poly.lineTo(38.569549792944244, 56.47456192829393); + poly.lineTo(42.79274114188401, 45.45117792578003); + poly.lineTo(41.09512147544657, 70.0); + + return poly; + } + + public Polygon makeNonSimplePolygon7() { + Polygon poly = new Polygon(); + + poly.startPath(41.987895433319686, 53.75822619011542); + poly.lineTo(41.98789542535497, 53.75822618803151); + poly.lineTo(40.15120412113667, 68.12604154722113); + poly.lineTo(37.72272697311022, 67.92767094118877); + poly.lineTo(37.147347454283086, 49.497473094145505); + poly.lineTo(38.636627026664385, 51.036687142232736); + + poly.startPath(39.00920080789793, 62.063425518369016); + poly.lineTo(38.604912643136885, 70.0); + poly.lineTo(40.71826863485308, 43.60337143116787); + poly.lineTo(35.34407570857744, 54.005512477134126); + poly.lineTo(39.29611825817084, 22.64634933678729); + + return poly; + } + + public Polyline makeNonSimplePolyline() { + // This polyline has a short segment + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(10, 0); + poly.lineTo(10, 10); + poly.lineTo(10, 5); + poly.lineTo(-5, 5); + + return poly; + }// done + + @Test + public void testIsSimpleBasicsPoint() { + boolean result; + // point is always simple + Point pt = new Point(); + result = simplifyOp.isSimpleAsFeature(pt, sr4326, false, null, null); + assertTrue(result); + pt.setXY(0, 0); + result = simplifyOp.isSimpleAsFeature(pt, sr4326, false, null, null); + assertTrue(result); + pt.setXY(100000, 10000); + result = simplifyOp.isSimpleAsFeature(pt, sr4326, false, null, null); + assertTrue(result); + }// done + + @Test + public void testIsSimpleBasicsEnvelope() { + // Envelope is simple, when it's width and height are not degenerate + Envelope env = new Envelope(); + boolean result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, + null); // Empty is simple + assertTrue(result); + env.setCoords(0, 0, 10, 10); + result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, null); + assertTrue(result); + // sliver but still simple + env.setCoords(0, 0, 0 + sr4326.getTolerance() * 2, 10); + result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, null); + assertTrue(result); + // sliver and not simple + env.setCoords(0, 0, 0 + sr4326.getTolerance() * 0.5, 10); + result = simplifyOp.isSimpleAsFeature(env, sr4326, false, null, null); + assertTrue(!result); + }// done + + @Test + public void testIsSimpleBasicsLine() { + Line line = new Line(); + boolean result = simplifyOp.isSimpleAsFeature(line, sr4326, false, + null, null); + assertTrue(!result); + + line.setStart(new Point(0, 0)); + // line.setEndXY(0, 0); + result = simplifyOp.isSimpleAsFeature(line, sr4326, false, null, null); + assertTrue(!result); + line.setEnd(new Point(1, 0)); + result = simplifyOp.isSimpleAsFeature(line, sr4326, false, null, null); + assertTrue(result); + }// done + + @Test + public void testIsSimpleMultiPoint1() { + MultiPoint mp = new MultiPoint(); + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(result);// empty is simple + result = simplifyOp.isSimpleAsFeature( + simplifyOp.execute(mp, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + }// done + + @Test + public void testIsSimpleMultiPoint2FarApart() { + // Two point test: far apart + MultiPoint mp = new MultiPoint(); + mp.add(20, 10); + mp.add(100, 100); + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(result); + result = simplifyOp.isSimpleAsFeature( + simplifyOp.execute(mp, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + assertTrue(mp.getPointCount() == 2); + }// done + + @Test + public void testIsSimpleMultiPointCoincident() { + // Two point test: coincident + MultiPoint mp = new MultiPoint(); + mp.add(100, 100); + mp.add(100, 100); + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(!result); + MultiPoint mpS; + result = simplifyOp.isSimpleAsFeature( + mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), + sr4326, false, null, null); + assertTrue(result); + assertTrue(mpS.getPointCount() == 1); + }// done + + @Test + public void testMultiPointSR4326_CR184439() { + OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); + OperatorSimplify simpOp = (OperatorSimplify) engine + .getOperator(Operator.Type.Simplify); + NonSimpleResult nonSimpResult = new NonSimpleResult(); + nonSimpResult.m_reason = NonSimpleResult.Reason.NotDetermined; + MultiPoint multiPoint = new MultiPoint(); + multiPoint.add(0, 0); + multiPoint.add(0, 1); + multiPoint.add(0, 0); + Boolean multiPointIsSimple = simpOp.isSimpleAsFeature(multiPoint, + SpatialReference.create(4326), true, nonSimpResult, null); + assertFalse(multiPointIsSimple); + assertTrue(nonSimpResult.m_reason == NonSimpleResult.Reason.Clustering); + assertTrue(nonSimpResult.m_vertexIndex1 == 0); + assertTrue(nonSimpResult.m_vertexIndex2 == 2); + } + + @Test + public void testIsSimpleMultiPointCloserThanTolerance() { + // Two point test: closer than tolerance + MultiPoint mp = new MultiPoint(); + MultiPoint mpS; + mp.add(100, 100); + mp.add(100, 100 + sr4326.getTolerance() * .5); + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(result); + result = simplifyOp.isSimpleAsFeature( + mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), + sr4326, false, null, null); + assertTrue(result); + assertTrue(mpS.getPointCount() == 2); + }// done + + @Test + public void testIsSimpleMultiPointFarApart2() { + // 5 point test: far apart + MultiPoint mp = new MultiPoint(); + mp.add(100, 100); + mp.add(100, 101); + mp.add(101, 101); + mp.add(11, 1); + mp.add(11, 14); + MultiPoint mpS; + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(result); + result = simplifyOp.isSimpleAsFeature( + mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), + sr4326, false, null, null); + assertTrue(result); + assertTrue(mpS.getPointCount() == 5); + }// done + + @Test + public void testIsSimpleMultiPoint_coincident2() { + // 5 point test: coincident + MultiPoint mp = new MultiPoint(); + mp.add(100, 100); + mp.add(100, 101); + mp.add(100, 100); + mp.add(11, 1); + mp.add(11, 14); + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(!result); + MultiPoint mpS; + result = simplifyOp.isSimpleAsFeature( + mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), + sr4326, false, null, null); + assertTrue(result); + assertTrue(mpS.getPointCount() == 4); + assertEquals(mpS.getPoint(0).getX(), 100, 1e-7); + assertEquals(mpS.getPoint(0).getY(), 100, 1e-7); + assertEquals(mpS.getPoint(1).getX(), 100, 1e-7); + assertEquals(mpS.getPoint(1).getY(), 101, 1e-7); + assertEquals(mpS.getPoint(2).getX(), 11, 1e-7); + assertEquals(mpS.getPoint(2).getY(), 1, 1e-7); + assertEquals(mpS.getPoint(3).getX(), 11, 1e-7); + assertEquals(mpS.getPoint(3).getY(), 14, 1e-7); + }// done + + @Test + public void testIsSimpleMultiPointCloserThanTolerance2() { + // 5 point test: closer than tolerance + MultiPoint mp = new MultiPoint(); + mp.add(100, 100); + mp.add(100, 101); + mp.add(100, 100 + sr4326.getTolerance() / 2); + mp.add(11, 1); + mp.add(11, 14); + MultiPoint mpS; + boolean result = simplifyOp.isSimpleAsFeature(mp, sr4326, false, null, + null); + assertTrue(result); + result = simplifyOp.isSimpleAsFeature( + mpS = (MultiPoint) simplifyOp.execute(mp, sr4326, false, null), + sr4326, false, null, null); + assertTrue(result); + assertTrue(mpS.getPointCount() == 5); + }// done + + @Test + public void testIsSimplePolyline() { + Polyline poly = new Polyline(); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// empty is simple + } + + @Test + public void testIsSimplePolylineFarApart() { + // Two point test: far apart + Polyline poly = new Polyline(); + poly.startPath(20, 10); + poly.lineTo(100, 100); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + } + + @Test + public void testIsSimplePolylineCoincident() { + // Two point test: coincident + Polyline poly = new Polyline(); + poly.startPath(100, 100); + poly.lineTo(100, 100); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + @SuppressWarnings("unused") + Polyline polyS; + result = simplifyOp.isSimpleAsFeature( + polyS = (Polyline) simplifyOp + .execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + } + + @Test + public void testIsSimplePolylineCloserThanTolerance() { + // Two point test: closer than tolerance + Polyline poly = new Polyline(); + poly.startPath(100, 100); + poly.lineTo(100, 100 + sr4326.getTolerance() / 2); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + @SuppressWarnings("unused") + Polyline polyS; + result = simplifyOp.isSimpleAsFeature( + polyS = (Polyline) simplifyOp + .execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + } + + @Test + public void testIsSimplePolylineFarApartSelfOverlap0() { + // 3 point test: far apart, self overlapping + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(0, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// TO CONFIRM should be false + } + + @Test + public void testIsSimplePolylineSelfIntersect() { + // 4 point test: far apart, self intersecting + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(0, 100); + poly.lineTo(100, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// TO CONFIRM should be false + } + + @Test + public void testIsSimplePolylineDegenerateSegment() { + // 4 point test: degenerate segment + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(100, 100 + sr4326.getTolerance() / 2); + poly.lineTo(100, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + @SuppressWarnings("unused") + Polyline polyS; + result = simplifyOp.isSimpleAsFeature( + polyS = (Polyline) simplifyOp + .execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + { + Polyline other = new Polyline(); + other.startPath(0, 0); + other.lineTo(100, 100); + other.lineTo(100, 0); + other.equals(poly); + } + } + + @Test + public void testIsSimplePolylineFarApartSelfOverlap() { + // 3 point test: far apart, self overlapping + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(0, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// TO CONFIRM should be false + } + + @Test + public void testIsSimplePolylineFarApartIntersect() { + // 4 point 2 parts test: far apart, intersecting parts + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.startPath(100, 0); + poly.lineTo(0, 100); + + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// TO CONFIRM should be false + } + + @Test + public void testIsSimplePolylineFarApartOverlap2() { + // 4 point 2 parts test: far apart, overlapping parts. second part + // starts where first one ends + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.startPath(100, 100); + poly.lineTo(0, 100); + + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// TO CONFIRM should be false + } + + @Test + public void testIsSimplePolylineDegenerateVertical() { + // 3 point test: degenerate vertical line + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(new Point(100, 100)); + poly.lineTo(new Point(100, 100)); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + Polyline polyS; + result = simplifyOp.isSimpleAsFeature( + polyS = (Polyline) simplifyOp + .execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + assertTrue(polyS.getPointCount() == 2); + } + + @Test + public void testIsSimplePolylineEmptyPath() { + // TODO: any way to test this? + // Empty path + // Polyline poly = new Polyline(); + // assertTrue(poly.isEmpty()); + // poly.addPath(new Polyline(), 0, true); + // assertTrue(poly.isEmpty()); + // boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + // null, null); + // assertTrue(result); + } + + @Test + public void testIsSimplePolylineSinglePointInPath() { + // Single point in path + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.removePoint(0, 1); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + Polyline polyS; + result = simplifyOp.isSimpleAsFeature( + polyS = (Polyline) simplifyOp + .execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + assertTrue(polyS.isEmpty()); + } + + @Test + public void testIsSimplePolygon() { + Polygon poly = new Polygon(); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result);// empty is simple + result = simplifyOp.isSimpleAsFeature( + simplifyOp.execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result);// empty is simple + } + + @Test + public void testIsSimplePolygonEmptyPath() { + // TODO: + // Empty path + // Polygon poly = new Polygon(); + // poly.addPath(new Polyline(), 0, true); + // assertTrue(poly.getPathCount() == 1); + // boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + // null, + // null); + // assertTrue(result); + // result = simplifyOp.isSimpleAsFeature(simplifyOp.execute(poly, + // sr4326, false, null), sr4326, false, null, null); + // assertTrue(result);// empty is simple + // assertTrue(poly.getPathCount() == 1); + } + + @Test + public void testIsSimplePolygonIncomplete1() { + // Incomplete polygon 1 + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + // poly.removePoint(0, 1);//TO CONFIRM no removePoint method in Java + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonIncomplete2() { + // Incomplete polygon 2 + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonDegenerateTriangle() { + // Degenerate triangle (self overlap) + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(0, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonSelfIntersect() { + // Self intersection - cracking is needed + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(0, 100); + poly.lineTo(100, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonRectangleHole() { + // Rectangle and rectangular hole that has one segment overlapping + // with the with the exterior ring. Cracking is needed. + Polygon poly = new Polygon(); + poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); + poly.addEnvelope(new Envelope(-100, -100, 100, 50), true); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonRectangleHole2() { + // Rectangle and rectangular hole + Polygon poly = new Polygon(); + poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); + poly.addEnvelope(new Envelope(-100, -50, 100, 50), true); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonSelfIntersectAtVertex() { + // Self intersection at vertex + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(50, 50); + poly.lineTo(100, 100); + poly.lineTo(0, 100); + poly.lineTo(50, 50); + poly.lineTo(100, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + result = simplifyOp.isSimpleAsFeature( + simplifyOp.execute(poly, sr4326, false, null), sr4326, false, + null, null); + assertTrue(result); + } + + @Test + public void testIsSimplePolygon_2EdgesTouchAtVertex() { + // No self-intersection, but more than two edges touch at the same + // vertex. Simple for ArcGIS, not simple for OGC + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(50, 50); + poly.lineTo(0, 100); + poly.lineTo(100, 100); + poly.lineTo(50, 50); + poly.lineTo(100, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + } + + @Test + public void testIsSimplePolygonTriangle() { + // Triangle + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(100, 100); + poly.lineTo(100, 0); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonRectangle() { + // Rectangle + Polygon poly = new Polygon(); + poly.addEnvelope(new Envelope(-200, -100, 100, 200), false); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonRectangleHoleWrongDirection() { + // Rectangle and rectangular hole that has wrong direction + Polygon poly = new Polygon(); + poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); + poly.addEnvelope(new Envelope(-100, -50, 100, 50), false); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(!result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygon_2RectanglesSideBySide() { + // Two rectangles side by side, simple + Polygon poly = new Polygon(); + poly.addEnvelope(new Envelope(-200, -100, 200, 100), false); + poly.addEnvelope(new Envelope(220, -50, 300, 50), false); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testIsSimplePolygonRectangleOneBelow() { + // Two rectangles one below another, simple + Polygon poly = new Polygon(); + poly.addEnvelope(new Envelope(50, 50, 100, 100), false); + poly.addEnvelope(new Envelope(50, 200, 100, 250), false); + boolean result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, + null, null); + assertTrue(result); + poly.reverseAllPaths(); + result = simplifyOp.isSimpleAsFeature(poly, sr4326, false, null, null); + assertTrue(!result); + } + + @Test + public void testisSimpleOGC() { + Polyline poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(10, 0); + boolean result = simplifyOpOGC.isSimpleOGC(poly, sr4326, true, null, + null); + assertTrue(result); + + poly = new Polyline(); + poly.startPath(0, 0); + poly.lineTo(10, 10); + poly.lineTo(0, 10); + poly.lineTo(10, 0); + NonSimpleResult nsr = new NonSimpleResult(); + result = simplifyOpOGC.isSimpleOGC(poly, sr4326, true, nsr, null); + assertTrue(!result); + assertTrue(nsr.m_reason == NonSimpleResult.Reason.Cracking); + + MultiPoint mp = new MultiPoint(); + mp.add(0, 0); + mp.add(10, 0); + result = simplifyOpOGC.isSimpleOGC(mp, sr4326, true, null, null); + assertTrue(result); + + mp = new MultiPoint(); + mp.add(10, 0); + mp.add(10, 0); + nsr = new NonSimpleResult(); + result = simplifyOpOGC.isSimpleOGC(mp, sr4326, true, nsr, null); + assertTrue(!result); + assertTrue(nsr.m_reason == NonSimpleResult.Reason.Clustering); + } + + @Test + public void testPolylineIsSimpleForOGC() { + OperatorImportFromJson importerJson = (OperatorImportFromJson) factory + .getOperator(Operator.Type.ImportFromJson); + OperatorSimplify simplify = (OperatorSimplify) factory + .getOperator(Operator.Type.Simplify); + + { + String s = "{\"paths\":[[[0, 10], [8, 5], [5, 2], [6, 0]]]}"; + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(res); + } + { + String s = "{\"paths\":[[[0, 10], [6, 0], [7, 5], [0, 3]]]}";// self + // intersection + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(!res); + } + + { + String s = "{\"paths\":[[[0, 10], [6, 0], [0, 3], [0, 10]]]}"; // closed + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(res); + } + + { + String s = "{\"paths\":[[[0, 10], [5, 5], [6, 0], [0, 3], [5, 5], [0, 9], [0, 10]]]}"; // closed + // with + // self + // tangent + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(!res); + } + + { + String s = "{\"paths\":[[[0, 10], [5, 2]], [[5, 2], [6, 0]]]}";// two + // paths + // connected + // at + // a + // point + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(res); + } + + { + String s = "{\"paths\":[[[0, 0], [3, 3], [5, 0], [0, 0]], [[0, 10], [3, 3], [10, 10], [0, 10]]]}";// two + // closed + // rings + // touch + // at + // one + // point + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(!res); + } + + { + String s = "{\"paths\":[[[0, 0], [10, 10]], [[0, 10], [10, 0]]]}";// two + // lines + // intersect + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(!res); + } + + { + String s = "{\"paths\":[[[0, 0], [5, 5], [0, 10]], [[10, 10], [5, 5], [10, 0]]]}";// two + // paths + // share + // mid + // point. + Geometry g = importerJson.execute(Geometry.Type.Unknown, + JsonParserReader.createFromString(s)).getGeometry(); + boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); + assertTrue(!res); + } + + } + + @Test + public void testFillRule() { + //self intersecting star shape + MapGeometry mg = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"rings\":[[[0,0], [5,10], [10, 0], [0, 7], [10, 7], [0, 0]]]}"); + Polygon poly = (Polygon)mg.getGeometry(); + assertTrue(poly.getFillRule() == Polygon.FillRule.enumFillRuleOddEven); + poly.setFillRule(Polygon.FillRule.enumFillRuleWinding); + assertTrue(poly.getFillRule() == Polygon.FillRule.enumFillRuleWinding); + Geometry simpleResult = OperatorSimplify.local().execute(poly, null, true, null); + assertTrue(((Polygon)simpleResult).getFillRule() == Polygon.FillRule.enumFillRuleOddEven); + //solid start without holes: + MapGeometry mg1 = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, "{\"rings\":[[[0,0],[2.5925925925925926,5.185185185185185],[0,7],[3.5,7],[5,10],[6.5,7],[10,7],[7.407407407407407,5.185185185185185],[10,0],[5,3.5],[0,0]]]}"); + boolean equals = OperatorEquals.local().execute(mg1.getGeometry(), simpleResult, null, null); + assertTrue(equals); + } + +} diff --git a/src/test/java/com/esri/core/geometry/TestWKBSupport.java b/src/test/java/com/esri/core/geometry/TestWKBSupport.java index 0c84d883..f0f4752a 100644 --- a/src/test/java/com/esri/core/geometry/TestWKBSupport.java +++ b/src/test/java/com/esri/core/geometry/TestWKBSupport.java @@ -1,85 +1,86 @@ -package com.esri.core.geometry; - -import java.io.IOException; -import java.nio.ByteBuffer; -import junit.framework.TestCase; -import org.junit.Test; - -//import com.vividsolutions.jts.io.WKBReader; - -public class TestWKBSupport extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void testWKB() { - // JSON -> GEOM -> WKB - - String strPolygon1 = "{\"xmin\":-1.1663479012889031E7,\"ymin\":4919777.494405342,\"xmax\":-1.1658587043078788E7,\"ymax\":4924669.464215587,\"spatialReference\":{\"wkid\":102100}}"; - // String strPolygon1 = - // "{\"rings\":[[[-119.152450421001,38.4118009590513],[-119.318825070203,38.5271086243914],[-119.575687062955,38.7029101298904],[-119.889341639399,38.9222515603984],[-119.995254694357,38.9941061536377],[-119.995150114198,39.0634913594691],[-119.994541258334,39.1061318056708],[-119.995527335641,39.1587132866355],[-119.995304181493,39.3115454332125],[-119.996011479298,39.4435009764511],[-119.996165311172,39.7206108077274],[-119.996324660047,41.1775662656441],[-119.993459369715,41.9892049531992],[-119.351692186077,41.9888529749781],[-119.3109421304,41.9891353872811],[-118.185316829038,41.9966370981387],[-117.018864363596,41.9947941808341],[-116.992313337997,41.9947945094663],[-115.947544658193,41.9945994628997],[-115.024862911148,41.996506455953],[-114.269471632824,41.9959242345073],[-114.039072662345,41.9953908974688],[-114.038151248682,40.9976868405942],[-114.038108189376,40.1110466529553],[-114.039844684228,39.9087788600023],[-114.040105338584,39.5386849268845],[-114.044267501155,38.6789958815881],[-114.045090206153,38.5710950539539],[-114.047272999176,38.1376524399918],[-114.047260595159,37.5984784866001],[-114.043939384154,36.9965379371421],[-114.043716435713,36.8418489458647],[-114.037392074194,36.2160228969702],[-114.045105557286,36.1939778840226],[-114.107775185788,36.1210907070504],[-114.12902308363,36.041730493896],[-114.206768869568,36.0172554164834],[-114.233472615347,36.0183310595897],[-114.307587598189,36.0622330993643],[-114.303857056018,36.0871084040611],[-114.316095374696,36.1114380366653],[-114.344233941709,36.1374802520568],[-114.380803116644,36.1509912717765],[-114.443945697733,36.1210532841897],[-114.466613475422,36.1247112590539],[-114.530573568745,36.1550902046725],[-114.598935242024,36.1383354528834],[-114.621610747198,36.1419666834504],[-114.712761724737,36.1051810523675],[-114.728150311069,36.0859627711604],[-114.728966012834,36.0587530361083],[-114.717673567756,36.0367580437018],[-114.736212493583,35.9876483502758],[-114.699275906446,35.9116119537412],[-114.661600122152,35.8804735854242],[-114.662462095522,35.8709599070091],[-114.689867343369,35.8474424944766],[-114.682739704595,35.7647034175617],[-114.688820027649,35.7325957399896],[-114.665091345861,35.6930994107107],[-114.668486064922,35.6563989882404],[-114.654065925137,35.6465840800053],[-114.6398667219,35.6113485698329],[-114.653134321223,35.5848331056108],[-114.649792053474,35.5466373866597],[-114.672215155693,35.5157541647721],[-114.645396168451,35.4507608261463],[-114.589584275424,35.3583787306827],[-114.587889840369,35.30476812919],[-114.559583045727,35.2201828714608],[-114.561039964054,35.1743461616313],[-114.572255261053,35.1400677445931],[-114.582616239058,35.1325604694085],[-114.626440825485,35.1339067529872],[-114.6359090842,35.1186557767895],[-114.595631971944,35.0760579746697],[-114.633779872695,35.0418633504303],[-114.621068606189,34.9989144286133],[-115.626197382816,35.7956983148418],[-115.88576934392,36.0012259572723],[-117.160423771838,36.9595941441767],[-117.838686423167,37.457298239715],[-118.417419755966,37.8866767486211],[-119.152450421001,38.4118009590513]]], \"spatialReference\":{\"wkid\":4326}}"; - - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(strPolygon1); - Geometry geom = mapGeom.getGeometry(); - OperatorExportToWkb operatorExport = (OperatorExportToWkb) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ExportToWkb); - ByteBuffer byteBuffer = operatorExport.execute(0, geom, null); - byte[] wkb = byteBuffer.array(); - - // WKB -> GEOM -> JSON - OperatorImportFromWkb operatorImport = (OperatorImportFromWkb) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ImportFromWkb); - geom = operatorImport.execute(0, Geometry.Type.Polygon, - ByteBuffer.wrap(wkb), null); - // geom = operatorImport.execute(0, Geometry.Type.Polygon, - // byteBuffer); - String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom); - } - - @Test - public void testWKB2() throws Exception { - // JSON -> GEOM -> WKB - - // String strPolygon1 = - // "{\"xmin\":-1.16605115291E7,\"ymin\":4925189.941699997,\"xmax\":-1.16567772126E7,\"ymax\":4928658.771399997,\"spatialReference\":{\"wkid\":102100}}"; - String strPolygon1 = "{\"rings\" : [ [ [-1.16605115291E7,4925189.941699997], [-1.16567772126E7,4925189.941699997], [-1.16567772126E7,4928658.771399997], [-1.16605115291E7,4928658.771399997], [-1.16605115291E7,4925189.941699997] ] ], \"spatialReference\" : {\"wkid\" : 102100}}"; - - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(strPolygon1); - Geometry geom = mapGeom.getGeometry(); - - // simplifying geom - OperatorSimplify operatorSimplify = (OperatorSimplify) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.Simplify); - SpatialReference sr = SpatialReference.create(102100); - geom = operatorSimplify.execute(geom, sr, true, null); - - OperatorExportToWkb operatorExport = (OperatorExportToWkb) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ExportToWkb); - ByteBuffer byteBuffer = operatorExport.execute(0, geom, null); - byte[] wkb = byteBuffer.array(); - - // // checking WKB correctness - // WKBReader jtsReader = new WKBReader(); - // com.vividsolutions.jts.geom.Geometry jtsGeom = jtsReader.read(wkb); - // System.out.println("jtsGeom = " + jtsGeom); - - // WKB -> GEOM -> JSON - OperatorImportFromWkb operatorImport = (OperatorImportFromWkb) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ImportFromWkb); - geom = operatorImport.execute(0, Geometry.Type.Polygon, - ByteBuffer.wrap(wkb), null); - assertTrue(!geom.isEmpty()); - // geom = operatorImport.execute(0, Geometry.Type.Polygon, byteBuffer); - // String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom); - // System.out.println(strPolygon1); - // System.out.println(outputPolygon1); - - } - } +package com.esri.core.geometry; + +import java.io.IOException; +import java.nio.ByteBuffer; +import junit.framework.TestCase; +import org.junit.Test; + +//import com.vividsolutions.jts.io.WKBReader; + +public class TestWKBSupport extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testWKB() { + // JSON -> GEOM -> WKB + + String strPolygon1 = "{\"xmin\":-1.1663479012889031E7,\"ymin\":4919777.494405342,\"xmax\":-1.1658587043078788E7,\"ymax\":4924669.464215587,\"spatialReference\":{\"wkid\":102100}}"; + // String strPolygon1 = + // "{\"rings\":[[[-119.152450421001,38.4118009590513],[-119.318825070203,38.5271086243914],[-119.575687062955,38.7029101298904],[-119.889341639399,38.9222515603984],[-119.995254694357,38.9941061536377],[-119.995150114198,39.0634913594691],[-119.994541258334,39.1061318056708],[-119.995527335641,39.1587132866355],[-119.995304181493,39.3115454332125],[-119.996011479298,39.4435009764511],[-119.996165311172,39.7206108077274],[-119.996324660047,41.1775662656441],[-119.993459369715,41.9892049531992],[-119.351692186077,41.9888529749781],[-119.3109421304,41.9891353872811],[-118.185316829038,41.9966370981387],[-117.018864363596,41.9947941808341],[-116.992313337997,41.9947945094663],[-115.947544658193,41.9945994628997],[-115.024862911148,41.996506455953],[-114.269471632824,41.9959242345073],[-114.039072662345,41.9953908974688],[-114.038151248682,40.9976868405942],[-114.038108189376,40.1110466529553],[-114.039844684228,39.9087788600023],[-114.040105338584,39.5386849268845],[-114.044267501155,38.6789958815881],[-114.045090206153,38.5710950539539],[-114.047272999176,38.1376524399918],[-114.047260595159,37.5984784866001],[-114.043939384154,36.9965379371421],[-114.043716435713,36.8418489458647],[-114.037392074194,36.2160228969702],[-114.045105557286,36.1939778840226],[-114.107775185788,36.1210907070504],[-114.12902308363,36.041730493896],[-114.206768869568,36.0172554164834],[-114.233472615347,36.0183310595897],[-114.307587598189,36.0622330993643],[-114.303857056018,36.0871084040611],[-114.316095374696,36.1114380366653],[-114.344233941709,36.1374802520568],[-114.380803116644,36.1509912717765],[-114.443945697733,36.1210532841897],[-114.466613475422,36.1247112590539],[-114.530573568745,36.1550902046725],[-114.598935242024,36.1383354528834],[-114.621610747198,36.1419666834504],[-114.712761724737,36.1051810523675],[-114.728150311069,36.0859627711604],[-114.728966012834,36.0587530361083],[-114.717673567756,36.0367580437018],[-114.736212493583,35.9876483502758],[-114.699275906446,35.9116119537412],[-114.661600122152,35.8804735854242],[-114.662462095522,35.8709599070091],[-114.689867343369,35.8474424944766],[-114.682739704595,35.7647034175617],[-114.688820027649,35.7325957399896],[-114.665091345861,35.6930994107107],[-114.668486064922,35.6563989882404],[-114.654065925137,35.6465840800053],[-114.6398667219,35.6113485698329],[-114.653134321223,35.5848331056108],[-114.649792053474,35.5466373866597],[-114.672215155693,35.5157541647721],[-114.645396168451,35.4507608261463],[-114.589584275424,35.3583787306827],[-114.587889840369,35.30476812919],[-114.559583045727,35.2201828714608],[-114.561039964054,35.1743461616313],[-114.572255261053,35.1400677445931],[-114.582616239058,35.1325604694085],[-114.626440825485,35.1339067529872],[-114.6359090842,35.1186557767895],[-114.595631971944,35.0760579746697],[-114.633779872695,35.0418633504303],[-114.621068606189,34.9989144286133],[-115.626197382816,35.7956983148418],[-115.88576934392,36.0012259572723],[-117.160423771838,36.9595941441767],[-117.838686423167,37.457298239715],[-118.417419755966,37.8866767486211],[-119.152450421001,38.4118009590513]]], \"spatialReference\":{\"wkid\":4326}}"; + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(strPolygon1); + Geometry geom = mapGeom.getGeometry(); + OperatorExportToWkb operatorExport = (OperatorExportToWkb) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.ExportToWkb); + ByteBuffer byteBuffer = operatorExport.execute(0, geom, null); + byte[] wkb = byteBuffer.array(); + + // WKB -> GEOM -> JSON + OperatorImportFromWkb operatorImport = (OperatorImportFromWkb) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.ImportFromWkb); + geom = operatorImport.execute(0, Geometry.Type.Polygon, + ByteBuffer.wrap(wkb), null); + // geom = operatorImport.execute(0, Geometry.Type.Polygon, + // byteBuffer); + String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom); + } + + @Test + public void testWKB2() throws Exception { + // JSON -> GEOM -> WKB + + // String strPolygon1 = + // "{\"xmin\":-1.16605115291E7,\"ymin\":4925189.941699997,\"xmax\":-1.16567772126E7,\"ymax\":4928658.771399997,\"spatialReference\":{\"wkid\":102100}}"; + String strPolygon1 = "{\"rings\" : [ [ [-1.16605115291E7,4925189.941699997], [-1.16567772126E7,4925189.941699997], [-1.16567772126E7,4928658.771399997], [-1.16605115291E7,4928658.771399997], [-1.16605115291E7,4925189.941699997] ] ], \"spatialReference\" : {\"wkid\" : 102100}}"; + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(strPolygon1); + Geometry geom = mapGeom.getGeometry(); + + // simplifying geom + OperatorSimplify operatorSimplify = (OperatorSimplify) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.Simplify); + SpatialReference sr = SpatialReference.create(102100); + geom = operatorSimplify.execute(geom, sr, true, null); + + OperatorExportToWkb operatorExport = (OperatorExportToWkb) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.ExportToWkb); + ByteBuffer byteBuffer = operatorExport.execute(0, geom, null); + byte[] wkb = byteBuffer.array(); + + // // checking WKB correctness + // WKBReader jtsReader = new WKBReader(); + // com.vividsolutions.jts.geom.Geometry jtsGeom = jtsReader.read(wkb); + // System.out.println("jtsGeom = " + jtsGeom); + + // WKB -> GEOM -> JSON + OperatorImportFromWkb operatorImport = (OperatorImportFromWkb) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.ImportFromWkb); + geom = operatorImport.execute(0, Geometry.Type.Polygon, + ByteBuffer.wrap(wkb), null); + assertTrue(!geom.isEmpty()); + // geom = operatorImport.execute(0, Geometry.Type.Polygon, byteBuffer); + // String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom); + // System.out.println(strPolygon1); + // System.out.println(outputPolygon1); + + } + +} From b0bc20e9f3a8e6ea880dbfefebeb54d2552b97fe Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Thu, 13 Jul 2017 15:01:14 -0700 Subject: [PATCH 03/75] added missing license header (#138) --- .gitignore | 1 + .../core/geometry/AttributeStreamOfDbl.java | 12 +- .../core/geometry/AttributeStreamOfFloat.java | 12 +- .../core/geometry/AttributeStreamOfInt16.java | 12 +- .../core/geometry/AttributeStreamOfInt32.java | 14 +- .../core/geometry/AttributeStreamOfInt64.java | 12 +- .../core/geometry/AttributeStreamOfInt8.java | 12 +- .../ogc/OGCConcreteGeometryCollection.java | 24 + .../com/esri/core/geometry/ogc/OGCCurve.java | 24 + .../esri/core/geometry/ogc/OGCGeometry.java | 24 + .../geometry/ogc/OGCGeometryCollection.java | 24 + .../esri/core/geometry/ogc/OGCLineString.java | 24 + .../esri/core/geometry/ogc/OGCLinearRing.java | 24 + .../esri/core/geometry/ogc/OGCMultiCurve.java | 24 + .../core/geometry/ogc/OGCMultiLineString.java | 24 + .../esri/core/geometry/ogc/OGCMultiPoint.java | 24 + .../core/geometry/ogc/OGCMultiPolygon.java | 24 + .../core/geometry/ogc/OGCMultiSurface.java | 24 + .../com/esri/core/geometry/ogc/OGCPoint.java | 24 + .../esri/core/geometry/ogc/OGCPolygon.java | 24 + .../esri/core/geometry/ogc/OGCSurface.java | 24 + .../com/esri/core/geometry/GeometryUtils.java | 24 + .../geometry/RandomCoordinateGenerator.java | 24 + .../esri/core/geometry/TestAttributes.java | 24 + .../com/esri/core/geometry/TestBuffer.java | 24 + .../java/com/esri/core/geometry/TestClip.java | 24 + .../esri/core/geometry/TestCommonMethods.java | 24 + .../com/esri/core/geometry/TestContains.java | 24 + .../esri/core/geometry/TestConvexHull.java | 24 + .../java/com/esri/core/geometry/TestCut.java | 24 + .../esri/core/geometry/TestDifference.java | 24 + .../com/esri/core/geometry/TestDistance.java | 24 + .../com/esri/core/geometry/TestEditShape.java | 26 +- .../geometry/TestEnvelope2DIntersector.java | 24 + .../com/esri/core/geometry/TestEquals.java | 24 + .../com/esri/core/geometry/TestFailed.java | 24 + .../esri/core/geometry/TestGeneralize.java | 24 + .../com/esri/core/geometry/TestGeodetic.java | 24 + ...omToJSonExportSRFromWkiOrWkt_CR181369.java | 24 + .../esri/core/geometry/TestImportExport.java | 24 + .../geometry/TestInterpolateAttributes.java | 24 + .../esri/core/geometry/TestIntersect2.java | 24 + .../esri/core/geometry/TestIntersection.java | 24 + .../esri/core/geometry/TestIntervalTree.java | 24 + .../esri/core/geometry/TestJSonGeometry.java | 24 + .../TestJSonToGeomFromWkiOrWkt_CR177613.java | 24 + .../esri/core/geometry/TestJsonParser.java | 1205 ++++++++--------- .../com/esri/core/geometry/TestMathUtils.java | 24 + .../esri/core/geometry/TestMultiPoint.java | 24 + .../java/com/esri/core/geometry/TestOGC.java | 24 + .../com/esri/core/geometry/TestOffset.java | 24 + .../com/esri/core/geometry/TestPoint.java | 24 + .../com/esri/core/geometry/TestPolygon.java | 24 + .../esri/core/geometry/TestPolygonUtils.java | 24 + .../esri/core/geometry/TestProximity2D.java | 24 + .../com/esri/core/geometry/TestQuadTree.java | 24 + .../geometry/TestRasterizedGeometry2D.java | 24 + .../com/esri/core/geometry/TestRelation.java | 24 + .../esri/core/geometry/TestSerialization.java | 24 + .../com/esri/core/geometry/TestSimplify.java | 24 + .../core/geometry/TestSpatialReference.java | 24 + .../com/esri/core/geometry/TestTouch.java | 24 + .../com/esri/core/geometry/TestTreap.java | 24 + .../com/esri/core/geometry/TestUnion.java | 24 + .../esri/core/geometry/TestWKBSupport.java | 24 + .../geometry/TestWkbImportOnPostgresST.java | 24 + .../java/com/esri/core/geometry/TestWkid.java | 24 + .../com/esri/core/geometry/TestWktParser.java | 24 + .../java/com/esri/core/geometry/Utils.java | 24 + 69 files changed, 2072 insertions(+), 674 deletions(-) diff --git a/.gitignore b/.gitignore index f31512c4..7328fe5d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ esri-geometry-api.jar description.jardesc *.bak *.properties +*.zip # Intellij project files *.iml diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java index bbf40fde..88a639b8 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -31,14 +31,14 @@ final class AttributeStreamOfDbl extends AttributeStreamBase { - double[] m_buffer = null; - int m_size; + private double[] m_buffer = null; + private int m_size; public int size() { return m_size; } - public void reserve(int reserve)// only in Java + public void reserve(int reserve) { if (reserve <= 0) return; @@ -54,6 +54,10 @@ public void reserve(int reserve)// only in Java } + public int capacity() { + return m_buffer != null ? m_buffer.length : 0; + } + public AttributeStreamOfDbl(int size) { int sz = size; if (sz < 2) diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java index 1e90b35b..491ae221 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,8 +30,8 @@ final class AttributeStreamOfFloat extends AttributeStreamBase { - float[] m_buffer = null; - int m_size; + private float[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +53,10 @@ public void reserve(int reserve)// only in Java } + public int capacity() { + return m_buffer != null ? m_buffer.length : 0; + } + public AttributeStreamOfFloat(int size) { int sz = size; if (sz < 2) @@ -314,7 +318,7 @@ public void addRange(AttributeStreamBase src, int start, int count, resize(newSize); if (bForward) { - System.arraycopy(((AttributeStreamOfDbl) src).m_buffer, start, + System.arraycopy(((AttributeStreamOfFloat) src).m_buffer, start, m_buffer, oldSize, count); } else { int n = count; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java index d4af7efe..a7d1e175 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,8 +30,8 @@ final class AttributeStreamOfInt16 extends AttributeStreamBase { - short[] m_buffer = null; - int m_size; + private short[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +53,10 @@ public void reserve(int reserve)// only in Java } + public int capacity() { + return m_buffer != null ? m_buffer.length : 0; + } + public AttributeStreamOfInt16(int size) { int sz = size; if (sz < 2) @@ -299,7 +303,7 @@ public void addRange(AttributeStreamBase src, int start, int count, resize(newSize); if (bForward) { - System.arraycopy(((AttributeStreamOfDbl) src).m_buffer, start, + System.arraycopy(((AttributeStreamOfInt16) src).m_buffer, start, m_buffer, oldSize, count); } else { int n = count; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java index 8aa48e56..6ece2a71 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -31,10 +31,10 @@ final class AttributeStreamOfInt32 extends AttributeStreamBase { - int[] m_buffer = null; - int m_size; + private int[] m_buffer = null; + private int m_size; - public void reserve(int reserve)// only in Java + public void reserve(int reserve) { if (reserve <= 0) return; @@ -54,6 +54,10 @@ public int size() { return m_size; } + public int capacity() { + return m_buffer != null ? m_buffer.length : 0; + } + public AttributeStreamOfInt32(int size) { int sz = size; if (sz < 2) @@ -352,7 +356,7 @@ public void addRange(AttributeStreamBase src, int start, int count, resize(newSize); if (bForward) { - System.arraycopy(((AttributeStreamOfDbl) src).m_buffer, start, + System.arraycopy(((AttributeStreamOfInt32) src).m_buffer, start, m_buffer, oldSize, count); } else { int n = count; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java index 62516ea2..92688ccd 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,8 +30,8 @@ final class AttributeStreamOfInt64 extends AttributeStreamBase { - long[] m_buffer = null; - int m_size; + private long[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +53,10 @@ public void reserve(int reserve)// only in Java } + public int capacity() { + return m_buffer != null ? m_buffer.length : 0; + } + public AttributeStreamOfInt64(int size) { int sz = size; if (sz < 2) @@ -299,7 +303,7 @@ public void addRange(AttributeStreamBase src, int start, int count, resize(newSize); if (bForward) { - System.arraycopy(((AttributeStreamOfDbl) src).m_buffer, start, + System.arraycopy(((AttributeStreamOfInt64) src).m_buffer, start, m_buffer, oldSize, count); } else { int n = count; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java index b0a746e4..a4af8ff5 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,8 +30,8 @@ final class AttributeStreamOfInt8 extends AttributeStreamBase { - byte[] m_buffer = null; - int m_size; + private byte[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +53,10 @@ public void reserve(int reserve)// only in Java } + public int capacity() { + return m_buffer != null ? m_buffer.length : 0; + } + public AttributeStreamOfInt8(int size) { int sz = size; if (sz < 2) @@ -350,7 +354,7 @@ public void addRange(AttributeStreamBase src, int start, int count, resize(newSize); if (bForward) { - System.arraycopy(((AttributeStreamOfDbl) src).m_buffer, start, + System.arraycopy(((AttributeStreamOfInt8) src).m_buffer, start, m_buffer, oldSize, count); } else { int n = count; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 1e4cb7be..3560333c 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.Envelope; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java index 2cad67f7..30f50dd0 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.MultiPoint; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 49197b83..716ee745 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import java.io.IOException; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometryCollection.java index ea0d84af..ef5a3631 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometryCollection.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; public abstract class OGCGeometryCollection extends OGCGeometry { diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java index eb3ee7bb..da51e2d9 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.Geometry; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCLinearRing.java b/src/main/java/com/esri/core/geometry/ogc/OGCLinearRing.java index e733f6a5..a4b67d78 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCLinearRing.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCLinearRing.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.MultiPath; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiCurve.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiCurve.java index 1084d3e2..9aae3bee 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiCurve.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiCurve.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.MultiPath; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java index 2ea784a3..37006a16 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.GeoJsonExportFlags; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java index a57c3b4e..1b0473b8 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import java.nio.ByteBuffer; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java index 878ea168..944e88d5 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.GeoJsonExportFlags; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java index fbb71977..1c98be92 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; public abstract class OGCMultiSurface extends OGCGeometryCollection { diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java index b6a8f9e0..98b2aaf9 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import java.nio.ByteBuffer; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java index 5a038d2a..b27e4e48 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; import com.esri.core.geometry.Geometry; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java b/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java index 99886778..43d192e6 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry.ogc; public abstract class OGCSurface extends OGCGeometry { diff --git a/src/test/java/com/esri/core/geometry/GeometryUtils.java b/src/test/java/com/esri/core/geometry/GeometryUtils.java index 62ddbc37..2734db7c 100644 --- a/src/test/java/com/esri/core/geometry/GeometryUtils.java +++ b/src/test/java/com/esri/core/geometry/GeometryUtils.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.File; diff --git a/src/test/java/com/esri/core/geometry/RandomCoordinateGenerator.java b/src/test/java/com/esri/core/geometry/RandomCoordinateGenerator.java index f50f12d7..dcaa0444 100644 --- a/src/test/java/com/esri/core/geometry/RandomCoordinateGenerator.java +++ b/src/test/java/com/esri/core/geometry/RandomCoordinateGenerator.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.Random; diff --git a/src/test/java/com/esri/core/geometry/TestAttributes.java b/src/test/java/com/esri/core/geometry/TestAttributes.java index bd59cc9b..16c1d9df 100644 --- a/src/test/java/com/esri/core/geometry/TestAttributes.java +++ b/src/test/java/com/esri/core/geometry/TestAttributes.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import static org.junit.Assert.*; diff --git a/src/test/java/com/esri/core/geometry/TestBuffer.java b/src/test/java/com/esri/core/geometry/TestBuffer.java index f381234b..341751f5 100755 --- a/src/test/java/com/esri/core/geometry/TestBuffer.java +++ b/src/test/java/com/esri/core/geometry/TestBuffer.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestClip.java b/src/test/java/com/esri/core/geometry/TestClip.java index 9653e5fa..3dcca075 100644 --- a/src/test/java/com/esri/core/geometry/TestClip.java +++ b/src/test/java/com/esri/core/geometry/TestClip.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestCommonMethods.java b/src/test/java/com/esri/core/geometry/TestCommonMethods.java index b38aeec4..9b937d4b 100644 --- a/src/test/java/com/esri/core/geometry/TestCommonMethods.java +++ b/src/test/java/com/esri/core/geometry/TestCommonMethods.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.File; diff --git a/src/test/java/com/esri/core/geometry/TestContains.java b/src/test/java/com/esri/core/geometry/TestContains.java index 4488b3ef..d6da4af7 100644 --- a/src/test/java/com/esri/core/geometry/TestContains.java +++ b/src/test/java/com/esri/core/geometry/TestContains.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestConvexHull.java b/src/test/java/com/esri/core/geometry/TestConvexHull.java index 62c59c2f..b2e2d59e 100644 --- a/src/test/java/com/esri/core/geometry/TestConvexHull.java +++ b/src/test/java/com/esri/core/geometry/TestConvexHull.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestCut.java b/src/test/java/com/esri/core/geometry/TestCut.java index 8bb8f25c..456973cd 100644 --- a/src/test/java/com/esri/core/geometry/TestCut.java +++ b/src/test/java/com/esri/core/geometry/TestCut.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestDifference.java b/src/test/java/com/esri/core/geometry/TestDifference.java index 455877e6..c6f22321 100644 --- a/src/test/java/com/esri/core/geometry/TestDifference.java +++ b/src/test/java/com/esri/core/geometry/TestDifference.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.ArrayList; diff --git a/src/test/java/com/esri/core/geometry/TestDistance.java b/src/test/java/com/esri/core/geometry/TestDistance.java index efcdaeeb..50399967 100644 --- a/src/test/java/com/esri/core/geometry/TestDistance.java +++ b/src/test/java/com/esri/core/geometry/TestDistance.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestEditShape.java b/src/test/java/com/esri/core/geometry/TestEditShape.java index 173a4970..95b5ea30 100644 --- a/src/test/java/com/esri/core/geometry/TestEditShape.java +++ b/src/test/java/com/esri/core/geometry/TestEditShape.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; @@ -17,8 +41,6 @@ protected void tearDown() throws Exception { @Test public static void testEditShape() { { - // std::shared_ptr poly_base_6 - // = std::make_shared(); // Single part polygon Polygon poly = new Polygon(); poly.startPath(10, 10); diff --git a/src/test/java/com/esri/core/geometry/TestEnvelope2DIntersector.java b/src/test/java/com/esri/core/geometry/TestEnvelope2DIntersector.java index b7bc7d2e..2f33fadb 100644 --- a/src/test/java/com/esri/core/geometry/TestEnvelope2DIntersector.java +++ b/src/test/java/com/esri/core/geometry/TestEnvelope2DIntersector.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.ArrayList; diff --git a/src/test/java/com/esri/core/geometry/TestEquals.java b/src/test/java/com/esri/core/geometry/TestEquals.java index a42abf30..90ed71a0 100644 --- a/src/test/java/com/esri/core/geometry/TestEquals.java +++ b/src/test/java/com/esri/core/geometry/TestEquals.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestFailed.java b/src/test/java/com/esri/core/geometry/TestFailed.java index 5c5b6c41..05bede19 100644 --- a/src/test/java/com/esri/core/geometry/TestFailed.java +++ b/src/test/java/com/esri/core/geometry/TestFailed.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestGeneralize.java b/src/test/java/com/esri/core/geometry/TestGeneralize.java index 5348d20d..34d497e4 100644 --- a/src/test/java/com/esri/core/geometry/TestGeneralize.java +++ b/src/test/java/com/esri/core/geometry/TestGeneralize.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestGeodetic.java b/src/test/java/com/esri/core/geometry/TestGeodetic.java index 35c805ea..93185af9 100644 --- a/src/test/java/com/esri/core/geometry/TestGeodetic.java +++ b/src/test/java/com/esri/core/geometry/TestGeodetic.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java b/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java index 498dab4b..1a0bf432 100644 --- a/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java +++ b/src/test/java/com/esri/core/geometry/TestGeomToJSonExportSRFromWkiOrWkt_CR181369.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.IOException; diff --git a/src/test/java/com/esri/core/geometry/TestImportExport.java b/src/test/java/com/esri/core/geometry/TestImportExport.java index 5fd97f10..0b9e2bc8 100644 --- a/src/test/java/com/esri/core/geometry/TestImportExport.java +++ b/src/test/java/com/esri/core/geometry/TestImportExport.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.nio.ByteBuffer; diff --git a/src/test/java/com/esri/core/geometry/TestInterpolateAttributes.java b/src/test/java/com/esri/core/geometry/TestInterpolateAttributes.java index de462a02..f20f3063 100644 --- a/src/test/java/com/esri/core/geometry/TestInterpolateAttributes.java +++ b/src/test/java/com/esri/core/geometry/TestInterpolateAttributes.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestIntersect2.java b/src/test/java/com/esri/core/geometry/TestIntersect2.java index 8bdcd3c8..36860635 100644 --- a/src/test/java/com/esri/core/geometry/TestIntersect2.java +++ b/src/test/java/com/esri/core/geometry/TestIntersect2.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import com.esri.core.geometry.Geometry.Type; diff --git a/src/test/java/com/esri/core/geometry/TestIntersection.java b/src/test/java/com/esri/core/geometry/TestIntersection.java index 8e3f7fcc..eb6a2a73 100644 --- a/src/test/java/com/esri/core/geometry/TestIntersection.java +++ b/src/test/java/com/esri/core/geometry/TestIntersection.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestIntervalTree.java b/src/test/java/com/esri/core/geometry/TestIntervalTree.java index 0b12d678..4c0cde97 100644 --- a/src/test/java/com/esri/core/geometry/TestIntervalTree.java +++ b/src/test/java/com/esri/core/geometry/TestIntervalTree.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.ArrayList; diff --git a/src/test/java/com/esri/core/geometry/TestJSonGeometry.java b/src/test/java/com/esri/core/geometry/TestJSonGeometry.java index a996575f..62342524 100644 --- a/src/test/java/com/esri/core/geometry/TestJSonGeometry.java +++ b/src/test/java/com/esri/core/geometry/TestJSonGeometry.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.HashMap; diff --git a/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java b/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java index 8b036785..a6ac4d96 100644 --- a/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java +++ b/src/test/java/com/esri/core/geometry/TestJSonToGeomFromWkiOrWkt_CR177613.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.IOException; diff --git a/src/test/java/com/esri/core/geometry/TestJsonParser.java b/src/test/java/com/esri/core/geometry/TestJsonParser.java index 9f2d887f..96f6343c 100644 --- a/src/test/java/com/esri/core/geometry/TestJsonParser.java +++ b/src/test/java/com/esri/core/geometry/TestJsonParser.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.Hashtable; @@ -14,651 +38,538 @@ public class TestJsonParser extends TestCase { - JsonFactory factory = new JsonFactory(); - SpatialReference spatialReferenceWebMerc1 = SpatialReference.create(102100); - SpatialReference spatialReferenceWebMerc2 = SpatialReference - .create(spatialReferenceWebMerc1.getLatestID()); - SpatialReference spatialReferenceWGS84 = SpatialReference.create(4326); - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @Test - public void test3DPoint() throws JsonParseException, IOException { - String jsonString3DPt = "{\"x\" : -118.15, \"y\" : 33.80, \"z\" : 10.0, \"spatialReference\" : {\"wkid\" : 4326}}"; - - JsonParser jsonParser3DPt = factory.createParser(jsonString3DPt); - MapGeometry point3DMP = GeometryEngine.jsonToGeometry(jsonParser3DPt); - assertTrue(-118.15 == ((Point) point3DMP.getGeometry()).getX()); - assertTrue(33.80 == ((Point) point3DMP.getGeometry()).getY()); - assertTrue(spatialReferenceWGS84.getID() == point3DMP - .getSpatialReference().getID()); - } - - @Test - public void test3DPoint1() throws JsonParseException, IOException { - Point point1 = new Point(10.0, 20.0); - Point pointEmpty = new Point(); - { - JsonParser pointWebMerc1Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWebMerc1, point1)); - MapGeometry pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(point1.getX() == ((Point) pointWebMerc1MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWebMerc1MP.getGeometry()) - .getY()); - int srIdOri = spatialReferenceWebMerc1.getID(); - int srIdAfter = pointWebMerc1MP.getSpatialReference().getID(); - assertTrue(srIdOri == srIdAfter || srIdAfter == 3857); - - pointWebMerc1Parser = factory.createJsonParser(GeometryEngine - .geometryToJson(null, point1)); - pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(null == pointWebMerc1MP.getSpatialReference()); - - String pointEmptyString = GeometryEngine.geometryToJson( - spatialReferenceWebMerc1, pointEmpty); - pointWebMerc1Parser = factory.createJsonParser(pointEmptyString); - - pointWebMerc1MP = GeometryEngine - .jsonToGeometry(pointWebMerc1Parser); - assertTrue(pointWebMerc1MP.getGeometry().isEmpty()); - int srIdOri2 = spatialReferenceWebMerc1.getID(); - int srIdAfter2 = pointWebMerc1MP.getSpatialReference().getID(); - assertTrue(srIdOri2 == srIdAfter2 || srIdAfter2 == 3857); - } - } - - @Test - public void test3DPoint2() throws JsonParseException, IOException { - { - Point point1 = new Point(10.0, 20.0); - JsonParser pointWebMerc2Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWebMerc2, point1)); - MapGeometry pointWebMerc2MP = GeometryEngine - .jsonToGeometry(pointWebMerc2Parser); - assertTrue(point1.getX() == ((Point) pointWebMerc2MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWebMerc2MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWebMerc2.getLatestID() == pointWebMerc2MP - .getSpatialReference().getLatestID()); - } - } - - @Test - public void test3DPoint3() throws JsonParseException, IOException { - { - Point point1 = new Point(10.0, 20.0); - JsonParser pointWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, point1)); - MapGeometry pointWgs84MP = GeometryEngine - .jsonToGeometry(pointWgs84Parser); - assertTrue(point1.getX() == ((Point) pointWgs84MP.getGeometry()) - .getX()); - assertTrue(point1.getY() == ((Point) pointWgs84MP.getGeometry()) - .getY()); - assertTrue(spatialReferenceWGS84.getID() == pointWgs84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testMultiPoint() throws JsonParseException, IOException { - MultiPoint multiPoint1 = new MultiPoint(); - multiPoint1.add(-97.06138, 32.837); - multiPoint1.add(-97.06133, 32.836); - multiPoint1.add(-97.06124, 32.834); - multiPoint1.add(-97.06127, 32.832); - - { - JsonParser mPointWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, multiPoint1)); - MapGeometry mPointWgs84MP = GeometryEngine - .jsonToGeometry(mPointWgs84Parser); - assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPointCount()); - assertTrue(multiPoint1.getPoint(0).getX() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(multiPoint1.getPoint(0).getY() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(0).getY()); - int lastIndex = multiPoint1.getPointCount() - 1; - assertTrue(multiPoint1.getPoint(lastIndex).getX() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(multiPoint1.getPoint(lastIndex).getY() == ((MultiPoint) mPointWgs84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP - .getSpatialReference().getID()); - - MultiPoint mPointEmpty = new MultiPoint(); - String mPointEmptyString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, mPointEmpty); - mPointWgs84Parser = factory.createJsonParser(mPointEmptyString); - - mPointWgs84MP = GeometryEngine.jsonToGeometry(mPointWgs84Parser); - assertTrue(mPointWgs84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP - .getSpatialReference().getID()); - - } - } - - @Test - public void testPolyline() throws JsonParseException, IOException { - Polyline polyline = new Polyline(); - polyline.startPath(-97.06138, 32.837); - polyline.lineTo(-97.06133, 32.836); - polyline.lineTo(-97.06124, 32.834); - polyline.lineTo(-97.06127, 32.832); - - polyline.startPath(-97.06326, 32.759); - polyline.lineTo(-97.06298, 32.755); - - { - JsonParser polylinePathsWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, polyline)); - MapGeometry mPolylineWGS84MP = GeometryEngine - .jsonToGeometry(polylinePathsWgs84Parser); - - assertTrue(polyline.getPointCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPointCount()); - assertTrue(polyline.getPoint(0).getX() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(polyline.getPoint(0).getY() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(0).getY()); - - assertTrue(polyline.getPathCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPathCount()); - assertTrue(polyline.getSegmentCount() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount()); - assertTrue(polyline.getSegmentCount(0) == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount(0)); - assertTrue(polyline.getSegmentCount(1) == ((Polyline) mPolylineWGS84MP - .getGeometry()).getSegmentCount(1)); - - int lastIndex = polyline.getPointCount() - 1; - assertTrue(polyline.getPoint(lastIndex).getX() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(polyline.getPoint(lastIndex).getY() == ((Polyline) mPolylineWGS84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP - .getSpatialReference().getID()); - - Polyline emptyPolyline = new Polyline(); - String emptyString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, emptyPolyline); - mPolylineWGS84MP = GeometryEngine.jsonToGeometry(factory - .createJsonParser(emptyString)); - assertTrue(mPolylineWGS84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testPolygon() throws JsonParseException, IOException { - Polygon polygon = new Polygon(); - polygon.startPath(-97.06138, 32.837); - polygon.lineTo(-97.06133, 32.836); - polygon.lineTo(-97.06124, 32.834); - polygon.lineTo(-97.06127, 32.832); - - polygon.startPath(-97.06326, 32.759); - polygon.lineTo(-97.06298, 32.755); - - { - JsonParser polygonPathsWgs84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, polygon)); - MapGeometry mPolygonWGS84MP = GeometryEngine - .jsonToGeometry(polygonPathsWgs84Parser); - - assertTrue(polygon.getPointCount() + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPointCount()); - assertTrue(polygon.getPoint(0).getX() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(0).getX()); - assertTrue(polygon.getPoint(0).getY() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(0).getY()); - - assertTrue(polygon.getPathCount() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPathCount()); - assertTrue(polygon.getSegmentCount() + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount()); - assertTrue(polygon.getSegmentCount(0) == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount(0)); - assertTrue(polygon.getSegmentCount(1) + 1 == ((Polygon) mPolygonWGS84MP - .getGeometry()).getSegmentCount(1)); - - int lastIndex = polygon.getPointCount() - 1; - assertTrue(polygon.getPoint(lastIndex).getX() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(lastIndex).getX()); - assertTrue(polygon.getPoint(lastIndex).getY() == ((Polygon) mPolygonWGS84MP - .getGeometry()).getPoint(lastIndex).getY()); - - assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP - .getSpatialReference().getID()); - - Polygon emptyPolygon = new Polygon(); - String emptyPolygonString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, emptyPolygon); - polygonPathsWgs84Parser = factory - .createJsonParser(emptyPolygonString); - mPolygonWGS84MP = GeometryEngine - .jsonToGeometry(polygonPathsWgs84Parser); - - assertTrue(mPolygonWGS84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testEnvelope() throws JsonParseException, IOException { - Envelope envelope = new Envelope(); - envelope.setCoords(-109.55, 25.76, -86.39, 49.94); - - { - JsonParser envelopeWGS84Parser = factory - .createJsonParser(GeometryEngine.geometryToJson( - spatialReferenceWGS84, envelope)); - MapGeometry envelopeWGS84MP = GeometryEngine - .jsonToGeometry(envelopeWGS84Parser); - assertTrue(envelope.isEmpty() == envelopeWGS84MP.getGeometry() - .isEmpty()); - assertTrue(envelope.getXMax() == ((Envelope) envelopeWGS84MP - .getGeometry()).getXMax()); - assertTrue(envelope.getYMax() == ((Envelope) envelopeWGS84MP - .getGeometry()).getYMax()); - assertTrue(envelope.getXMin() == ((Envelope) envelopeWGS84MP - .getGeometry()).getXMin()); - assertTrue(envelope.getYMin() == ((Envelope) envelopeWGS84MP - .getGeometry()).getYMin()); - assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP - .getSpatialReference().getID()); - - Envelope emptyEnvelope = new Envelope(); - String emptyEnvString = GeometryEngine.geometryToJson( - spatialReferenceWGS84, emptyEnvelope); - envelopeWGS84Parser = factory.createJsonParser(emptyEnvString); - envelopeWGS84MP = GeometryEngine - .jsonToGeometry(envelopeWGS84Parser); - - assertTrue(envelopeWGS84MP.getGeometry().isEmpty()); - assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP - .getSpatialReference().getID()); - } - } - - @Test - public void testCR181369() throws JsonParseException, IOException { - // CR181369 - { - String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; - JsonParser jsonParserPointAndWKT = factory - .createJsonParser(jsonStringPointAndWKT); - MapGeometry mapGeom2 = GeometryEngine - .jsonToGeometry(jsonParserPointAndWKT); - String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson( - mapGeom2.getSpatialReference(), mapGeom2.getGeometry()); - JsonParser jsonParserPointAndWKT2 = factory - .createJsonParser(jsonStringPointAndWKT2); - MapGeometry mapGeom3 = GeometryEngine - .jsonToGeometry(jsonParserPointAndWKT2); - assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3 - .getGeometry()).getX()); - assertTrue(((Point) mapGeom2.getGeometry()).getY() == ((Point) mapGeom3 - .getGeometry()).getY()); - assertTrue(mapGeom2.getSpatialReference().getText() - .equals(mapGeom3.getSpatialReference().getText())); - assertTrue(mapGeom2.getSpatialReference().getID() == mapGeom3 - .getSpatialReference().getID()); - } - } - - @Test - public void testSpatialRef() throws JsonParseException, IOException { - // String jsonStringPt = - // "{\"x\":-20037508.342787,\"y\":20037508.342787},\"spatialReference\":{\"wkid\":102100}}"; - String jsonStringPt = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\": 102100}}";// 102100 - @SuppressWarnings("unused") - String jsonStringPt2 = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\":4326}}"; - String jsonStringMpt = "{ \"points\" : [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], \"spatialReference\" : {\"wkid\" : 4326}}";// 4326 - String jsonStringMpt3D = "{\"hasZs\" : true,\"points\" : [ [-97.06138,32.837,35.0], [-97.06133,32.836,35.1], [-97.06124,32.834,35.2], [-97.06127,32.832,35.3] ],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPl = "{\"paths\" : [ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], [ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPl3D = "{\"hasMs\" : true,\"paths\" : [[ [-97.06138,32.837,5], [-97.06133,32.836,6], [-97.06124,32.834,7], [-97.06127,32.832,8] ],[ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPg = "{ \"rings\" :[ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], [ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], \"spatialReference\" : {\"wkt\" : \"\"}}"; - String jsonStringPg3D = "{\"hasZs\" : true,\"hasMs\" : true,\"rings\" : [ [ [-97.06138, 32.837, 35.1, 4], [-97.06133, 32.836, 35.2, 4.1], [-97.06124, 32.834, 35.3, 4.2], [-97.06127, 32.832, 35.2, 44.3], [-97.06138, 32.837, 35.1, 4] ],[ [-97.06326, 32.759, 35.4], [-97.06298, 32.755, 35.5], [-97.06153, 32.749, 35.6], [-97.06326, 32.759, 35.4] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringPg2 = "{ \"spatialReference\" : {\"wkid\" : 4326}, \"rings\" : [[[-118.35,32.81],[-118.42,32.806],[-118.511,32.892],[-118.35,32.81]]]}"; - String jsonStringPg3 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":null}}"; - String jsonString2SpatialReferences = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; - String jsonString2SpatialReferences2 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":10,\"wkid\":10,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; - String jsonStringSR = "{\"wkid\" : 4326}"; - String jsonStringEnv = "{\"xmin\" : -109.55, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94,\"spatialReference\" : {\"wkid\" : 4326}}"; - String jsonStringHongKon = "{\"xmin\" : -122.55, \"ymin\" : 37.65, \"xmax\" : -122.28, \"ymax\" : 37.84,\"spatialReference\" : {\"wkid\" : 4326}}"; - @SuppressWarnings("unused") - String jsonStringWKT = " {\"wkt\" : \"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}"; - String jsonStringInvalidWKID = "{\"x\":10.0,\"y\":20.0},\"spatialReference\":{\"wkid\":35253523}}"; - String jsonStringOregon = "{\"xmin\":7531831.219849482,\"ymin\":585702.9799639136,\"xmax\":7750143.589982405,\"ymax\":733289.6299999952,\"spatialReference\":{\"wkid\":102726}}"; - - JsonParser jsonParserPt = factory.createJsonParser(jsonStringPt); - JsonParser jsonParserMpt = factory.createJsonParser(jsonStringMpt); - JsonParser jsonParserMpt3D = factory.createJsonParser(jsonStringMpt3D); - JsonParser jsonParserPl = factory.createJsonParser(jsonStringPl); - JsonParser jsonParserPl3D = factory.createJsonParser(jsonStringPl3D); - JsonParser jsonParserPg = factory.createJsonParser(jsonStringPg); - JsonParser jsonParserPg3D = factory.createJsonParser(jsonStringPg3D); - JsonParser jsonParserPg2 = factory.createJsonParser(jsonStringPg2); - @SuppressWarnings("unused") - JsonParser jsonParserSR = factory.createJsonParser(jsonStringSR); - JsonParser jsonParserEnv = factory.createJsonParser(jsonStringEnv); - JsonParser jsonParserPg3 = factory.createJsonParser(jsonStringPg3); - @SuppressWarnings("unused") - JsonParser jsonParserCrazy1 = factory - .createJsonParser(jsonString2SpatialReferences); - @SuppressWarnings("unused") - JsonParser jsonParserCrazy2 = factory - .createJsonParser(jsonString2SpatialReferences2); - JsonParser jsonParserInvalidWKID = factory - .createJsonParser(jsonStringInvalidWKID); - @SuppressWarnings("unused") - JsonParser jsonParseHongKon = factory - .createJsonParser(jsonStringHongKon); - JsonParser jsonParseOregon = factory.createJsonParser(jsonStringOregon); - - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPt); - // showProjectedGeometryInfo(mapGeom); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); - - MapGeometry mapGeomOregon = GeometryEngine - .jsonToGeometry(jsonParseOregon); - Assert.assertTrue(mapGeomOregon.getSpatialReference().getID() == 102726); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt3D); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - { - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0) - .getX() == -97.06138); - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0) - .getY() == 32.837); - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3) - .getX() == -97.06127); - Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3) - .getY() == 32.832); - } - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl3D); - { - // [[ [-97.06138,32.837,5], [-97.06133,32.836,6], - // [-97.06124,32.834,7], [-97.06127,32.832,8] ], - // [ [-97.06326,32.759], [-97.06298,32.755] ]]"; - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0) - .getX() == -97.06138); - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0) - .getY() == 32.837); - int lastIndex = ((Polyline) mapGeom.getGeometry()).getPointCount() - 1; - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndex).getX() == -97.06298);// -97.06153, 32.749 - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndex).getY() == 32.755); - int lastIndexFirstLine = ((Polyline) mapGeom.getGeometry()) - .getPathEnd(0) - 1; - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndexFirstLine).getX() == -97.06127);// -97.06153, - // 32.749 - Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint( - lastIndexFirstLine).getY() == 32.832); - } - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); - Assert.assertTrue(mapGeom.getSpatialReference() == null); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3D); - { - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0) - .getX() == -97.06138); - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0) - .getY() == 32.837); - int lastIndex = ((Polygon) mapGeom.getGeometry()).getPointCount() - 1; - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint( - lastIndex).getX() == -97.06153);// -97.06153, 32.749 - Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint( - lastIndex).getY() == 32.749); - } - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg2); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); - // showProjectedGeometryInfo(mapGeom); - - // mapGeom = GeometryEngine.jsonToGeometry(jsonParserCrazy1); - // Assert.assertTrue(mapGeom.getSpatialReference().getText().equals("")); - // showProjectedGeometryInfo(mapGeom); - - mapGeom = GeometryEngine.jsonToGeometry(jsonParserEnv); - Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); - // showProjectedGeometryInfo(mapGeom); - - try { - GeometryEngine.jsonToGeometry(jsonParserInvalidWKID); - } catch (Exception ex) { - Assert.assertTrue("Should not throw for invalid wkid", false); - } - } - - @Test - public void testMP2onCR175871() throws Exception { - Polygon pg = new Polygon(); - pg.startPath(-50, 10); - pg.lineTo(-50, 12); - pg.lineTo(-45, 12); - pg.lineTo(-45, 10); - - Polygon pg1 = new Polygon(); - pg1.startPath(-45, 10); - pg1.lineTo(-40, 10); - pg1.lineTo(-40, 8); - pg.add(pg1, false); - - SpatialReference spatialReference = SpatialReference.create(4326); - - try { - String jSonStr = GeometryEngine - .geometryToJson(spatialReference, pg); - JsonFactory jf = new JsonFactory(); - - JsonParser jp = jf.createJsonParser(jSonStr); - jp.nextToken(); - MapGeometry mg = GeometryEngine.jsonToGeometry(jp); - Geometry gm = mg.getGeometry(); - Assert.assertEquals(Geometry.Type.Polygon, gm.getType()); - Assert.assertTrue(mg.getSpatialReference().getID() == 4326); - - Polygon pgNew = (Polygon) gm; - - Assert.assertEquals(pgNew.getPathCount(), pg.getPathCount()); - Assert.assertEquals(pgNew.getPointCount(), pg.getPointCount()); - Assert.assertEquals(pgNew.getSegmentCount(), pg.getSegmentCount()); - - Assert.assertEquals(pgNew.getPoint(0).getX(), - pg.getPoint(0).getX(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(1).getX(), - pg.getPoint(1).getX(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(2).getX(), - pg.getPoint(2).getX(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(3).getX(), - pg.getPoint(3).getX(), 0.000000001); - - Assert.assertEquals(pgNew.getPoint(0).getY(), - pg.getPoint(0).getY(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(1).getY(), - pg.getPoint(1).getY(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(2).getY(), - pg.getPoint(2).getY(), 0.000000001); - Assert.assertEquals(pgNew.getPoint(3).getY(), - pg.getPoint(3).getY(), 0.000000001); - } catch (Exception ex) { - String err = ex.getMessage(); - System.out.print(err); - throw ex; - } - } - - @Test - public static int fromJsonToWkid(JsonParser parser) - throws JsonParseException, IOException { - int wkid = 0; - if (parser.getCurrentToken() != JsonToken.START_OBJECT) { - return 0; - } - - while (parser.nextToken() != JsonToken.END_OBJECT) { - String fieldName = parser.getCurrentName(); - - if ("wkid".equals(fieldName)) { - parser.nextToken(); - wkid = parser.getIntValue(); - } - } - return wkid; - } - - @SuppressWarnings("unused") - private static void showProjectedGeometryInfo(MapGeometry mapGeom) { - System.out.println("\n"); - MapGeometry geom = mapGeom; - // while ((geom = geomCursor.next()) != null) { - - if (geom.getGeometry() instanceof Point) { - Point pnt = (Point) geom.getGeometry(); - System.out - .println("Point(" + pnt.getX() + " , " + pnt.getY() + ")"); - if (geom.getSpatialReference() == null) { - System.out.println("No spatial reference"); - } else { - System.out.println("wkid: " - + geom.getSpatialReference().getID()); - } - - } else if (geom.getGeometry() instanceof MultiPoint) { - MultiPoint mp = (MultiPoint) geom.getGeometry(); - System.out.println("Multipoint has " + mp.getPointCount() - + " points."); - - System.out.println("wkid: " + geom.getSpatialReference().getID()); - - } else if (geom.getGeometry() instanceof Polygon) { - Polygon mp = (Polygon) geom.getGeometry(); - System.out.println("Polygon has " + mp.getPointCount() - + " points and " + mp.getPathCount() + " parts."); - if (mp.getPathCount() > 1) { - System.out.println("Part start of 2nd segment : " - + mp.getPathStart(1)); - System.out.println("Part end of 2nd segment : " - + mp.getPathEnd(1)); - System.out.println("Part size of 2nd segment : " - + mp.getPathSize(1)); - - int start = mp.getPathStart(1); - int end = mp.getPathEnd(1); - for (int i = start; i < end; i++) { - Point pp = mp.getPoint(i); - System.out.println("Point(" + i + ") = (" + pp.getX() - + ", " + pp.getY() + ")"); - } - } - System.out.println("wkid: " + geom.getSpatialReference().getID()); - - } else if (geom.getGeometry() instanceof Polyline) { - Polyline mp = (Polyline) geom.getGeometry(); - System.out.println("Polyline has " + mp.getPointCount() - + " points and " + mp.getPathCount() + " parts."); - System.out.println("Part start of 2nd segment : " - + mp.getPathStart(1)); - System.out.println("Part end of 2nd segment : " - + mp.getPathEnd(1)); - System.out.println("Part size of 2nd segment : " - + mp.getPathSize(1)); - int start = mp.getPathStart(1); - int end = mp.getPathEnd(1); - for (int i = start; i < end; i++) { - Point pp = mp.getPoint(i); - System.out.println("Point(" + i + ") = (" + pp.getX() + ", " - + pp.getY() + ")"); - } - - System.out.println("wkid: " + geom.getSpatialReference().getID()); - } - } - - @Test - public void testGeometryToJSON() { - Polygon geom = new Polygon(); - geom.startPath(new Point(-113, 34)); - geom.lineTo(new Point(-105, 34)); - geom.lineTo(new Point(-108, 40)); - - String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom);// Test - // WKID - // == -1 - //System.out.println("Geom JSON STRING is" + outputPolygon1); - String correctPolygon1 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]]}"; - - assertEquals(correctPolygon1, outputPolygon1); - - String outputPolygon2 = GeometryEngine.geometryToJson(4326, geom); - //System.out.println("Geom JSON STRING is" + outputPolygon2); - - String correctPolygon2 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":4326}}"; - assertEquals(correctPolygon2, outputPolygon2); - } - - @Test - public void testGeometryToJSONOldID() throws Exception {// CR - Polygon geom = new Polygon(); - geom.startPath(new Point(-113, 34)); - geom.lineTo(new Point(-105, 34)); - geom.lineTo(new Point(-108, 40)); - String outputPolygon = GeometryEngine.geometryToJson( - SpatialReference.create(3857), geom);// Test WKID == -1 - String correctPolygon = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; - assertTrue(outputPolygon.equals(correctPolygon)); - JsonFactory jf = new JsonFactory(); - JsonParser jp = jf.createJsonParser(outputPolygon); - jp.nextToken(); - MapGeometry mg = GeometryEngine.jsonToGeometry(jp); - @SuppressWarnings("unused") - int srId = mg.getSpatialReference().getID(); - @SuppressWarnings("unused") - int srOldId = mg.getSpatialReference().getOldID(); - Assert.assertTrue(mg.getSpatialReference().getID() == 3857); - Assert.assertTrue(mg.getSpatialReference().getLatestID() == 3857); - Assert.assertTrue(mg.getSpatialReference().getOldID() == 102100); - } + JsonFactory factory = new JsonFactory(); + SpatialReference spatialReferenceWebMerc1 = SpatialReference.create(102100); + SpatialReference spatialReferenceWebMerc2 = SpatialReference.create(spatialReferenceWebMerc1.getLatestID()); + SpatialReference spatialReferenceWGS84 = SpatialReference.create(4326); + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void test3DPoint() throws JsonParseException, IOException { + String jsonString3DPt = "{\"x\" : -118.15, \"y\" : 33.80, \"z\" : 10.0, \"spatialReference\" : {\"wkid\" : 4326}}"; + + JsonParser jsonParser3DPt = factory.createParser(jsonString3DPt); + MapGeometry point3DMP = GeometryEngine.jsonToGeometry(jsonParser3DPt); + assertTrue(-118.15 == ((Point) point3DMP.getGeometry()).getX()); + assertTrue(33.80 == ((Point) point3DMP.getGeometry()).getY()); + assertTrue(spatialReferenceWGS84.getID() == point3DMP.getSpatialReference().getID()); + } + + @Test + public void test3DPoint1() throws JsonParseException, IOException { + Point point1 = new Point(10.0, 20.0); + Point pointEmpty = new Point(); + { + JsonParser pointWebMerc1Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWebMerc1, point1)); + MapGeometry pointWebMerc1MP = GeometryEngine.jsonToGeometry(pointWebMerc1Parser); + assertTrue(point1.getX() == ((Point) pointWebMerc1MP.getGeometry()).getX()); + assertTrue(point1.getY() == ((Point) pointWebMerc1MP.getGeometry()).getY()); + int srIdOri = spatialReferenceWebMerc1.getID(); + int srIdAfter = pointWebMerc1MP.getSpatialReference().getID(); + assertTrue(srIdOri == srIdAfter || srIdAfter == 3857); + + pointWebMerc1Parser = factory.createJsonParser(GeometryEngine.geometryToJson(null, point1)); + pointWebMerc1MP = GeometryEngine.jsonToGeometry(pointWebMerc1Parser); + assertTrue(null == pointWebMerc1MP.getSpatialReference()); + + String pointEmptyString = GeometryEngine.geometryToJson(spatialReferenceWebMerc1, pointEmpty); + pointWebMerc1Parser = factory.createJsonParser(pointEmptyString); + + pointWebMerc1MP = GeometryEngine.jsonToGeometry(pointWebMerc1Parser); + assertTrue(pointWebMerc1MP.getGeometry().isEmpty()); + int srIdOri2 = spatialReferenceWebMerc1.getID(); + int srIdAfter2 = pointWebMerc1MP.getSpatialReference().getID(); + assertTrue(srIdOri2 == srIdAfter2 || srIdAfter2 == 3857); + } + } + + @Test + public void test3DPoint2() throws JsonParseException, IOException { + { + Point point1 = new Point(10.0, 20.0); + JsonParser pointWebMerc2Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWebMerc2, point1)); + MapGeometry pointWebMerc2MP = GeometryEngine.jsonToGeometry(pointWebMerc2Parser); + assertTrue(point1.getX() == ((Point) pointWebMerc2MP.getGeometry()).getX()); + assertTrue(point1.getY() == ((Point) pointWebMerc2MP.getGeometry()).getY()); + assertTrue(spatialReferenceWebMerc2.getLatestID() == pointWebMerc2MP.getSpatialReference().getLatestID()); + } + } + + @Test + public void test3DPoint3() throws JsonParseException, IOException { + { + Point point1 = new Point(10.0, 20.0); + JsonParser pointWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWGS84, point1)); + MapGeometry pointWgs84MP = GeometryEngine.jsonToGeometry(pointWgs84Parser); + assertTrue(point1.getX() == ((Point) pointWgs84MP.getGeometry()).getX()); + assertTrue(point1.getY() == ((Point) pointWgs84MP.getGeometry()).getY()); + assertTrue(spatialReferenceWGS84.getID() == pointWgs84MP.getSpatialReference().getID()); + } + } + + @Test + public void testMultiPoint() throws JsonParseException, IOException { + MultiPoint multiPoint1 = new MultiPoint(); + multiPoint1.add(-97.06138, 32.837); + multiPoint1.add(-97.06133, 32.836); + multiPoint1.add(-97.06124, 32.834); + multiPoint1.add(-97.06127, 32.832); + + { + JsonParser mPointWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWGS84, multiPoint1)); + MapGeometry mPointWgs84MP = GeometryEngine.jsonToGeometry(mPointWgs84Parser); + assertTrue(multiPoint1.getPointCount() == ((MultiPoint) mPointWgs84MP.getGeometry()).getPointCount()); + assertTrue(multiPoint1.getPoint(0).getX() == ((MultiPoint) mPointWgs84MP.getGeometry()).getPoint(0).getX()); + assertTrue(multiPoint1.getPoint(0).getY() == ((MultiPoint) mPointWgs84MP.getGeometry()).getPoint(0).getY()); + int lastIndex = multiPoint1.getPointCount() - 1; + assertTrue(multiPoint1.getPoint(lastIndex).getX() == ((MultiPoint) mPointWgs84MP.getGeometry()) + .getPoint(lastIndex).getX()); + assertTrue(multiPoint1.getPoint(lastIndex).getY() == ((MultiPoint) mPointWgs84MP.getGeometry()) + .getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP.getSpatialReference().getID()); + + MultiPoint mPointEmpty = new MultiPoint(); + String mPointEmptyString = GeometryEngine.geometryToJson(spatialReferenceWGS84, mPointEmpty); + mPointWgs84Parser = factory.createJsonParser(mPointEmptyString); + + mPointWgs84MP = GeometryEngine.jsonToGeometry(mPointWgs84Parser); + assertTrue(mPointWgs84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == mPointWgs84MP.getSpatialReference().getID()); + + } + } + + @Test + public void testPolyline() throws JsonParseException, IOException { + Polyline polyline = new Polyline(); + polyline.startPath(-97.06138, 32.837); + polyline.lineTo(-97.06133, 32.836); + polyline.lineTo(-97.06124, 32.834); + polyline.lineTo(-97.06127, 32.832); + + polyline.startPath(-97.06326, 32.759); + polyline.lineTo(-97.06298, 32.755); + + { + JsonParser polylinePathsWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWGS84, polyline)); + MapGeometry mPolylineWGS84MP = GeometryEngine.jsonToGeometry(polylinePathsWgs84Parser); + + assertTrue(polyline.getPointCount() == ((Polyline) mPolylineWGS84MP.getGeometry()).getPointCount()); + assertTrue(polyline.getPoint(0).getX() == ((Polyline) mPolylineWGS84MP.getGeometry()).getPoint(0).getX()); + assertTrue(polyline.getPoint(0).getY() == ((Polyline) mPolylineWGS84MP.getGeometry()).getPoint(0).getY()); + + assertTrue(polyline.getPathCount() == ((Polyline) mPolylineWGS84MP.getGeometry()).getPathCount()); + assertTrue(polyline.getSegmentCount() == ((Polyline) mPolylineWGS84MP.getGeometry()).getSegmentCount()); + assertTrue(polyline.getSegmentCount(0) == ((Polyline) mPolylineWGS84MP.getGeometry()).getSegmentCount(0)); + assertTrue(polyline.getSegmentCount(1) == ((Polyline) mPolylineWGS84MP.getGeometry()).getSegmentCount(1)); + + int lastIndex = polyline.getPointCount() - 1; + assertTrue(polyline.getPoint(lastIndex).getX() == ((Polyline) mPolylineWGS84MP.getGeometry()) + .getPoint(lastIndex).getX()); + assertTrue(polyline.getPoint(lastIndex).getY() == ((Polyline) mPolylineWGS84MP.getGeometry()) + .getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP.getSpatialReference().getID()); + + Polyline emptyPolyline = new Polyline(); + String emptyString = GeometryEngine.geometryToJson(spatialReferenceWGS84, emptyPolyline); + mPolylineWGS84MP = GeometryEngine.jsonToGeometry(factory.createJsonParser(emptyString)); + assertTrue(mPolylineWGS84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == mPolylineWGS84MP.getSpatialReference().getID()); + } + } + + @Test + public void testPolygon() throws JsonParseException, IOException { + Polygon polygon = new Polygon(); + polygon.startPath(-97.06138, 32.837); + polygon.lineTo(-97.06133, 32.836); + polygon.lineTo(-97.06124, 32.834); + polygon.lineTo(-97.06127, 32.832); + + polygon.startPath(-97.06326, 32.759); + polygon.lineTo(-97.06298, 32.755); + + { + JsonParser polygonPathsWgs84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWGS84, polygon)); + MapGeometry mPolygonWGS84MP = GeometryEngine.jsonToGeometry(polygonPathsWgs84Parser); + + assertTrue(polygon.getPointCount() + 1 == ((Polygon) mPolygonWGS84MP.getGeometry()).getPointCount()); + assertTrue(polygon.getPoint(0).getX() == ((Polygon) mPolygonWGS84MP.getGeometry()).getPoint(0).getX()); + assertTrue(polygon.getPoint(0).getY() == ((Polygon) mPolygonWGS84MP.getGeometry()).getPoint(0).getY()); + + assertTrue(polygon.getPathCount() == ((Polygon) mPolygonWGS84MP.getGeometry()).getPathCount()); + assertTrue(polygon.getSegmentCount() + 1 == ((Polygon) mPolygonWGS84MP.getGeometry()).getSegmentCount()); + assertTrue(polygon.getSegmentCount(0) == ((Polygon) mPolygonWGS84MP.getGeometry()).getSegmentCount(0)); + assertTrue(polygon.getSegmentCount(1) + 1 == ((Polygon) mPolygonWGS84MP.getGeometry()).getSegmentCount(1)); + + int lastIndex = polygon.getPointCount() - 1; + assertTrue(polygon.getPoint(lastIndex).getX() == ((Polygon) mPolygonWGS84MP.getGeometry()) + .getPoint(lastIndex).getX()); + assertTrue(polygon.getPoint(lastIndex).getY() == ((Polygon) mPolygonWGS84MP.getGeometry()) + .getPoint(lastIndex).getY()); + + assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP.getSpatialReference().getID()); + + Polygon emptyPolygon = new Polygon(); + String emptyPolygonString = GeometryEngine.geometryToJson(spatialReferenceWGS84, emptyPolygon); + polygonPathsWgs84Parser = factory.createJsonParser(emptyPolygonString); + mPolygonWGS84MP = GeometryEngine.jsonToGeometry(polygonPathsWgs84Parser); + + assertTrue(mPolygonWGS84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == mPolygonWGS84MP.getSpatialReference().getID()); + } + } + + @Test + public void testEnvelope() throws JsonParseException, IOException { + Envelope envelope = new Envelope(); + envelope.setCoords(-109.55, 25.76, -86.39, 49.94); + + { + JsonParser envelopeWGS84Parser = factory + .createJsonParser(GeometryEngine.geometryToJson(spatialReferenceWGS84, envelope)); + MapGeometry envelopeWGS84MP = GeometryEngine.jsonToGeometry(envelopeWGS84Parser); + assertTrue(envelope.isEmpty() == envelopeWGS84MP.getGeometry().isEmpty()); + assertTrue(envelope.getXMax() == ((Envelope) envelopeWGS84MP.getGeometry()).getXMax()); + assertTrue(envelope.getYMax() == ((Envelope) envelopeWGS84MP.getGeometry()).getYMax()); + assertTrue(envelope.getXMin() == ((Envelope) envelopeWGS84MP.getGeometry()).getXMin()); + assertTrue(envelope.getYMin() == ((Envelope) envelopeWGS84MP.getGeometry()).getYMin()); + assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP.getSpatialReference().getID()); + + Envelope emptyEnvelope = new Envelope(); + String emptyEnvString = GeometryEngine.geometryToJson(spatialReferenceWGS84, emptyEnvelope); + envelopeWGS84Parser = factory.createJsonParser(emptyEnvString); + envelopeWGS84MP = GeometryEngine.jsonToGeometry(envelopeWGS84Parser); + + assertTrue(envelopeWGS84MP.getGeometry().isEmpty()); + assertTrue(spatialReferenceWGS84.getID() == envelopeWGS84MP.getSpatialReference().getID()); + } + } + + @Test + public void testCR181369() throws JsonParseException, IOException { + // CR181369 + { + String jsonStringPointAndWKT = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkt\" : \"PROJCS[\\\"NAD83_UTM_zone_15N\\\",GEOGCS[\\\"GCS_North_American_1983\\\",DATUM[\\\"D_North_American_1983\\\",SPHEROID[\\\"GRS_1980\\\",6378137.0,298.257222101]],PRIMEM[\\\"Greenwich\\\",0.0],UNIT[\\\"Degree\\\",0.0174532925199433]],PROJECTION[\\\"Transverse_Mercator\\\"],PARAMETER[\\\"false_easting\\\",500000.0],PARAMETER[\\\"false_northing\\\",0.0],PARAMETER[\\\"central_meridian\\\",-93.0],PARAMETER[\\\"scale_factor\\\",0.9996],PARAMETER[\\\"latitude_of_origin\\\",0.0],UNIT[\\\"Meter\\\",1.0]]\"} }"; + JsonParser jsonParserPointAndWKT = factory.createJsonParser(jsonStringPointAndWKT); + MapGeometry mapGeom2 = GeometryEngine.jsonToGeometry(jsonParserPointAndWKT); + String jsonStringPointAndWKT2 = GeometryEngine.geometryToJson(mapGeom2.getSpatialReference(), + mapGeom2.getGeometry()); + JsonParser jsonParserPointAndWKT2 = factory.createJsonParser(jsonStringPointAndWKT2); + MapGeometry mapGeom3 = GeometryEngine.jsonToGeometry(jsonParserPointAndWKT2); + assertTrue(((Point) mapGeom2.getGeometry()).getX() == ((Point) mapGeom3.getGeometry()).getX()); + assertTrue(((Point) mapGeom2.getGeometry()).getY() == ((Point) mapGeom3.getGeometry()).getY()); + assertTrue(mapGeom2.getSpatialReference().getText().equals(mapGeom3.getSpatialReference().getText())); + assertTrue(mapGeom2.getSpatialReference().getID() == mapGeom3.getSpatialReference().getID()); + } + } + + @Test + public void testSpatialRef() throws JsonParseException, IOException { + // String jsonStringPt = + // "{\"x\":-20037508.342787,\"y\":20037508.342787},\"spatialReference\":{\"wkid\":102100}}"; + String jsonStringPt = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\": 102100}}";// 102100 + @SuppressWarnings("unused") + String jsonStringPt2 = "{\"x\":10.0,\"y\":20.0,\"spatialReference\":{\"wkid\":4326}}"; + String jsonStringMpt = "{ \"points\" : [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], \"spatialReference\" : {\"wkid\" : 4326}}";// 4326 + String jsonStringMpt3D = "{\"hasZs\" : true,\"points\" : [ [-97.06138,32.837,35.0], [-97.06133,32.836,35.1], [-97.06124,32.834,35.2], [-97.06127,32.832,35.3] ],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPl = "{\"paths\" : [ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832] ], [ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPl3D = "{\"hasMs\" : true,\"paths\" : [[ [-97.06138,32.837,5], [-97.06133,32.836,6], [-97.06124,32.834,7], [-97.06127,32.832,8] ],[ [-97.06326,32.759], [-97.06298,32.755] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPg = "{ \"rings\" :[ [ [-97.06138,32.837], [-97.06133,32.836], [-97.06124,32.834], [-97.06127,32.832], [-97.06138,32.837] ], [ [-97.06326,32.759], [-97.06298,32.755], [-97.06153,32.749], [-97.06326,32.759] ]], \"spatialReference\" : {\"wkt\" : \"\"}}"; + String jsonStringPg3D = "{\"hasZs\" : true,\"hasMs\" : true,\"rings\" : [ [ [-97.06138, 32.837, 35.1, 4], [-97.06133, 32.836, 35.2, 4.1], [-97.06124, 32.834, 35.3, 4.2], [-97.06127, 32.832, 35.2, 44.3], [-97.06138, 32.837, 35.1, 4] ],[ [-97.06326, 32.759, 35.4], [-97.06298, 32.755, 35.5], [-97.06153, 32.749, 35.6], [-97.06326, 32.759, 35.4] ]],\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringPg2 = "{ \"spatialReference\" : {\"wkid\" : 4326}, \"rings\" : [[[-118.35,32.81],[-118.42,32.806],[-118.511,32.892],[-118.35,32.81]]]}"; + String jsonStringPg3 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":null}}"; + String jsonString2SpatialReferences = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":102100,\"wkid\":102100,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; + String jsonString2SpatialReferences2 = "{ \"spatialReference\": {\"layerName\":\"GAS_POINTS\",\"name\":null,\"sdesrid\":10,\"wkid\":10,\"wkt\":\"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}}"; + String jsonStringSR = "{\"wkid\" : 4326}"; + String jsonStringEnv = "{\"xmin\" : -109.55, \"ymin\" : 25.76, \"xmax\" : -86.39, \"ymax\" : 49.94,\"spatialReference\" : {\"wkid\" : 4326}}"; + String jsonStringHongKon = "{\"xmin\" : -122.55, \"ymin\" : 37.65, \"xmax\" : -122.28, \"ymax\" : 37.84,\"spatialReference\" : {\"wkid\" : 4326}}"; + @SuppressWarnings("unused") + String jsonStringWKT = " {\"wkt\" : \"GEOGCS[\\\"GCS_WGS_1984\\\",DATUM[\\\"D_WGS_1984\\\",SPHEROID[\\\"WGS_1984\\\",6378137,298.257223563]],PRIMEM[\\\"Greenwich\\\",0],UNIT[\\\"Degree\\\",0.017453292519943295]]\"}"; + String jsonStringInvalidWKID = "{\"x\":10.0,\"y\":20.0},\"spatialReference\":{\"wkid\":35253523}}"; + String jsonStringOregon = "{\"xmin\":7531831.219849482,\"ymin\":585702.9799639136,\"xmax\":7750143.589982405,\"ymax\":733289.6299999952,\"spatialReference\":{\"wkid\":102726}}"; + + JsonParser jsonParserPt = factory.createJsonParser(jsonStringPt); + JsonParser jsonParserMpt = factory.createJsonParser(jsonStringMpt); + JsonParser jsonParserMpt3D = factory.createJsonParser(jsonStringMpt3D); + JsonParser jsonParserPl = factory.createJsonParser(jsonStringPl); + JsonParser jsonParserPl3D = factory.createJsonParser(jsonStringPl3D); + JsonParser jsonParserPg = factory.createJsonParser(jsonStringPg); + JsonParser jsonParserPg3D = factory.createJsonParser(jsonStringPg3D); + JsonParser jsonParserPg2 = factory.createJsonParser(jsonStringPg2); + @SuppressWarnings("unused") + JsonParser jsonParserSR = factory.createJsonParser(jsonStringSR); + JsonParser jsonParserEnv = factory.createJsonParser(jsonStringEnv); + JsonParser jsonParserPg3 = factory.createJsonParser(jsonStringPg3); + @SuppressWarnings("unused") + JsonParser jsonParserCrazy1 = factory.createJsonParser(jsonString2SpatialReferences); + @SuppressWarnings("unused") + JsonParser jsonParserCrazy2 = factory.createJsonParser(jsonString2SpatialReferences2); + JsonParser jsonParserInvalidWKID = factory.createJsonParser(jsonStringInvalidWKID); + @SuppressWarnings("unused") + JsonParser jsonParseHongKon = factory.createJsonParser(jsonStringHongKon); + JsonParser jsonParseOregon = factory.createJsonParser(jsonStringOregon); + + MapGeometry mapGeom = GeometryEngine.jsonToGeometry(jsonParserPt); + // showProjectedGeometryInfo(mapGeom); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); + + MapGeometry mapGeomOregon = GeometryEngine.jsonToGeometry(jsonParseOregon); + Assert.assertTrue(mapGeomOregon.getSpatialReference().getID() == 102726); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserMpt3D); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + { + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0).getX() == -97.06138); + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(0).getY() == 32.837); + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3).getX() == -97.06127); + Assert.assertTrue(((MultiPoint) mapGeom.getGeometry()).getPoint(3).getY() == 32.832); + } + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPl3D); + { + // [[ [-97.06138,32.837,5], [-97.06133,32.836,6], + // [-97.06124,32.834,7], [-97.06127,32.832,8] ], + // [ [-97.06326,32.759], [-97.06298,32.755] ]]"; + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0).getX() == -97.06138); + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(0).getY() == 32.837); + int lastIndex = ((Polyline) mapGeom.getGeometry()).getPointCount() - 1; + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(lastIndex).getX() == -97.06298);// -97.06153, + // 32.749 + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(lastIndex).getY() == 32.755); + int lastIndexFirstLine = ((Polyline) mapGeom.getGeometry()).getPathEnd(0) - 1; + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(lastIndexFirstLine).getX() == -97.06127);// -97.06153, + // 32.749 + Assert.assertTrue(((Polyline) mapGeom.getGeometry()).getPoint(lastIndexFirstLine).getY() == 32.832); + } + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg); + Assert.assertTrue(mapGeom.getSpatialReference() == null); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3D); + { + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0).getX() == -97.06138); + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(0).getY() == 32.837); + int lastIndex = ((Polygon) mapGeom.getGeometry()).getPointCount() - 1; + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(lastIndex).getX() == -97.06153);// -97.06153, + // 32.749 + Assert.assertTrue(((Polygon) mapGeom.getGeometry()).getPoint(lastIndex).getY() == 32.749); + } + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg2); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserPg3); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 102100); + // showProjectedGeometryInfo(mapGeom); + + // mapGeom = GeometryEngine.jsonToGeometry(jsonParserCrazy1); + // Assert.assertTrue(mapGeom.getSpatialReference().getText().equals("")); + // showProjectedGeometryInfo(mapGeom); + + mapGeom = GeometryEngine.jsonToGeometry(jsonParserEnv); + Assert.assertTrue(mapGeom.getSpatialReference().getID() == 4326); + // showProjectedGeometryInfo(mapGeom); + + try { + GeometryEngine.jsonToGeometry(jsonParserInvalidWKID); + } catch (Exception ex) { + Assert.assertTrue("Should not throw for invalid wkid", false); + } + } + + @Test + public void testMP2onCR175871() throws Exception { + Polygon pg = new Polygon(); + pg.startPath(-50, 10); + pg.lineTo(-50, 12); + pg.lineTo(-45, 12); + pg.lineTo(-45, 10); + + Polygon pg1 = new Polygon(); + pg1.startPath(-45, 10); + pg1.lineTo(-40, 10); + pg1.lineTo(-40, 8); + pg.add(pg1, false); + + SpatialReference spatialReference = SpatialReference.create(4326); + + try { + String jSonStr = GeometryEngine.geometryToJson(spatialReference, pg); + JsonFactory jf = new JsonFactory(); + + JsonParser jp = jf.createJsonParser(jSonStr); + jp.nextToken(); + MapGeometry mg = GeometryEngine.jsonToGeometry(jp); + Geometry gm = mg.getGeometry(); + Assert.assertEquals(Geometry.Type.Polygon, gm.getType()); + Assert.assertTrue(mg.getSpatialReference().getID() == 4326); + + Polygon pgNew = (Polygon) gm; + + Assert.assertEquals(pgNew.getPathCount(), pg.getPathCount()); + Assert.assertEquals(pgNew.getPointCount(), pg.getPointCount()); + Assert.assertEquals(pgNew.getSegmentCount(), pg.getSegmentCount()); + + Assert.assertEquals(pgNew.getPoint(0).getX(), pg.getPoint(0).getX(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(1).getX(), pg.getPoint(1).getX(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(2).getX(), pg.getPoint(2).getX(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(3).getX(), pg.getPoint(3).getX(), 0.000000001); + + Assert.assertEquals(pgNew.getPoint(0).getY(), pg.getPoint(0).getY(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(1).getY(), pg.getPoint(1).getY(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(2).getY(), pg.getPoint(2).getY(), 0.000000001); + Assert.assertEquals(pgNew.getPoint(3).getY(), pg.getPoint(3).getY(), 0.000000001); + } catch (Exception ex) { + String err = ex.getMessage(); + System.out.print(err); + throw ex; + } + } + + @Test + public static int fromJsonToWkid(JsonParser parser) throws JsonParseException, IOException { + int wkid = 0; + if (parser.getCurrentToken() != JsonToken.START_OBJECT) { + return 0; + } + + while (parser.nextToken() != JsonToken.END_OBJECT) { + String fieldName = parser.getCurrentName(); + + if ("wkid".equals(fieldName)) { + parser.nextToken(); + wkid = parser.getIntValue(); + } + } + return wkid; + } + + @SuppressWarnings("unused") + private static void showProjectedGeometryInfo(MapGeometry mapGeom) { + System.out.println("\n"); + MapGeometry geom = mapGeom; + // while ((geom = geomCursor.next()) != null) { + + if (geom.getGeometry() instanceof Point) { + Point pnt = (Point) geom.getGeometry(); + System.out.println("Point(" + pnt.getX() + " , " + pnt.getY() + ")"); + if (geom.getSpatialReference() == null) { + System.out.println("No spatial reference"); + } else { + System.out.println("wkid: " + geom.getSpatialReference().getID()); + } + + } else if (geom.getGeometry() instanceof MultiPoint) { + MultiPoint mp = (MultiPoint) geom.getGeometry(); + System.out.println("Multipoint has " + mp.getPointCount() + " points."); + + System.out.println("wkid: " + geom.getSpatialReference().getID()); + + } else if (geom.getGeometry() instanceof Polygon) { + Polygon mp = (Polygon) geom.getGeometry(); + System.out.println("Polygon has " + mp.getPointCount() + " points and " + mp.getPathCount() + " parts."); + if (mp.getPathCount() > 1) { + System.out.println("Part start of 2nd segment : " + mp.getPathStart(1)); + System.out.println("Part end of 2nd segment : " + mp.getPathEnd(1)); + System.out.println("Part size of 2nd segment : " + mp.getPathSize(1)); + + int start = mp.getPathStart(1); + int end = mp.getPathEnd(1); + for (int i = start; i < end; i++) { + Point pp = mp.getPoint(i); + System.out.println("Point(" + i + ") = (" + pp.getX() + ", " + pp.getY() + ")"); + } + } + System.out.println("wkid: " + geom.getSpatialReference().getID()); + + } else if (geom.getGeometry() instanceof Polyline) { + Polyline mp = (Polyline) geom.getGeometry(); + System.out.println("Polyline has " + mp.getPointCount() + " points and " + mp.getPathCount() + " parts."); + System.out.println("Part start of 2nd segment : " + mp.getPathStart(1)); + System.out.println("Part end of 2nd segment : " + mp.getPathEnd(1)); + System.out.println("Part size of 2nd segment : " + mp.getPathSize(1)); + int start = mp.getPathStart(1); + int end = mp.getPathEnd(1); + for (int i = start; i < end; i++) { + Point pp = mp.getPoint(i); + System.out.println("Point(" + i + ") = (" + pp.getX() + ", " + pp.getY() + ")"); + } + + System.out.println("wkid: " + geom.getSpatialReference().getID()); + } + } + + @Test + public void testGeometryToJSON() { + Polygon geom = new Polygon(); + geom.startPath(new Point(-113, 34)); + geom.lineTo(new Point(-105, 34)); + geom.lineTo(new Point(-108, 40)); + + String outputPolygon1 = GeometryEngine.geometryToJson(-1, geom);// Test + // WKID + // == -1 + // System.out.println("Geom JSON STRING is" + outputPolygon1); + String correctPolygon1 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]]}"; + + assertEquals(correctPolygon1, outputPolygon1); + + String outputPolygon2 = GeometryEngine.geometryToJson(4326, geom); + // System.out.println("Geom JSON STRING is" + outputPolygon2); + + String correctPolygon2 = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":4326}}"; + assertEquals(correctPolygon2, outputPolygon2); + } + + @Test + public void testGeometryToJSONOldID() throws Exception {// CR + Polygon geom = new Polygon(); + geom.startPath(new Point(-113, 34)); + geom.lineTo(new Point(-105, 34)); + geom.lineTo(new Point(-108, 40)); + String outputPolygon = GeometryEngine.geometryToJson(SpatialReference.create(3857), geom);// Test + // WKID + // == + // -1 + String correctPolygon = "{\"rings\":[[[-113,34],[-105,34],[-108,40],[-113,34]]],\"spatialReference\":{\"wkid\":102100,\"latestWkid\":3857}}"; + assertTrue(outputPolygon.equals(correctPolygon)); + JsonFactory jf = new JsonFactory(); + JsonParser jp = jf.createJsonParser(outputPolygon); + jp.nextToken(); + MapGeometry mg = GeometryEngine.jsonToGeometry(jp); + @SuppressWarnings("unused") + int srId = mg.getSpatialReference().getID(); + @SuppressWarnings("unused") + int srOldId = mg.getSpatialReference().getOldID(); + Assert.assertTrue(mg.getSpatialReference().getID() == 3857); + Assert.assertTrue(mg.getSpatialReference().getLatestID() == 3857); + Assert.assertTrue(mg.getSpatialReference().getOldID() == 102100); + } } diff --git a/src/test/java/com/esri/core/geometry/TestMathUtils.java b/src/test/java/com/esri/core/geometry/TestMathUtils.java index 0d41a739..c6d39735 100644 --- a/src/test/java/com/esri/core/geometry/TestMathUtils.java +++ b/src/test/java/com/esri/core/geometry/TestMathUtils.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestMultiPoint.java b/src/test/java/com/esri/core/geometry/TestMultiPoint.java index b5b7d534..cd8e8d70 100644 --- a/src/test/java/com/esri/core/geometry/TestMultiPoint.java +++ b/src/test/java/com/esri/core/geometry/TestMultiPoint.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index 3edf417c..50fdcf5f 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestOffset.java b/src/test/java/com/esri/core/geometry/TestOffset.java index 1bd18b9a..385e3504 100644 --- a/src/test/java/com/esri/core/geometry/TestOffset.java +++ b/src/test/java/com/esri/core/geometry/TestOffset.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import com.esri.core.geometry.OperatorOffset.JoinType; diff --git a/src/test/java/com/esri/core/geometry/TestPoint.java b/src/test/java/com/esri/core/geometry/TestPoint.java index 0140198a..c2e8bd2f 100644 --- a/src/test/java/com/esri/core/geometry/TestPoint.java +++ b/src/test/java/com/esri/core/geometry/TestPoint.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.Random; diff --git a/src/test/java/com/esri/core/geometry/TestPolygon.java b/src/test/java/com/esri/core/geometry/TestPolygon.java index 8b918e9c..2c4b0b4f 100644 --- a/src/test/java/com/esri/core/geometry/TestPolygon.java +++ b/src/test/java/com/esri/core/geometry/TestPolygon.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.IOException; diff --git a/src/test/java/com/esri/core/geometry/TestPolygonUtils.java b/src/test/java/com/esri/core/geometry/TestPolygonUtils.java index 16bc5215..2967d2f7 100644 --- a/src/test/java/com/esri/core/geometry/TestPolygonUtils.java +++ b/src/test/java/com/esri/core/geometry/TestPolygonUtils.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestProximity2D.java b/src/test/java/com/esri/core/geometry/TestProximity2D.java index f06c8ce9..9f6cd184 100644 --- a/src/test/java/com/esri/core/geometry/TestProximity2D.java +++ b/src/test/java/com/esri/core/geometry/TestProximity2D.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestQuadTree.java b/src/test/java/com/esri/core/geometry/TestQuadTree.java index 6dde9220..9c4800ad 100644 --- a/src/test/java/com/esri/core/geometry/TestQuadTree.java +++ b/src/test/java/com/esri/core/geometry/TestQuadTree.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.util.ArrayList; diff --git a/src/test/java/com/esri/core/geometry/TestRasterizedGeometry2D.java b/src/test/java/com/esri/core/geometry/TestRasterizedGeometry2D.java index a1ff65fc..c8c835be 100644 --- a/src/test/java/com/esri/core/geometry/TestRasterizedGeometry2D.java +++ b/src/test/java/com/esri/core/geometry/TestRasterizedGeometry2D.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestRelation.java b/src/test/java/com/esri/core/geometry/TestRelation.java index 041908cf..4ecbf514 100644 --- a/src/test/java/com/esri/core/geometry/TestRelation.java +++ b/src/test/java/com/esri/core/geometry/TestRelation.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.IOException; diff --git a/src/test/java/com/esri/core/geometry/TestSerialization.java b/src/test/java/com/esri/core/geometry/TestSerialization.java index 269b0879..8cdb4ad9 100644 --- a/src/test/java/com/esri/core/geometry/TestSerialization.java +++ b/src/test/java/com/esri/core/geometry/TestSerialization.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.ByteArrayInputStream; diff --git a/src/test/java/com/esri/core/geometry/TestSimplify.java b/src/test/java/com/esri/core/geometry/TestSimplify.java index 47a741c1..944d271d 100644 --- a/src/test/java/com/esri/core/geometry/TestSimplify.java +++ b/src/test/java/com/esri/core/geometry/TestSimplify.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; //import java.io.FileOutputStream; diff --git a/src/test/java/com/esri/core/geometry/TestSpatialReference.java b/src/test/java/com/esri/core/geometry/TestSpatialReference.java index 8d21712f..c002f977 100644 --- a/src/test/java/com/esri/core/geometry/TestSpatialReference.java +++ b/src/test/java/com/esri/core/geometry/TestSpatialReference.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestTouch.java b/src/test/java/com/esri/core/geometry/TestTouch.java index b677ba7d..8be45c11 100644 --- a/src/test/java/com/esri/core/geometry/TestTouch.java +++ b/src/test/java/com/esri/core/geometry/TestTouch.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestTreap.java b/src/test/java/com/esri/core/geometry/TestTreap.java index 3bd20606..e1f2b5b5 100644 --- a/src/test/java/com/esri/core/geometry/TestTreap.java +++ b/src/test/java/com/esri/core/geometry/TestTreap.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestUnion.java b/src/test/java/com/esri/core/geometry/TestUnion.java index ad06dbbc..55392e39 100644 --- a/src/test/java/com/esri/core/geometry/TestUnion.java +++ b/src/test/java/com/esri/core/geometry/TestUnion.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import junit.framework.TestCase; diff --git a/src/test/java/com/esri/core/geometry/TestWKBSupport.java b/src/test/java/com/esri/core/geometry/TestWKBSupport.java index f0f4752a..a55252fb 100644 --- a/src/test/java/com/esri/core/geometry/TestWKBSupport.java +++ b/src/test/java/com/esri/core/geometry/TestWKBSupport.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.io.IOException; diff --git a/src/test/java/com/esri/core/geometry/TestWkbImportOnPostgresST.java b/src/test/java/com/esri/core/geometry/TestWkbImportOnPostgresST.java index ccac6c5f..95c55d2b 100644 --- a/src/test/java/com/esri/core/geometry/TestWkbImportOnPostgresST.java +++ b/src/test/java/com/esri/core/geometry/TestWkbImportOnPostgresST.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import java.nio.ByteBuffer; diff --git a/src/test/java/com/esri/core/geometry/TestWkid.java b/src/test/java/com/esri/core/geometry/TestWkid.java index cd249233..9bac7c5b 100644 --- a/src/test/java/com/esri/core/geometry/TestWkid.java +++ b/src/test/java/com/esri/core/geometry/TestWkid.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import static org.junit.Assert.*; diff --git a/src/test/java/com/esri/core/geometry/TestWktParser.java b/src/test/java/com/esri/core/geometry/TestWktParser.java index db40cdff..71ce5b1d 100644 --- a/src/test/java/com/esri/core/geometry/TestWktParser.java +++ b/src/test/java/com/esri/core/geometry/TestWktParser.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; import static org.junit.Assert.*; diff --git a/src/test/java/com/esri/core/geometry/Utils.java b/src/test/java/com/esri/core/geometry/Utils.java index 9bbe51c0..d9923281 100644 --- a/src/test/java/com/esri/core/geometry/Utils.java +++ b/src/test/java/com/esri/core/geometry/Utils.java @@ -1,3 +1,27 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + package com.esri.core.geometry; public class Utils { From 43fbcaaad1ebdfb9f1c832335c3acee7f8a2943c Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sat, 12 Aug 2017 00:06:48 -0700 Subject: [PATCH 04/75] rename equals to Equals (#143) --- .../com/esri/core/geometry/ogc/OGCCurve.java | 1 - .../esri/core/geometry/ogc/OGCGeometry.java | 18 +++++++++--- .../esri/core/geometry/ogc/OGCMultiPoint.java | 2 -- .../com/esri/core/geometry/ogc/OGCPoint.java | 1 - .../java/com/esri/core/geometry/TestOGC.java | 28 ++++++++++++------- 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java index 30f50dd0..0755dc2e 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java @@ -25,7 +25,6 @@ package com.esri.core.geometry.ogc; import com.esri.core.geometry.MultiPoint; -import com.esri.core.geometry.Point; public abstract class OGCCurve extends OGCGeometry { public abstract double length(); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 716ee745..7bcc17c8 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -24,7 +24,6 @@ package com.esri.core.geometry.ogc; -import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; @@ -205,16 +204,27 @@ public boolean isMeasured() { abstract public OGCGeometry boundary(); /** - * OGC equals - * + * OGC equals. Performs topological comparison with tolerance. + * This is different from equals(Object), that uses exact comparison. */ - public boolean equals(OGCGeometry another) { + public boolean Equals(OGCGeometry another) { + if (this == another) + return true; + + if (another == null) + return false; + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.equals(geom1, geom2, getEsriSpatialReference()); } + @Deprecated + public boolean equals(OGCGeometry another) { + return Equals(another); + } + public boolean disjoint(OGCGeometry another) { com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java index 1b0473b8..77258957 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java @@ -27,13 +27,11 @@ import java.nio.ByteBuffer; import com.esri.core.geometry.Geometry; -import com.esri.core.geometry.GeometryCursor; import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.MultiPoint; import com.esri.core.geometry.Operator; import com.esri.core.geometry.OperatorExportToWkb; import com.esri.core.geometry.OperatorFactoryLocal; -import com.esri.core.geometry.OperatorUnion; import com.esri.core.geometry.Point; import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.WkbExportFlags; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java index 98b2aaf9..7e246a6e 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java @@ -26,7 +26,6 @@ import java.nio.ByteBuffer; -import com.esri.core.geometry.GeometryCursor; import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.MultiPoint; import com.esri.core.geometry.Operator; diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index 50fdcf5f..ca2bcf6d 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -82,28 +82,36 @@ public void testPolygon() throws Exception { OGCLineString ls = p.exteriorRing(); // assertTrue(ls.pointN(1).equals(OGCGeometry.fromText("POINT(10 -10)"))); boolean b = ls - .equals(OGCGeometry + .Equals(OGCGeometry .fromText("LINESTRING(-10 -10, 10 -10, 10 10, -10 10, -10 -10)")); assertTrue(b); OGCLineString lsi = p.interiorRingN(0); - b = lsi.equals(OGCGeometry + b = lsi.Equals(OGCGeometry .fromText("LINESTRING(-5 -5, -5 5, 5 5, 5 -5, -5 -5)")); assertTrue(b); b = lsi.equals((Object)OGCGeometry .fromText("LINESTRING(-5 -5, -5 5, 5 5, 5 -5, -5 -5)")); - assertTrue(!lsi.equals(ls)); + assertTrue(!lsi.Equals(ls)); OGCMultiCurve boundary = p.boundary(); String s = boundary.asText(); assertTrue(s.equals("MULTILINESTRING ((-10 -10, 10 -10, 10 10, -10 10, -10 -10), (-5 -5, -5 5, 5 5, 5 -5, -5 -5))")); { - OGCGeometry g2 = OGCGeometry.fromGeoJson("{\"type\": \"Polygon\", \"coordinates\": [[[1.00000001,1.00000001], [4.00000001,1.00000001], [4.00000001,4.00000001], [1.00000001,4.00000001]]]}"); - OGCGeometry.fromGeoJson("{\"type\": \"LineString\", \"coordinates\": [[1.00000001,1.00000001], [7.00000001,8.00000001]]}").intersects(g2); - OGCGeometry.fromGeoJson("{\"type\": \"LineString\", \"coordinates\": [[2.449,4.865], [7.00000001,8.00000001]]}").intersects(g2); - - OGCGeometry g3 = OGCGeometry.fromGeoJson("{\"type\": \"Polygon\", \"coordinates\": [[[1.00000001,1.00000001], [4.00000001,1.00000001], [4.00000001,4.00000001], [1.00000001,4.00000001]]]}"); - boolean bb = g2.equals((Object)g3); - assertTrue(bb); + OGCGeometry g2 = OGCGeometry.fromGeoJson( + "{\"type\": \"Polygon\", \"coordinates\": [[[1.00000001,1.00000001], [4.00000001,1.00000001], [4.00000001,4.00000001], [1.00000001,4.00000001]]]}"); + OGCGeometry + .fromGeoJson( + "{\"type\": \"LineString\", \"coordinates\": [[1.00000001,1.00000001], [7.00000001,8.00000001]]}") + .intersects(g2); + OGCGeometry + .fromGeoJson( + "{\"type\": \"LineString\", \"coordinates\": [[2.449,4.865], [7.00000001,8.00000001]]}") + .intersects(g2); + + OGCGeometry g3 = OGCGeometry.fromGeoJson( + "{\"type\": \"Polygon\", \"coordinates\": [[[1.00000001,1.00000001], [4.00000001,1.00000001], [4.00000001,4.00000001], [1.00000001,4.00000001]]]}"); + boolean bb = g2.equals((Object) g3); + assertTrue(bb); } } From 630a46e35db64d112a79fbe0ea587a57a32ac7f6 Mon Sep 17 00:00:00 2001 From: GISDev01 Date: Thu, 30 Nov 2017 13:19:42 -0500 Subject: [PATCH 05/75] Update Maven coordinates to the latest stable version of the Esri Geometry API for Java, 2.0.0 (#148) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6d243c1..ca345997 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 1.2.1 + 2.0.0 ``` From e2f5fadf29e517618ff3c5f109f64e837d43220f Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Mon, 4 Dec 2017 10:00:04 -0800 Subject: [PATCH 06/75] Update .travis.yml (#149) * Update .travis.yml Update to use JDKs that are available: https://docs.travis-ci.com/user/reference/trusty/#JVM-(Clojure%2C-Groovy%2C-Java%2C-Scala)-images * Update pom.xml Update javadoc plugin version --- .travis.yml | 7 ++++--- pom.xml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7406d2b7..d1fa4fad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: java jdk: - - openjdk6 - openjdk7 - - oraclejdk7 + - openjdk8 + - oraclejdk8 + - oraclejdk9 notifications: - email: false \ No newline at end of file + email: false diff --git a/pom.xml b/pom.xml index 6738b3ae..bb048091 100755 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ 2.3.1 2.2.1 - 2.9 + 3.0.0-M1 From 3704c2205b435788573303a0698a082734ae76c4 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Fri, 29 Dec 2017 16:14:11 -0800 Subject: [PATCH 07/75] README: update copyright to 2018 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca345997..34589c2f 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Find a bug or want to request a new feature? Please let us know by submitting a Esri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/esri/contributing) ## Licensing -Copyright 2013-2017 Esri +Copyright 2013-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 1adecb86f11052e835cf1bb4ae97fd13bb49d4de Mon Sep 17 00:00:00 2001 From: Maria Basmanova Date: Mon, 5 Mar 2018 13:32:15 -0500 Subject: [PATCH 08/75] Add OGCGeometry::estimateMemorySize API (#157) --- pom.xml | 9 ++ .../core/geometry/AttributeStreamBase.java | 7 + .../core/geometry/AttributeStreamOfDbl.java | 11 ++ .../core/geometry/AttributeStreamOfFloat.java | 11 +- .../core/geometry/AttributeStreamOfInt16.java | 11 +- .../core/geometry/AttributeStreamOfInt32.java | 11 +- .../core/geometry/AttributeStreamOfInt64.java | 11 +- .../core/geometry/AttributeStreamOfInt8.java | 10 ++ .../java/com/esri/core/geometry/Envelope.java | 10 +- .../com/esri/core/geometry/Envelope2D.java | 9 +- .../java/com/esri/core/geometry/Geometry.java | 20 ++- .../java/com/esri/core/geometry/Line.java | 8 ++ .../com/esri/core/geometry/MultiPathImpl.java | 24 +++- .../com/esri/core/geometry/MultiPoint.java | 8 ++ .../esri/core/geometry/MultiPointImpl.java | 16 ++- .../java/com/esri/core/geometry/Point.java | 10 +- .../java/com/esri/core/geometry/Polygon.java | 8 +- .../java/com/esri/core/geometry/Polyline.java | 7 + .../java/com/esri/core/geometry/SizeOf.java | 127 ++++++++++++++++++ .../esri/core/geometry/SpatialReference.java | 7 +- .../core/geometry/SpatialReferenceImpl.java | 13 -- .../ogc/OGCConcreteGeometryCollection.java | 15 +++ .../esri/core/geometry/ogc/OGCGeometry.java | 46 ++++++- .../esri/core/geometry/ogc/OGCLineString.java | 10 ++ .../core/geometry/ogc/OGCMultiLineString.java | 10 +- .../esri/core/geometry/ogc/OGCMultiPoint.java | 12 +- .../core/geometry/ogc/OGCMultiPolygon.java | 9 ++ .../com/esri/core/geometry/ogc/OGCPoint.java | 12 +- .../esri/core/geometry/ogc/OGCPolygon.java | 9 ++ .../core/geometry/TestEstimateMemorySize.java | 106 +++++++++++++++ 30 files changed, 539 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/esri/core/geometry/SizeOf.java create mode 100644 src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java diff --git a/pom.xml b/pom.xml index bb048091..f9e62a0c 100755 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,7 @@ 2.6.5 4.12 + 0.2 2.3.1 @@ -120,6 +121,14 @@ ${junit.version} test + + + + org.openjdk.jol + jol-core + ${jol.version} + test + diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamBase.java b/src/main/java/com/esri/core/geometry/AttributeStreamBase.java index 54f03ba2..2755406a 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamBase.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamBase.java @@ -46,6 +46,13 @@ public AttributeStreamBase() { */ public abstract int virtualSize(); + /** + * Returns an estimate of this object size in bytes. + * + * @return Returns an estimate of this object size in bytes. + */ + public abstract long estimateMemorySize(); + /** * Returns the Persistence type of the stream. */ diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java index 88a639b8..75d45a76 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java @@ -26,9 +26,14 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Persistence; + import java.nio.ByteBuffer; import java.util.Arrays; +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_DBL; +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32; +import static com.esri.core.geometry.SizeOf.sizeOfDoubleArray; + final class AttributeStreamOfDbl extends AttributeStreamBase { private double[] m_buffer = null; @@ -173,6 +178,12 @@ public int virtualSize() { return size(); } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ATTRIBUTE_STREAM_OF_DBL + sizeOfDoubleArray(m_buffer.length); + } + // @Override // public void addRange(AttributeStreamBase src, int srcStartIndex, int // count) { diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java index 491ae221..95ef8c5f 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java @@ -26,10 +26,13 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Persistence; + import java.nio.ByteBuffer; -final class AttributeStreamOfFloat extends AttributeStreamBase { +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT; +import static com.esri.core.geometry.SizeOf.sizeOfFloatArray; +final class AttributeStreamOfFloat extends AttributeStreamBase { private float[] m_buffer = null; private int m_size; @@ -145,6 +148,12 @@ public int virtualSize() { return size(); } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT + sizeOfFloatArray(m_buffer.length); + } + @Override public int getPersistence() { return Persistence.enumFloat; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java index a7d1e175..987ffae3 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt16.java @@ -26,10 +26,13 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Persistence; + import java.nio.ByteBuffer; -final class AttributeStreamOfInt16 extends AttributeStreamBase { +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT16; +import static com.esri.core.geometry.SizeOf.sizeOfShortArray; +final class AttributeStreamOfInt16 extends AttributeStreamBase { private short[] m_buffer = null; private int m_size; @@ -145,6 +148,12 @@ public int virtualSize() { return size(); } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ATTRIBUTE_STREAM_OF_INT16 + sizeOfShortArray(m_buffer.length); + } + @Override public int getPersistence() { return Persistence.enumInt16; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java index 6ece2a71..1939bb0f 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java @@ -26,11 +26,14 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Persistence; + import java.nio.ByteBuffer; import java.util.Arrays; -final class AttributeStreamOfInt32 extends AttributeStreamBase { +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32; +import static com.esri.core.geometry.SizeOf.sizeOfIntArray; +final class AttributeStreamOfInt32 extends AttributeStreamBase { private int[] m_buffer = null; private int m_size; @@ -158,6 +161,12 @@ public int virtualSize() { return size(); } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ATTRIBUTE_STREAM_OF_INT32 + sizeOfIntArray(m_buffer.length); + } + @Override public int getPersistence() { return Persistence.enumInt32; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java index 92688ccd..99376590 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java @@ -26,10 +26,13 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Persistence; + import java.nio.ByteBuffer; -final class AttributeStreamOfInt64 extends AttributeStreamBase { +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT64; +import static com.esri.core.geometry.SizeOf.sizeOfLongArray; +final class AttributeStreamOfInt64 extends AttributeStreamBase { private long[] m_buffer = null; private int m_size; @@ -145,6 +148,12 @@ public int virtualSize() { return size(); } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ATTRIBUTE_STREAM_OF_INT64 + sizeOfLongArray(m_buffer.length); + } + @Override public int getPersistence() { return Persistence.enumInt64; diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java index a4af8ff5..a93d154a 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt8.java @@ -26,8 +26,12 @@ package com.esri.core.geometry; import com.esri.core.geometry.VertexDescription.Persistence; + import java.nio.ByteBuffer; +import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT8; +import static com.esri.core.geometry.SizeOf.sizeOfByteArray; + final class AttributeStreamOfInt8 extends AttributeStreamBase { private byte[] m_buffer = null; @@ -152,6 +156,12 @@ public int virtualSize() { return size(); } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ATTRIBUTE_STREAM_OF_INT8 + sizeOfByteArray(m_buffer.length); + } + @Override public int getPersistence() { return Persistence.enumInt8; diff --git a/src/main/java/com/esri/core/geometry/Envelope.java b/src/main/java/com/esri/core/geometry/Envelope.java index 1370ca4f..ca884b55 100644 --- a/src/main/java/com/esri/core/geometry/Envelope.java +++ b/src/main/java/com/esri/core/geometry/Envelope.java @@ -25,9 +25,11 @@ package com.esri.core.geometry; +import com.esri.core.geometry.VertexDescription.Semantics; + import java.io.Serializable; -import com.esri.core.geometry.VertexDescription.Semantics; +import static com.esri.core.geometry.SizeOf.SIZE_OF_ENVELOPE; /** * An envelope is an axis-aligned rectangle. @@ -445,6 +447,12 @@ public int getDimension() { return 2; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_ENVELOPE + m_envelope.estimateMemorySize() + estimateMemorySize(m_attributes); + } + @Override public void queryEnvelope(Envelope env) { copyTo(env); diff --git a/src/main/java/com/esri/core/geometry/Envelope2D.java b/src/main/java/com/esri/core/geometry/Envelope2D.java index 172619dd..fa41db68 100644 --- a/src/main/java/com/esri/core/geometry/Envelope2D.java +++ b/src/main/java/com/esri/core/geometry/Envelope2D.java @@ -28,12 +28,14 @@ import java.io.ObjectStreamException; import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_ENVELOPE2D; + /** * An axis parallel 2-dimensional rectangle. */ public final class Envelope2D implements Serializable { private static final long serialVersionUID = 1L; - + private final static int XLESSXMIN = 1; // private final int XGREATERXMAX = 2; private final static int YLESSYMIN = 4; @@ -79,6 +81,11 @@ public Envelope2D(double _xmin, double _ymin, double _xmax, double _ymax) { public Envelope2D(Envelope2D other) { setCoords(other); } + + public int estimateMemorySize() + { + return SIZE_OF_ENVELOPE2D; + } public void setCoords(double _x, double _y) { xmin = _x; diff --git a/src/main/java/com/esri/core/geometry/Geometry.java b/src/main/java/com/esri/core/geometry/Geometry.java index 68e93671..01614b14 100644 --- a/src/main/java/com/esri/core/geometry/Geometry.java +++ b/src/main/java/com/esri/core/geometry/Geometry.java @@ -25,11 +25,11 @@ package com.esri.core.geometry; -import com.esri.core.geometry.VertexDescription.Semantics; - import java.io.ObjectStreamException; import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.sizeOfDoubleArray; + /** * Common properties and methods shared by all geometric objects. Geometries are * objects that define a spatial location and and associated geometric shape. @@ -150,6 +150,22 @@ static public Geometry.Type intToType(int geometryType) */ public abstract int getDimension(); + /** + * Returns an estimate of this object size in bytes. + *

+ * This estimate doesn't include the size of the {@link VertexDescription} object + * because instances of {@link VertexDescription} are shared among + * geometry objects. + * + * @return Returns an estimate of this object size in bytes. + */ + public abstract long estimateMemorySize(); + + protected static long estimateMemorySize(double[] attributes) + { + return attributes != null ? sizeOfDoubleArray(attributes.length) : 0; + } + /** * Returns the VertexDescription of this geomtry. */ diff --git a/src/main/java/com/esri/core/geometry/Line.java b/src/main/java/com/esri/core/geometry/Line.java index 4eccd513..90b08561 100644 --- a/src/main/java/com/esri/core/geometry/Line.java +++ b/src/main/java/com/esri/core/geometry/Line.java @@ -29,6 +29,8 @@ import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_LINE; + /** * A straight line between a pair of points. * @@ -40,6 +42,12 @@ public Geometry.Type getType() { return Type.Line; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_LINE + estimateMemorySize(m_attributes); + } + @Override public double calculateLength2D() { double dx = m_xStart - m_xEnd; diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java index dce85615..54ec0a5d 100644 --- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java @@ -25,10 +25,9 @@ package com.esri.core.geometry; -import com.esri.core.geometry.MultiVertexGeometryImpl.DirtyFlags; +import static com.esri.core.geometry.SizeOf.SIZE_OF_MULTI_PATH_IMPL; final class MultiPathImpl extends MultiVertexGeometryImpl { - protected boolean m_bPolygon; protected Point m_moveToPoint; protected double m_cachedLength2D; @@ -60,6 +59,27 @@ final class MultiPathImpl extends MultiVertexGeometryImpl { // Bezier, XXX, Arc, // XXX; + @Override + public long estimateMemorySize() + { + long size = SIZE_OF_MULTI_PATH_IMPL + + + (m_envelope != null ? m_envelope.estimateMemorySize() : 0) + + (m_moveToPoint != null ? m_moveToPoint.estimateMemorySize() : 0) + + (m_cachedRingAreas2D != null ? m_cachedRingAreas2D.estimateMemorySize() : 0) + + m_paths.estimateMemorySize() + + m_pathFlags.estimateMemorySize() + + (m_segmentFlags != null ? m_segmentFlags.estimateMemorySize() : 0) + + (m_segmentParamIndex != null ? m_segmentParamIndex.estimateMemorySize() : 0) + + (m_segmentParams != null ? m_segmentParams.estimateMemorySize() : 0); + + if (m_vertexAttributes != null) { + for (int i = 0; i < m_vertexAttributes.length; i++) { + size += m_vertexAttributes[i].estimateMemorySize(); + } + } + return size; + } + public boolean hasNonLinearSegments() { return m_curveParamwritePoint > 0; } diff --git a/src/main/java/com/esri/core/geometry/MultiPoint.java b/src/main/java/com/esri/core/geometry/MultiPoint.java index 8a3f6f6a..4beca5b5 100644 --- a/src/main/java/com/esri/core/geometry/MultiPoint.java +++ b/src/main/java/com/esri/core/geometry/MultiPoint.java @@ -26,6 +26,8 @@ import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_MULTI_POINT; + /** * A Multipoint is a collection of points. A multipoint is a one-dimensional * geometry object. Multipoints can be used to store a collection of point-based @@ -258,6 +260,12 @@ public int getDimension() { return 0; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_MULTI_POINT + m_impl.estimateMemorySize(); + } + @Override public Geometry.Type getType() { return Type.MultiPoint; diff --git a/src/main/java/com/esri/core/geometry/MultiPointImpl.java b/src/main/java/com/esri/core/geometry/MultiPointImpl.java index b3d0a4b7..bb16671f 100644 --- a/src/main/java/com/esri/core/geometry/MultiPointImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiPointImpl.java @@ -26,11 +26,12 @@ import com.esri.core.geometry.VertexDescription.Semantics; +import static com.esri.core.geometry.SizeOf.SIZE_OF_MULTI_POINT_IMPL; + /** * The MultiPoint is a collection of points. */ final class MultiPointImpl extends MultiVertexGeometryImpl { - public MultiPointImpl() { super(); m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D(); @@ -247,6 +248,19 @@ public int getDimension() { return 0; } + @Override + public long estimateMemorySize() + { + long size = SIZE_OF_MULTI_POINT_IMPL + (m_envelope != null ? m_envelope.estimateMemorySize() : 0); + + if (m_vertexAttributes != null) { + for (int i = 0; i < m_vertexAttributes.length; i++) { + size += m_vertexAttributes[i].estimateMemorySize(); + } + } + return size; + } + @Override public Geometry.Type getType() { return Type.MultiPoint; diff --git a/src/main/java/com/esri/core/geometry/Point.java b/src/main/java/com/esri/core/geometry/Point.java index 2343c5df..d96589ae 100644 --- a/src/main/java/com/esri/core/geometry/Point.java +++ b/src/main/java/com/esri/core/geometry/Point.java @@ -28,6 +28,8 @@ import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_POINT; + /** * A Point is a zero-dimensional object that represents a specific (X,Y) * location in a two-dimensional XY-Plane. In case of Geographic Coordinate @@ -37,7 +39,7 @@ public class Point extends Geometry implements Serializable { //We are using writeReplace instead. //private static final long serialVersionUID = 2L; - double[] m_attributes; // use doubles to store everything (long are bitcast) + double[] m_attributes; // use doubles to store everything (long are bitcast) /** * Creates an empty 2D point. @@ -369,6 +371,12 @@ public int getDimension() { return 0; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_POINT + estimateMemorySize(m_attributes); + } + @Override public void setEmpty() { _touch(); diff --git a/src/main/java/com/esri/core/geometry/Polygon.java b/src/main/java/com/esri/core/geometry/Polygon.java index cb027357..a8298077 100644 --- a/src/main/java/com/esri/core/geometry/Polygon.java +++ b/src/main/java/com/esri/core/geometry/Polygon.java @@ -27,11 +27,12 @@ import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_POLYGON; + /** * A polygon is a collection of one or many interior or exterior rings. */ public class Polygon extends MultiPath implements Serializable { - private static final long serialVersionUID = 2L;// TODO:remove as we use // writeReplace and // GeometrySerializer @@ -62,6 +63,11 @@ public Geometry.Type getType() { return Type.Polygon; } + @Override + public long estimateMemorySize() { + return SIZE_OF_POLYGON + m_impl.estimateMemorySize(); + } + /** * Calculates the ring area for this ring. * diff --git a/src/main/java/com/esri/core/geometry/Polyline.java b/src/main/java/com/esri/core/geometry/Polyline.java index 4c83a147..0d842806 100644 --- a/src/main/java/com/esri/core/geometry/Polyline.java +++ b/src/main/java/com/esri/core/geometry/Polyline.java @@ -27,6 +27,8 @@ import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_POLYLINE; + /** * A polyline is a collection of one or many paths. * @@ -72,6 +74,11 @@ public Geometry.Type getType() { return Type.Polyline; } + @Override + public long estimateMemorySize() { + return SIZE_OF_POLYLINE + m_impl.estimateMemorySize(); + } + /** * Returns TRUE when this geometry has exactly same type, properties, and * coordinates as the other geometry. diff --git a/src/main/java/com/esri/core/geometry/SizeOf.java b/src/main/java/com/esri/core/geometry/SizeOf.java new file mode 100644 index 00000000..86683a93 --- /dev/null +++ b/src/main/java/com/esri/core/geometry/SizeOf.java @@ -0,0 +1,127 @@ +/* + Copyright 1995-2018 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ +package com.esri.core.geometry; + +import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_CHAR_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_CHAR_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_DOUBLE_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_DOUBLE_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_FLOAT_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_FLOAT_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_INT_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_INT_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_LONG_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_LONG_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE; + +public final class SizeOf +{ + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT = 24; + + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_DBL = 24; + + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT8 = 24; + + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT16 = 24; + + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT32 = 24; + + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT64 = 24; + + public static final int SIZE_OF_ENVELOPE = 32; + + public static final int SIZE_OF_ENVELOPE2D = 48; + + public static final int SIZE_OF_LINE = 56; + + public static final int SIZE_OF_MULTI_PATH = 24; + + public static final int SIZE_OF_MULTI_PATH_IMPL = 112; + + public static final int SIZE_OF_MULTI_POINT = 24; + + public static final int SIZE_OF_MULTI_POINT_IMPL = 56; + + public static final int SIZE_OF_POINT = 24; + + public static final int SIZE_OF_POLYGON = 24; + + public static final int SIZE_OF_POLYLINE = 24; + + public static final int SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION = 24; + + public static final int SIZE_OF_OGC_LINE_STRING = 24; + + public static final int SIZE_OF_OGC_MULTI_LINE_STRING = 24; + + public static final int SIZE_OF_OGC_MULTI_POINT = 24; + + public static final int SIZE_OF_OGC_MULTI_POLYGON = 24; + + public static final int SIZE_OF_OGC_POINT = 24; + + public static final int SIZE_OF_OGC_POLYGON = 24; + + public static long sizeOfByteArray(int length) + { + return ARRAY_BYTE_BASE_OFFSET + (((long) ARRAY_BYTE_INDEX_SCALE) * length); + } + + public static long sizeOfShortArray(int length) + { + return ARRAY_SHORT_BASE_OFFSET + (((long) ARRAY_SHORT_INDEX_SCALE) * length); + } + + public static long sizeOfCharArray(int length) + { + return ARRAY_CHAR_BASE_OFFSET + (((long) ARRAY_CHAR_INDEX_SCALE) * length); + } + + public static long sizeOfIntArray(int length) + { + return ARRAY_INT_BASE_OFFSET + (((long) ARRAY_INT_INDEX_SCALE) * length); + } + + public static long sizeOfLongArray(int length) + { + return ARRAY_LONG_BASE_OFFSET + (((long) ARRAY_LONG_INDEX_SCALE) * length); + } + + public static long sizeOfFloatArray(int length) + { + return ARRAY_FLOAT_BASE_OFFSET + (((long) ARRAY_FLOAT_INDEX_SCALE) * length); + } + + public static long sizeOfDoubleArray(int length) + { + return ARRAY_DOUBLE_BASE_OFFSET + (((long) ARRAY_DOUBLE_INDEX_SCALE) * length); + } + + private SizeOf() + { + } +} diff --git a/src/main/java/com/esri/core/geometry/SpatialReference.java b/src/main/java/com/esri/core/geometry/SpatialReference.java index 44fe3912..22b0c74f 100644 --- a/src/main/java/com/esri/core/geometry/SpatialReference.java +++ b/src/main/java/com/esri/core/geometry/SpatialReference.java @@ -24,14 +24,11 @@ package com.esri.core.geometry; +import com.fasterxml.jackson.core.JsonParser; + import java.io.ObjectStreamException; import java.io.Serializable; -import com.esri.core.geometry.SpatialReference; -import com.esri.core.geometry.SpatialReferenceSerializer; -import com.esri.core.geometry.VertexDescription; -import com.fasterxml.jackson.core.JsonParser; - /** * A class that represents the spatial reference for the geometry. * This class provide tolerance value for the topological and relational operations. diff --git a/src/main/java/com/esri/core/geometry/SpatialReferenceImpl.java b/src/main/java/com/esri/core/geometry/SpatialReferenceImpl.java index 618eb6b8..25158369 100644 --- a/src/main/java/com/esri/core/geometry/SpatialReferenceImpl.java +++ b/src/main/java/com/esri/core/geometry/SpatialReferenceImpl.java @@ -25,20 +25,7 @@ package com.esri.core.geometry; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import java.util.concurrent.locks.ReentrantLock; -import java.lang.ref.*; - -import com.esri.core.geometry.Envelope2D; -import com.esri.core.geometry.GeoDist; -import com.esri.core.geometry.GeometryException; -import com.esri.core.geometry.PeDouble; -import com.esri.core.geometry.Point; -import com.esri.core.geometry.Polyline; -import com.esri.core.geometry.SpatialReference; -import com.esri.core.geometry.SpatialReferenceImpl; -import com.esri.core.geometry.VertexDescription.Semantics; class SpatialReferenceImpl extends SpatialReference { static final boolean no_projection_engine = true; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 3560333c..51e171e7 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -32,11 +32,14 @@ import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.GeoJsonExportFlags; import com.esri.core.geometry.OperatorExportToGeoJson; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION; + public class OGCConcreteGeometryCollection extends OGCGeometryCollection { public OGCConcreteGeometryCollection(List geoms, SpatialReference sr) { @@ -104,6 +107,18 @@ public String geometryType() { return "GeometryCollection"; } + @Override + public long estimateMemorySize() + { + long size = SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION; + if (geometries != null) { + for (OGCGeometry geometry : geometries) { + size += geometry.estimateMemorySize(); + } + } + return size; + } + @Override public String asText() { StringBuilder sb = new StringBuilder("GEOMETRYCOLLECTION "); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 7bcc17c8..4ad748be 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -24,12 +24,43 @@ package com.esri.core.geometry.ogc; +import com.esri.core.geometry.Envelope; +import com.esri.core.geometry.Envelope1D; +import com.esri.core.geometry.Geometry; +import com.esri.core.geometry.GeometryCursor; +import com.esri.core.geometry.GeometryCursorAppend; +import com.esri.core.geometry.GeometryEngine; +import com.esri.core.geometry.JsonParserReader; +import com.esri.core.geometry.MapGeometry; +import com.esri.core.geometry.MapOGCStructure; +import com.esri.core.geometry.MultiPoint; +import com.esri.core.geometry.NumberUtils; +import com.esri.core.geometry.OGCStructure; +import com.esri.core.geometry.Operator; +import com.esri.core.geometry.OperatorBuffer; +import com.esri.core.geometry.OperatorConvexHull; +import com.esri.core.geometry.OperatorExportToGeoJson; +import com.esri.core.geometry.OperatorExportToWkb; +import com.esri.core.geometry.OperatorFactoryLocal; +import com.esri.core.geometry.OperatorImportFromESRIShape; +import com.esri.core.geometry.OperatorImportFromGeoJson; +import com.esri.core.geometry.OperatorImportFromWkb; +import com.esri.core.geometry.OperatorImportFromWkt; +import com.esri.core.geometry.OperatorIntersection; +import com.esri.core.geometry.OperatorSimplify; +import com.esri.core.geometry.OperatorSimplifyOGC; +import com.esri.core.geometry.OperatorUnion; +import com.esri.core.geometry.Point; +import com.esri.core.geometry.Polygon; +import com.esri.core.geometry.Polyline; +import com.esri.core.geometry.SimpleGeometryCursor; +import com.esri.core.geometry.SpatialReference; +import com.esri.core.geometry.VertexDescription; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; -import com.esri.core.geometry.*; - /** * OGC Simple Feature Access specification v.1.2.1 * @@ -53,6 +84,17 @@ public int coordinateDimension() { abstract public String geometryType(); + /** + * Returns an estimate of this object size in bytes. + *

+ * This estimate doesn't include the size of the {@link SpatialReference} object + * because instances of {@link SpatialReference} are expected to be shared among + * geometry objects. + * + * @return Returns an estimate of this object size in bytes. + */ + public abstract long estimateMemorySize(); + public int SRID() { if (esriSR == null) return 0; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java index da51e2d9..464b9a7c 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java @@ -34,9 +34,13 @@ import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; + import java.nio.ByteBuffer; +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_LINE_STRING; + public class OGCLineString extends OGCCurve { + /** * The number of Points in this LineString. */ @@ -116,6 +120,12 @@ public String geometryType() { return "LineString"; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_LINE_STRING + (multiPath != null ? multiPath.estimateMemorySize() : 0); + } + @Override public OGCGeometry locateAlong(double mValue) { throw new UnsupportedOperationException(); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java index 37006a16..8fa020c8 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java @@ -36,10 +36,12 @@ import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; + import java.nio.ByteBuffer; -public class OGCMultiLineString extends OGCMultiCurve { +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_LINE_STRING; +public class OGCMultiLineString extends OGCMultiCurve { public OGCMultiLineString(Polyline poly, SpatialReference sr) { polyline = poly; esriSR = sr; @@ -75,6 +77,12 @@ public String geometryType() { return "MultiLineString"; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_MULTI_LINE_STRING + (polyline != null ? polyline.estimateMemorySize() : 0); + } + @Override public OGCGeometry boundary() { OperatorBoundary op = (OperatorBoundary) OperatorFactoryLocal diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java index 77258957..b25a948a 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java @@ -24,8 +24,6 @@ package com.esri.core.geometry.ogc; -import java.nio.ByteBuffer; - import com.esri.core.geometry.Geometry; import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.MultiPoint; @@ -37,6 +35,10 @@ import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; +import java.nio.ByteBuffer; + +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_POINT; + public class OGCMultiPoint extends OGCGeometryCollection { public int numGeometries() { return multiPoint.getPointCount(); @@ -66,6 +68,12 @@ public String geometryType() { return "MultiPoint"; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_MULTI_POINT + (multiPoint != null ? multiPoint.estimateMemorySize() : 0); + } + /** * * @param mp diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java index 944e88d5..bed0e114 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java @@ -36,8 +36,11 @@ import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; + import java.nio.ByteBuffer; +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_POLYGON; + public class OGCMultiPolygon extends OGCMultiSurface { public OGCMultiPolygon(Polygon src, SpatialReference sr) { @@ -89,6 +92,12 @@ public String geometryType() { return "MultiPolygon"; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_MULTI_POLYGON + (polygon != null ? polygon.estimateMemorySize() : 0); + } + @Override public OGCGeometry boundary() { Polyline polyline = new Polyline(); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java index 7e246a6e..9db01268 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java @@ -24,8 +24,6 @@ package com.esri.core.geometry.ogc; -import java.nio.ByteBuffer; - import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.MultiPoint; import com.esri.core.geometry.Operator; @@ -36,6 +34,10 @@ import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; +import java.nio.ByteBuffer; + +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_POINT; + public final class OGCPoint extends OGCGeometry { public OGCPoint(Point pt, SpatialReference sr) { point = pt; @@ -77,6 +79,12 @@ public String geometryType() { return "Point"; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_POINT + (point != null ? point.estimateMemorySize() : 0); + } + @Override public OGCGeometry boundary() { return new OGCMultiPoint(new MultiPoint(getEsriGeometry() diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java index b27e4e48..6f7a74f2 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java @@ -34,8 +34,11 @@ import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; + import java.nio.ByteBuffer; +import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_POLYGON; + public class OGCPolygon extends OGCSurface { public OGCPolygon(Polygon src, int exteriorRing, SpatialReference sr) { polygon = new Polygon(); @@ -109,6 +112,12 @@ public String geometryType() { return "Polygon"; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_POLYGON + (polygon != null ? polygon.estimateMemorySize() : 0); + } + @Override public OGCGeometry locateAlong(double mValue) { // TODO Auto-generated method stub diff --git a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java new file mode 100644 index 00000000..ba516b5f --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java @@ -0,0 +1,106 @@ +package com.esri.core.geometry; + +import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; +import com.esri.core.geometry.ogc.OGCGeometry; +import com.esri.core.geometry.ogc.OGCLineString; +import com.esri.core.geometry.ogc.OGCMultiLineString; +import com.esri.core.geometry.ogc.OGCMultiPoint; +import com.esri.core.geometry.ogc.OGCMultiPolygon; +import com.esri.core.geometry.ogc.OGCPoint; +import com.esri.core.geometry.ogc.OGCPolygon; +import org.junit.Test; +// ClassLayout is GPL with Classpath exception, see http://openjdk.java.net/legal/gplv2+ce.html +import org.openjdk.jol.info.ClassLayout; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TestEstimateMemorySize +{ + @Test + public void testInstanceSizes() + { + assertEquals(getInstanceSize(AttributeStreamOfFloat.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT); + assertEquals(getInstanceSize(AttributeStreamOfDbl.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_DBL); + assertEquals(getInstanceSize(AttributeStreamOfInt8.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT8); + assertEquals(getInstanceSize(AttributeStreamOfInt16.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT16); + assertEquals(getInstanceSize(AttributeStreamOfInt32.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32); + assertEquals(getInstanceSize(AttributeStreamOfInt64.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT64); + assertEquals(getInstanceSize(Envelope.class), SizeOf.SIZE_OF_ENVELOPE); + assertEquals(getInstanceSize(Envelope2D.class), SizeOf.SIZE_OF_ENVELOPE2D); + assertEquals(getInstanceSize(Line.class), SizeOf.SIZE_OF_LINE); + assertEquals(getInstanceSize(MultiPath.class), SizeOf.SIZE_OF_MULTI_PATH); + assertEquals(getInstanceSize(MultiPathImpl.class), SizeOf.SIZE_OF_MULTI_PATH_IMPL); + assertEquals(getInstanceSize(MultiPoint.class), SizeOf.SIZE_OF_MULTI_POINT); + assertEquals(getInstanceSize(MultiPointImpl.class), SizeOf.SIZE_OF_MULTI_POINT_IMPL); + assertEquals(getInstanceSize(Point.class), SizeOf.SIZE_OF_POINT); + assertEquals(getInstanceSize(Polygon.class), SizeOf.SIZE_OF_POLYGON); + assertEquals(getInstanceSize(Polyline.class), SizeOf.SIZE_OF_POLYLINE); + assertEquals(getInstanceSize(OGCConcreteGeometryCollection.class), SizeOf.SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION); + assertEquals(getInstanceSize(OGCLineString.class), SizeOf.SIZE_OF_OGC_LINE_STRING); + assertEquals(getInstanceSize(OGCMultiLineString.class), SizeOf.SIZE_OF_OGC_MULTI_LINE_STRING); + assertEquals(getInstanceSize(OGCMultiPoint.class), SizeOf.SIZE_OF_OGC_MULTI_POINT); + assertEquals(getInstanceSize(OGCMultiPolygon.class), SizeOf.SIZE_OF_OGC_MULTI_POLYGON); + assertEquals(getInstanceSize(OGCPoint.class), SizeOf.SIZE_OF_OGC_POINT); + assertEquals(getInstanceSize(OGCPolygon.class), SizeOf.SIZE_OF_OGC_POLYGON); + } + + private static int getInstanceSize(Class clazz) + { + return ClassLayout.parseClass(clazz).instanceSize(); + } + + @Test + public void testPoint() + { + testGeometry(parseWkt("POINT (1 2)")); + } + + @Test + public void testMultiPoint() + { + testGeometry(parseWkt("MULTIPOINT (0 0, 1 1, 2 3)")); + } + + @Test + public void testLineString() + { + testGeometry(parseWkt("LINESTRING (0 1, 2 3, 4 5)")); + } + + @Test + public void testMultiLineString() + { + testGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); + } + + @Test + public void testPolygon() + { + testGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); + } + + @Test + public void testMultiPolygon() + { + testGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))")); + } + + @Test + public void testGeometryCollection() + { + testGeometry(parseWkt("GEOMETRYCOLLECTION (POINT(4 6), LINESTRING(4 6,7 10))")); + } + + private void testGeometry(OGCGeometry geometry) + { + assertTrue(geometry.estimateMemorySize() > 0); + } + + private static OGCGeometry parseWkt(String wkt) + { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + geometry.setSpatialReference(null); + return geometry; + } +} From 9ba95a6b212c30fe8e0ed96bcb827414e7ddbbcb Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Mon, 5 Mar 2018 15:31:39 -0800 Subject: [PATCH 09/75] Stolstov/update jackson (#158) * fixed some errors in javadoc and updated jol to 0.9 * updated jackson to 2.9.4 * remove jars from DepFiles --- DepFiles/public/jackson-core-2.6.2.jar | Bin 258824 -> 0 bytes DepFiles/unittest/junit-4.12.jar | Bin 314932 -> 0 bytes build.xml | 8 +- pom.xml | 8 +- .../esri/core/geometry/CombineOperator.java | 3 +- .../java/com/esri/core/geometry/Envelope.java | 46 +++--- .../com/esri/core/geometry/Envelope1D.java | 4 +- .../com/esri/core/geometry/Envelope2D.java | 42 ++++- .../java/com/esri/core/geometry/Geometry.java | 99 +++++++----- .../esri/core/geometry/GeometryEngine.java | 8 +- .../com/esri/core/geometry/MapGeometry.java | 20 ++- .../geometry/OperatorDensifyByLength.java | 4 +- .../geometry/OperatorImportFromGeoJson.java | 4 +- .../core/geometry/OperatorIntersection.java | 8 +- .../esri/core/geometry/OperatorOffset.java | 4 +- .../java/com/esri/core/geometry/Point.java | 38 ++--- .../java/com/esri/core/geometry/Point2D.java | 4 +- .../java/com/esri/core/geometry/Polygon.java | 74 ++++----- .../java/com/esri/core/geometry/Polyline.java | 2 +- .../java/com/esri/core/geometry/SizeOf.java | 106 ++++++------- .../esri/core/geometry/SpatialReference.java | 2 +- .../esri/core/geometry/ogc/OGCGeometry.java | 2 +- .../core/geometry/TestEstimateMemorySize.java | 145 ++++++++---------- 23 files changed, 342 insertions(+), 289 deletions(-) delete mode 100644 DepFiles/public/jackson-core-2.6.2.jar delete mode 100644 DepFiles/unittest/junit-4.12.jar diff --git a/DepFiles/public/jackson-core-2.6.2.jar b/DepFiles/public/jackson-core-2.6.2.jar deleted file mode 100644 index a7d87f067340ac378230a8ccf8b4dfc9512a94c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 258824 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%0ANnsM4|)f9WP^dq=- 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

F9Ck<@RiJoLX=RjXyZyA$)Ipeh4?TNP+Eozyr@& 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

SN z?n~>Z6xraY8rwcL-E@>)hI5p-G1B59|s& z&v|H;i)OfySgog=RHZVEo8)!rPlEGI3|>&x9^0Wtq{D4rUeab=#>cIjQ!Md?dc>Lf z*rH=%q3dX(w;u`xl3_X=^!W)%xeXgB|?GK|X`EtGco&eps;$0UX&aEZ0Jslr(-kIYa=1)@Z!s&ju zH*cax@K`o2;k;ya(l*ilLeXJ|(uJIeAgSVcZzVOdVRPwSrJ#RDskA-VN7HdsZjveG zaOG{H66vvG=`s{#cw&VR*UZQlP;tc3zs7n9f4qk=<@jhiGDx%Bcs^~O9ux#R_@Eb~~j31#@ zP*`j8q1JJ~2=k?(5Mr!_;Y;B;Pbz0};Y&$!bC&sTSu?ylCysHdn#(LP%r+9 z)uQAdIZSYP^A54)AH{}<`OJF=x#fZpQ+?Y}4kWzh1*9%vy^-~U99OEsiT*fu|L8)3 zMnzA2b|X+tlDwK>7IJ}V)Hx|7-qFm$L)1OhyL@dqOoRCNRsRldvIQ^=n^Iv%Fo|QQ zXg{#5WsjUWB3Kl!2vqp&}DGm5sO7vDg^Cb;aox?qye5%z#-V0O6*O-MgjPNVg!|Jh8=qIbbR zp+Js`Z;HNHzRLK586J;s8^1t)-i7xq=pj?RjpxOGm7SDzlY5?2hyQ-VAr|}2$1M8R zh*;W22Y=HWB>m(8X#LTno%tpgeEVfs`cGab^DVwn@`w6r=9{YN{2LkJG&_{%t$PsV zEqM>+Q|mVKEAvI+TNiikPfXEQ{=+HXxUo<7Mddd!^8+Z86d$P^V*sw5xQ4O1W1GSF zYmi(}1bgd*IR#F{fOt*Jv3on*afv;l@@Q|kY@K9AIA{Qd&Y_`0R$n+R$NFHng=3C5 z+CAhl#+b7MFOStO*=-CoPE!hLP-)FBSUA-Q?;tX>raFf+I!K({uh~W9b4bHEk-s~H zeT?(k=siu9E5(8%o(~Dj* zSja4PTm|E`v^r7Eodr5((SDMk@kFpZ0Eroj!D32Wtu?!;3X^EPjD-)2dhUBDEyH2jA5`TLY%bh+ zqcoIg6l*pxz7emE5DvZPw#Noqli++tYQr+W8ASjf<0E=00YUn?0MugaVS~chVAdhV z3_I9ivLQ%q+lWxj_0Bog;;RxD;UciaA9_1KKm^Ijn-E40QZ_Hb2g#}$c%73xZ*3V% z?U{8W?NfI~BGf#Z8zA5eTa1~DiWTvbI~t)x?=HzST8ruf>Sa1>mH{-$S8s~;Vki@+ zEUf!icw0Eg&n)>y^q*wg=bZ|(0ja$OX_J%+KDNia*YA4o1snIj`|6kMz_Cyau;XX8 zD22-a;H{!aL70Q=y_5of0cc8*7V5?mJsP4^^h~CEnnvhA%zB4*z^}<6?GA&C2)79E zEr@<7b^+}&AZFF0B&n<&{H-lJUcsD+W%=L4de}?F_UOg|D7u7}lQFJSL5`BL1ck&j zrBaLcS-Rb3K9q>t&GA9Bs_QF<&jOY)?Q4~Aktv!HTE^dxAy{}h=)LZiXB~s{b`+_D zpj@w`fgcBgjZNJ+p;LpX;8|b;Io_ujvQ^+z0t=ALuV=p*TyF^Wu~fbC0gp z!vs(%-tB%ICU+c+g+oIWiVBc{wbit`^yK_dOI?f5VfnnSWyxW{m65Pj8i!xhe4bk_ z$nv_;FK+}I;lb{M?7az+Vq)ayJ3zHzB@+*~L|9)s#`U1F&$b{J4tY+nRSi-NxlpoI z4I}SEDC4ksrXJc$LMWkLx%G$IUSVpe1MJh%ZH96+wGU0xr3M#YLY3PCZsM~S6ED_; zxP;~9nj9kUMeW-$AG8^&T#EB_G7^yA`=QuiW*}98G~9(O`?*MMN-KC0h+7NhkA>;}g!mk>9?5n*0nR%drZbtyhsuls z_0edSeK$#xqrO=kahZ&$w0aOx44-ZE#~>hu5Q(#-Yq}U=IhAWmQgWy|Id|*~z{LsAn&3b}qY$B>`0}G8 zpa|K*(hZmCXON}GRw9fA&&AL*@2L;B@SI;$!pb_3YpSu}5cY5PGJIITH^bmLdcRQh zozoiRkJbWOcHV+-!P-maKP0wr-MHgBG-Q6RYDf4sqM5Pdb0+8w=2kg6fdF6cBWM#F z<3vG48z|mSi1f&&aosKD zTP%s-l_U*CgoMD7#-MR3hyu!S_Z6B-!9)<$C@{LL#)g)59gUZGKcrCY4k9466_s%P z`nI>VQjbv%ZZlOm6O^s3;=hhxJ%y(dTE$gGgn?gi@WlK*B(kV)KfgRiiPARjaNSZy zwxZzyt}gY#$5JI;0gmF$5rJ^`{{Rnq`i9Fna%(`DZnS=glh;hN{l%<(V%rSy(v>$>dyyO zF5=~j03uT}#I>9i*ga!rG!s)cT0r~0GBaMIDFaJdXYJBOd4da5sZmJy1Ns{>_p}P} zrQfO~6ld#&USF4NvJj44M;S_hpiwaiP4E=h41{0=Lj=H?4_4e@-GUR819o8| z%GW~E4(Xmd=$}%`s_f}M5RUi{Qu<@fqI$%gV24sEaz?n3>L(ovy1nQ0exj$N)bwSD zd(sSW92sZWq3=r8V=kwYt?0`RgC0qLEbEg-grPt1TUr|2F+0($+MADRqe^TamJK!%UvNlVMtkn@pL+pR!eB%&!2Rf8;$ zby}ggR!D(*5S~d%<1{J84ec-mQ?$EDCBSOMAgmMkQChJ5RXd4e$Wo9EXd`C`N3lZab#;vewMkeLP2-D;8V+!INIMEgsnz5#+69_3{D4 zg`7CgEvFHInYNrpO1@_&5GBK#&Ou)8gZJ5L9nME+44EE-lkWcRGg4+(4s%$>d$NHU zMOM&9M8BE+Yj_U{+hCBMnIT3}pazd_82Sbf-2`hnaeXIddlxDxk2Jt7blpgz1w8(C zp?x}mLRciD_A`e~)Vxxj@A}sfQqW!=$j7%89*#C)cU}o+nRXzh3YVgR-Wx!3M$6B5 zB=}9~Ix`XoQQSj0vt<|f-lGPk$>q;@L(ET@0X9ECP16|SqC2Co@8K5G?Fd z7tpHX?HqhY{A(#S@KG{q8#tEg2Z9gEFtdbW^*TkOXO-`Y5EJq!<{SOZk7AMN^brd( z34$6zCKg@uUxB+=CXPpXlq22YQ%CP7CSPzGN53%5zx@3M#8UKsOV@pY-A~FnguTi+ zCNPK}=_&etLz|^-E5^LQC#P=jL*G+4CS{LmJQ>x$hO-Ugh$(5i!umIGt8hT9Z=fU0 z1Km?xBmFJJd(o<zUD8X_+*~g)>ZuX6s@N2lK-Z#n{U6-qfK+n&KE|ETi`;;4y6q^(+1x zW9Jy03DC6b-HkT3ZQHhO+j(N!wrwXH+u7K*Z97l+?fZUp&d*b)s;Bz@Ox4s(ci-2I z`j_MnajBNzWRnu(jFfPOXh!-HE~^?BRyCdm;At>J&918PZ5QbeeNBCXeNM_1=Y++i z3e-GfDnnKORDaEjURjsSW{nOBB6_4vP2e=D+bvX$lC-!+*sI%HaZ+qg5C)0JuDNqK zSPpl0UV+} zxyYxhmGj~~6=OV3=hh<1S9KcBL01yt@B_!PP#BN?zlx3BaMhpK)#ygvnI-gT;~CtX z%;X+eUZo^(>p*(e3iKPgv-3WQADePEi@G~zFz>Zo_Ev$FSp;rL^Bq~=@S{$k$7dG2 zA=DZ`3-cIp2*9uTs)$olSt4FkqhMA{L% ztk~>YPIY~mVY16(Z7W*--D;S*4QTtae{gOzqHgO|17@lbdRoyA!~qqvRa6N^IaD40 zjzj;C)}aO~(M%=kKou9`u+^=eFlMCb_#x@`qg1iq%Iktis3Yv&zI+%Q1f#}pV!oa- z#9n+c@A;o5Vsyq;=X4IOQT)(b`l+@t>E2nryACAT@<`iN+ah1a$`b&o*{joid7cb_ z2T@z!+(NkQ?_#F>RZY+fJJS-f?+iy@9~I?^>Pjy8?%4&P{fea!18YUjgVimFtOS9n zog=rU6{Q`R7y!{OM^3<*4ERrO3do7Uxxo3A@5DIBg+Ea3!ZFwJ1GqetZlN0}biwqi zaDs87BhdepDp`9azh5hEXxXK_rA9o*1!TI;mLz9eglkKHpa~JXI!m&w)#FCJWTALw z=~s)VP)Kj!T{u&3VOl^ZOgES@Ku%ir;i^FiYuK~*V-<+Ovm?rvW3TaJKRuZBxNx{EgeTh`)6fd5Z~&Ji7ohMRGu3;eOhOQJ<2iN zzk5sab6S~Xtc>xmXK3`x%V=Y65y2e~<_$Ec0KFoL4;bn49~4pj0m|iz@`i1J>L)Ta zEkBZ?Pvq(5?b6?GvE);F97DQNM13M5X(Wl}UZ%N1Yo*bM=RUa#`cA=Ag-pUX11MAO zcJFr0y)U@$8;|;9Pkwdpw{71+TfO-8@6dBWEYCmtrgtO(_=QPNjI!o@f_@juP^jO7 z?ic!?%y~)p-T`OJX@}7I3G^RfyGMY)G`qUtH#BqYorF?fBK}v*tm@CUg*ULyDi9PV zxP8fSg1irW^_vXY7uFH;n8nK34^Jr9 zthRw{@%xhuUEUYxoRh?z;(uQO&z=+r-Vc6@jtWzo%Z7MacPlr6hMYh-S8|i}oVlIr zzyeown8qLs%QC~NE!d>X>vW?Rk@_v@5?8y)=J)*m>nJR45Lj0-xz_hR9d2m!_4eFb zrXn4ZH_>yE@i%Upn$tu4nTz-D;)}{8Nh% zbS^V(eae8`%y?H-h4ik9M6M8@_VXL~>q=6=_1V!2CU&z}CC1~tH)Hut3Uu-`!uW|; z?ip%jEvM4st3GcPn(pw4J#P>x;Rk>cb%qw}Nh|3KD)Gk@>xJ#P@=EpuknDtyJxeuA ztESu54&!*iTJFIlubGQUy0wvSg(yb16akYGZ2@cNAHDkauur6J1*cIhAJ<82pK{d| z^r4Mo)BKJ{i;n(Yd~3Y)N@Pb(S@0+9oa6zmq&cK+UpCV;Z-C<7ND?ovL_05~&1aJD z=VDhBmrZ>)pAKE@>KMt!Y}#96qB!yg_=7y2yxt*A_%C!p!OCVXgKTEc9I{L;JQ-bl z#;l=Jp?m%~`+M*CJ}&1LdLmq%K<3K{hZY~w>Bib&uxC#lYkhIF9z^xk)_p54W=$a5 zrpb<=nlJfveOBE<546{%7v-z<2;kZ0HOYs6yU|VIM@P`FSvotRuU~=JYOeqm7heh4 zQT7gHr(E%1zs@E284mZLEC%VzXSLe-_*vi&s^CLEAuNap_ykV`pWs)>uXOL?HRg-f z3V6qu^Md{8!`DZ4zidXL@60*ErAFj ztncKxvSlvU4*poHr}5w|n1Ssek$1!5)i{H?Pws{jamwM#A(nT>hJ!Nu#Lp&ndFv4Cesbgt-0pPBV9j;wzW9-R#6HhQ@7apOnEi2{5!QDH2+KyD1{=|`6=7=58?66Zt zO0$=)Vg~tw-k|9d!g24Paey!6!&Tat%MQV9^oNp>H_Am4&oVXd z@`P3+U#ILcKA)>9yVz@W?5(yB%}4GITCW{quOFH3&c7g3{SHz2q^o$VEk1vdSi(=N z{J!&3U!wfrr*zx{plp)Te(@}%|CT7`Aef`0)-F1`F`s(fgf3iDxx0~NZ0!o~kc(Vw zqNVMPaz?pvF20Gjj%uTie8Ap=&SvkIlzNjJ&LL+LdD*Z+-293*c>)tHrKiMwhvL1o zlhE5SO8(>}TjfU>{FbR$@ug|<6KwbSz2pi#T@p6)VA-}=zFi_VEU%)Nk`5y?x?iE{j-K3xL>udRan%pD-Wcn@g|Urf`U24wQkjiF(|_o;|p(U=u? z{Xw6RvEGI(+I~boG=rfiT_VmJB-^d+iFlo5hs=8;JK*mj`Z%RVoM%@} z?>Q?>vI{-Erba#RZX6=n!BO1jmXvv+MR@QrHLABO;8<#v$iDuAZ~~+n677j^n{O4_ zyws*@d94&lx>2d$Qm1u&w;I&b4{{%0p~!uyMxlR`L-)JSA>4k-IUCyNLm@h$V!)!g zR?AbJV+@-;HZjl8>ALx(I`(;KqzZK(0lp?XmgP$PyR3X^1h14y?x;t7xW0uvv<*xG zonr6meD)pCOXQt*^qLwQlD-$B(}?w1Vh%iaMC-iK#ixX|F>*Vj0^0WE6^dY=j<2ZibarW~c^7JiT{gQ4_k-hP>vUP)Cb}vy zK^fn#^G+PT9nXdW0OF%=m~9XC+>9GCIFQYt{Ko8G0W|Q}PIdZWC+viG7LUM1n2K9b z|NHN9D&9RI?Pm8#zg{^?^AL9}o&#HX5<&hSd8EF1{Wnk}J+a17=9E-i_>HGEZ$GNS z?zVzf$4H{e?f$ru-SL*G+;)A0DFq_rjlmy=k-Gx_iz)prGC0g3_~VCP$o~t_@c)CI zR{iIN{U0*J|3y##FQuc~8`2#`746#3&L&5WoFo7)m;~WDJ{UK!ft*l);U`JNXkmdQ z7XmCK87>>U%BK3JsHh6dIR}@me^C(k^*h%Ahi&6bTP!mbk;lnqWsM5Ep%?SbosY^= zx67aN?C+14Y^Sto>3835=)V@gN_@A7DM$-+_WM0DzRgQ??Lk`a<`nqW`#rXr&Yaqo zyS-RYhcb(og(Y3@wyda^*Rxyb9xr-)-!b;4nb-tL3+Em64M z%}MZa_j@Z5`;2!S`k$e-u6KKobbM#X@^?T>-xcPFea$-@{i~M22j9a;bnkspzTUwU z`iCWI?mk9RP53-f6A$7a=L2e!QH29mlJs-4Fkgst&;4OFFYy3>_$$+@` zD+oT{@c=o^Y8l@hCOY5A0KU(@y!RI~-~(OkqE_bv8~^JX`P(4l>kL`{bui8QfjaLs zQ`>jorS~byFXHC)e8>A09=-P^3SR<}>T5KN*Y_@Ibs{Ve^TLP53Suk%R+^9$pQSR1 zYbzyGKXbk?$bE?1=MgjGFGR0C*|@(vS;8CB8hIzs1Zt)1-fRB%&$S$Q-dBV}VXmFi zF}us7G|UEe2T?Oe#wa_JcT@cOtlGExr48>C;f^ui&0>E3gfSP8Hd_LGaEC2}UK}DP zV5cxJenj>jSm|FIdS}Q1U<#}iyEjC^7ke;-!5_8~5D(LjO$y=T+@_C96n{Si?O{%U zPkLooqc0n+@J=5NBdVc(oUVSV!e=7%+ZpBRk7rLA1F#XlC0)%v~O|bEq?_0 zE5dam@f>&r-G07kvEZE zH2!m1hwmGe)@vij`#^JzL3AIY$7#OaW0#I$s`>-~V%7 zi77r+8kMnEYA;POzbS+^3m^s%{}P7R=KZPf!+~N6_=k(vS{B*OKXrFOn;nfdi5vgT zTJgJDiL1PabtKV=mQy|-_>H|B6*YmzxE-K@#x>Ob^i*w_$V!?^g_cWrKm#v+%w=Mu zIeq1M2-nQNfMKO|?VW=n=YqX{1CN~1yjftnn6lEuBGS){)gR+B$sS-(a{@+UEWF^D z1uuK)huG2h(0rEM5hZf`|ls;yCL`O$SeITDX6$`td(g`eJ-GnHds?e=psF}M%Zn@kR>p4v- z21g9wYmoU_z2Ly|x(+@}`Sy^j@23gmi)p~`MoJ*^4H|#ZmX|L9LYogfOw(uir z70K|)pek9zPzg<|B_T(vX*7jwRBl?Lx3z$3M#wLMv%1(<0JPax-Q&t8L?}*uPC$*+ zv|NDR!+m=s*3h9qLMG$%iErs?EHAD>PP9>DOe|A+X;EWqX`^2E(P1b3{a7p4mWN|c zfGB)+U1=~WA^k(6i7PtnnhRq=N=Z7)WaZJe!QZ%TkS-W>-FAS*`ZYp3O73&E05&jK|syw#P%@+gKl%skl zSz+f82K6?ySC^#Db5GALyi9b5F&q8tB1Q+hMaqTQ_2@$Qo8=zGwCArwlLmTAlnc3Q z+VcX1dkA?y_(N|9@UttHoVJ~X0AQ*s5NhfpK$k}St05qYd@KpX9or7fq(}!-0HOzO zlx)pa-up#=9@+WX7V|C$I$MB66?7|t)T?B^J|t$6r>$J|)k_M}<9s3T zAqwr71`u@!dWd;H>AxuuINJDX&n6k!eV^^WNl_8z<^*P`1~e7OrCtHMWtO(blb-$l zkyn?svGbSD_aC8Z63n|zL2uB)B03aJ))2BstwcybXKZ!~-AsVx!H^Umsl2^Q#6WN)^Rk(^}^F4enS>n2zg73*L^ZVdj)C~ncJQ{bLvtz3ep(3ayFp4lF znn}$1buZwSY(vyBzsI?g4%jTYZ3eSRvauFcKsusGzjN$z@pDQycq%6*tKM?yDvg8yqDLlH0Dtr7EPZ-D;Q{@;sHQZ4DFUgY6dVW2EW7~tBR z)OTo7S75LZ>+;|n;_&PzkYEdW#PN<$5i=fsLj0FwCj)IeF@YOY|Ak^b2Z0}LxoY^; zH-?Lq!>^6j(5SeHo!c0c8tFYQE*;Uh2V9D`I`lt<5?$%j&0}3))oRfG<1-o=#m~hQ_sGsSD#7( zJ(Ij$ZGBEP+@56#?}Uy9;yP9r z9uzP316?nFWZ%aMz3rDGQ;%7nQIw^+%+V+~5>axL-iW0IC}nUJeJK?_zYUhdl_T^D zhKG;W!JfN<-Rj0bN(*?XGb^=bCji2TH`PeeJwg>Pdl~iZrn@j+S}{x{FH{Q4B5u;< zeoahdlqD&oq7PDltfCW)my94l^-LOW^N$%%l6aJ zONBGe8qY8rp34|<;U5BYBPfG{96mDV0u9YQH^bfD%N02Jv-D}4!_6A9*2*>_Inn8G z)4_vdKYGcy3~5WVC3&_|b&t&J{!i={4lKB1j-nvJ;(7Irru0^vlg@blqIVYc)aqss z)`@^8{$%4Irs?XQvXl$spMnafLVHAb`{c}X(RYwm{gfoq#OR1%gQX7Dy)!EW8R6%0 zCy7Gr64?YaAwgJ?Q2c;kD}e+7`gC+FMdEQiJd2|3{=U>u^0|x&m?75AVm@6=Jygej z#TQd6|5cC105A599Zd9v*DwfykE25cfXf0U-ozUKD{~8ey=Ub4QgJ6~XzS)LflJ(U z(jd=b5O*4{?y}aR6~A!cA?{|`I{fO~ByQ;+OlE3!F87y>=4Y0S6z+|R>$xQz4VmJM z?ak7_xVc#_a+Z-?QexLvY^{k*m6m}8vX%>jFpjd0LT6u1$h;_NkFjwj%7abMYyXAL zOZhFX3o{nBFrw$h4I*Cyu{3xSnsoi)KX#_fWofC&swgQ**fkmIdMa$>dW7a=vE}HN zxhoh}7LiJG*itKqHPjwLS!?io-=?}MYe}t<#<4S}dJFTL*4zm2OP&>E zm0m+T=Ld%6nR;<{vkTLU9qxci+1=?CB-KO!Q8q&zsdlEu!z1R=Qc9!MF{-Lss@w_K z@OUM#L=^RLyU>a%C3&WrraD7cvXnZ5yR6b#4mIGQCdHYltH8y#O%=9;T1d9w2&Ykr zm%f}TlfN+;@9Ju{V?qM=$lE%e%@O^NhpTZ6FMq}+q?2fPSz2=nk6{9iZfJBV+4C=B z>yAXdMy93~L(`4%R|5;j4I=Zv_CYxU-I6Q_<9Y@Klmad(I=tO!2Ya0TB9QZ>OFPHwwiqGDB^OHRB<<9r#&3*I2nC{^LKd|}q zo2I93@+t1`NGlRvKpx=3nVRuN5VVE(47^f`(}_C~T|u<9>Plh_M%pe+u2#;+zo%r+ zhYO7;BDT8Dp5<3K0j$kw#L{UL>*&xKMhr8i7xIO1hsv@gGv*I^Kd27VjwSYyy`BYnf=g&GwuO_u|mLKqm_vA+}=w zq^Y1l)$((@Xw0gxivL&-V8oIg{gK9np(}==E9c$*%cl+!#DO$) z&nkL^H9Zo*2)$y+Sfl`9j z8+`fq*Q=32!>yYj0q1X57ka1z{#$u$v1osVeGJf`XX+(n4Si+R?NaC8tFSn@pgn)n zba`lQV!U2!=N%JujZNGFeDiPke`p-;g3wPm!ykO43o`ca#nq zqm3bQV~L&QNz$3dab#CLw5lANq9Iyoh~6BBa-@Vklp{KnT1JATD~z=#ZI9LdJ+=XP zqL0)8k6e&TK*cLe;+ZDVe|oa^yYtZterH#^L5R!eLO;?s${wqyh+1~8k{c=Mxv=vz zw^DA*1JaD?tJ*vDuU|5-$8FLr)wpL1@4F$%sq`ZV>zFh!^5rvBkRZtw z5J*LKP6?j53!W1C@aOuFD1C#xs7FWNH@`=JugiGtm6h0}XW=1%;USlavvln&U6U;Z z1|UoqyPISk3&}jElc7SIBu+VI&yjLz!1I;g zou4_0er^TlUFL=3Bn0!!$x3D$_b#V!>?E{dHza2(jadp_my96s%$FF!2N+4a@%s4l z_D^;-{oIH^lu5tBc>L|T$|JR>yj_GrLm9_`Vux>n}HzAC$@W;Rq141Qh48OPWC3igIuxAY8wSA1DJI64`r@=4&Y*7xzs@*q6xt79h)?fWN zG%~yZ0B?knWjJy?ft*M~xgb2EP^d;|Utw&zV%(h(Cs`C~I+2`E1PA6wxR{U&>2Z`< zHh~%;iPkKYmP4q;fQJ!l4HCdUM??JjNoA8UOKy;j`wrJ3f`-s{KF3UFVq`@4GlhiY87>V(BrChI% z#uPVUp5Q0MzE0pfkJ6cU;JXmgGtps`G=rRu++lYh*8y1|P)Y?EEG-J)5ZMN2v+rq* zz-~~~hPV=$#cQv3((jRT@SQ}dv}TXCz%6hli83AB{n)n%`pwekUux!2LGQjdcecWB z->Uw}WrGAP_&A~D-3b_roJitaxgT=m1e_7h&NonKbN@<@Ob}w&68$>2J>Pgi(CN)b zaK}&B^EHXkFX(mu0Wv5&I3G6VXG1>fs*tx6aWGV*L4;St_uWP=!q$nvs=RAH{FMJw z&^%nme>>)alRXm zXastLM0do6!HINQJ<{_oL5!}5l6{+|a5o+mOBV+VQXDAJF|g$EjpzBV1^ zlvhMq%dfNB1N%FUkI9qYw+g}nciR02ZX}yw!6V|qBlrpwe8Zr3kYr8#^TC`k_ zuI8EmIF?9XnuupzIFKY)x{EJniZA#;C3gvxjDi>Kn^+iP#KuP?@QBxLvaI0#%n2C*4&s(VSRY2|#I##~3Y3!{(n^36{>p<*uc9k8pcu}C0d zgqZoMsV(THW;q2;<|r*}#SztIr{OYPl-Id)V-6}VAt}B35-}x`yA!CG6X+Tl6wHi^ zFNLX|hfp$tkk;UtP5er>X^_ZKizx5>Vg_YL7^J@QNC+VcYkzYnBQWb8nRDgJ7AA-O zuIdW0WF(gSG}j2+y)un3Q6%vl{1F1G{mIW#NI)YJ88kEkhqmx#PH@;KPjD!dmdrW9 zO$EcC3NviNkt6f~B^ygfrxI@;f7dFN z9dSjrBFaHB#ir&w(c5z_zZQ6Z-~pYGZaZ_SDK(*tGAF>s`|xLv4((|1UyP=eHG z-FIk&M!wks0h?MllUjH%p+H?v3ld@nM7j_>%#lil6IQa}w`Btc?~!vHOSg`tC+9rL z6}{|CIg6rr9s;cQKGoYVdC#lKX}!$uCWR9`+{K*mVcd17^H##S>zf7qUA^3#W@jn2 zXB!TFet>lW-lFpKCisHfZFe_+xn1Qtg{azdwYQt1*T@D?Q$;PV_{|=hY>+oTlKjl{ z_zgCz^0~7y;97<^=-QqJ@?0u&e(VbOg1cTz#6nOle(5;gDI<*UUIQla!BR&%hR1^^ zbb^$ns#EaQ|ga9s7uxw>AtnETGHOnNm3uiwn^m|NpAp!Cd(@_kJ>$CTcb z(<`3f<)WDvci;P5#5i>7Q)uc4rgF6rmZz7{G2KW(ap^ z3KcWVUIM-U{%TdYk9Cf6G1^xxp30Mw&kK8Scy`!3BapM{pK@;vFPf#JkcpzegX!9J zdZfgH=y|SZf+#)$G*Xd2*z$vuXXk{w_-8&dx0r3f0Nu(2J(VxnKwTJ9hk3c1Xy}e< z>519i)qMc`w0EW$zcHSKGR`#*%w)52c)~94Ny;sio>3ro9U+uh)s@i&A~{l}A^WN$ z`Klwz){60a;3__P_B${uK8Q^wvm3T-210p2qm5N_C~k*(dT?hRvSpLs{H<=l?TvRk z;PZ&%KFN`@bc8=*zn~Ogn7$OeajWm$AwB%0BfN3@ZMkndr=7s*zmZ}JW12zp>IZ(~ z_Q~zgl=b^kuvBJEdb<)j)hv=Gti(=%wllf1s|hnKjUCm*JZWYvHbXpvCI=Nb}xxCR;EaqcUP66(ypNrVLc~qs7U%og?FD)Q@887LrGJpsq*EU zdCXDl9l1U62bLRNeIbkyz&%cO`aEbU7}|r|2p!`pqZD#^#SvQ33MRZInRFbS$9{m+KM?EC^7ql+D{s>A zj}YI-(FvCcAb+YvpIByp$wj|(OqQ#(_J{YSV)PG|thmI7F&a@3(j;`EOA>KTHwla83hz^|K04D)N^>tW z+DLVcHjm|@ z@}1uSbQmE-`X~q(aFAYL`#c8>>Popvhvup$l6Sa9`FP}~eV!V2EpeM+CTjsKvIhBN zjA{!E!VA1aUdW4b39Je|2eJcUk$Vt=Y9NQ@lT^w36r^$@zyBqSu z5jD|l{)(6omxD@)333G*m=$Ij;$od`dC}zY(S(T(m}3}Zm=}`6M-cH2iRs?A?Lu(60t-Cu+WX}*%a&Ai5no3qN?Nr#&Pa=SF3%}%r0+$$iCrPPw86iP)87Q@9O zE+0nf!5cVfTo()tLP#gS?*%t3b;Cujh@2Pb2+dt6!2xN8$*!E7RkG<7x@QSKsnqW@ zil-^v8~GUM3Ph#ciTsC?8K_4kOWcOkWXooWe|+M>Q5o=o+uF5k@3!3B zLzzxq`Rc?=p?f~#S{Gia)Xe1V!5mh3unxW$Z7_cM>&l3u^%IyHyB7b-fS z_5kY&cC)ZMqI#XXP1$P&*Pmrhf=acdE~Om7v`xHX?OLl@cT!E{aSzShVI+4+dNr!R zsLs&Dm|ifu3xc;x+T;V8ZlrvN`wP$=WHuOd3&?$Ox0|jd5`FBLD@3_X;Sxow zjbWN?KOTEiwOOs^+E_iVyHBs7Wo2a@bvdD}1m?2@O0OYJ-| zQB$VZ9JiJt8=j^0KN@dSS=*iNr} z8G-Tnfp!L>SOzbY#0P5Q$+vt4R&#JE>w7HBxWXt#jzejMk!lv<;kBCvf~3T=dis$i zVE(?I11CDdM0W&ymiw85NrtDm<%|~Kz&0bUj&j)o(5%-4+i;NEoYlt%6UP5n|Aw(- zLtFDCe7iVc)Zm8#zReY{iNI$Jb2VUL5Pn!e7Vw9V<|5ROB~NNwG>jQvi_R7*8e)Ch zuk6ij$<=VN`mG%DxKTP|Gp#CVRv>Lq>?6Mdv4F`j@Q0nY{M6^q2d*Eh`)NW8=JBu0 zbHen(rF{Ps{l*d>oEU#*hERNR#Xl-+_0y${_0jYPNM@8$$CA2&LfpKNzW0}le*7bE zc;pUAk@~cVzg1b2`YaoQ(RM>gda^1#ft{A%%m1Yx{NV#Bc1CVc=vzo`A?rw*cPKHf zJ_jt5%*_|&wGxQ_rCPXtrpPS$GncB3VP?%vR+7&(sfu&{t#8C^TX_KotirZtgNomgH!$ncG;--OrDk!t*L zL7^Zo;NX$jA+YD?#A74E@{C|m4eT%IET4NU9j*P00d=^ zTt0E_*QtwggWa_|b1s_tK&`%Ta$Bm-$rFYIuUB~w=D-s+qgL-&Ot3GEbLr}7QH_=H zCgeCHo#1ddSS~6+5|Kf9&@$oPuR!#;uemLysV%0dEvKn1sHrWf$%35rnuzwAuNX}c z1UCR}q;p~OXd3ULxofolUc9X1%zYa)iM;EgPVMZ*IOeN>8#+A* zhgE(m2?)?#UG5mxzvypSzJv2+i3ou@MX9oPwJbBv&>%rm<_D^TkU8Pcdzj52Nn>pB zN{q=c9x%A33l*#nyMG2S;td1$NW+5exgmsr^X|#?PKrG|ct`S(M>CK|{7B<|M9JSm z6yGUb=R0FwA3^(l=qTB}BK2RWQctxG(O{^dElnOTviq|)S zYgv+_W9{3b9^Fy*ROm-ZI>{Gs(T=X_6nVQ$KuFKr{p|H>8s*8$st!~}-g@cHT8CwQ zoLzJ3U3TK7AWyFmJ5`$k`qPa-nG?D3#7YZn{8kSVdJ6~n-a-Ytn>K2T5-r?T;u*{S z3l24B+>wek0oEL9j`KCy59=bEowlv<&`=g(@eV`62?+tefjAvve?u{(Va%~~6XyYE zVlbx|l}YvviguMBV}ozIV#2CiOHwkx@vOH#3+G@A#jjr>FI8@cVP`}O8*-e>Re=UC1Z zqLDvM7XRA2d6X?w%}qZf8!w~B4pyyDHhOxhtc3b}Gr+vZuhhAHp@;HT00!Vl2aXdA z!x9X|;|;|V4aJiTM+~|c(UhYd(hX7eHH>*Gql@ZS)BQ_^MY2s~`n8Oyrr9FxYZL>e zW6s)!D24`xWiFYY?xyF$jSH4MuJjrFOXkDi-`*^#)zmhM9w zAUBxUx7r6Z-qx#s_Md{CVubxc#~*A}KzG9*Bc%Q1H*-J#lXQOZTp$^wN&Dx({R}-2 ztXDydtcZ^beuR5$^2;Pi46&CGw0m}bz1Bq>IJ;AF3cp)RKt4dX?d7Ln-R6g};yEno z%h6Rh82=8$8gY@0d5FM5M_{ERv(k}TY>O^;;8Zk5Ry>fBVXGk`_hTK80o46%LyL;O zKxDEN=&r~76OHW+h#Knv#9)QysDYh7gCTqKdnrohF zo9>7_h4{ey+WNgtf9uv`puu3sFGhAbG71V$j9eJK`6A0h+&XKIFidB3h&(u27M?JJ zK%7S^c0CMw;331TCsJ{TL=~Mz$W+K|nKIV?D z1>van9FxFZ?haxAhe>1bF} zpiP;+RjkMkEtr2%&5&xClj@f)L%AnWc+6c#xXs|Z>`D)m8_~Zko`?A-Wj;10`{B*- z2`78{S)4>>FUdVKKty6W6{6W7A~KE<9I7}~R5Cn_5;AU(eEvv3s->Me6^Wqt3qKCg z&7q6yvg?XQ^sJJ;sid8XcZ%R2Aa&F1Br-_EXvmtQ`m5mOKLZEpICDwl zT$A6{);Kk$u(M^+*u1cZk4*1SIv2diA*McbH{!>U3#QplVl-doQ^W_xG%3wyHTvKo z3TL*mmMUIANfutp{xXy$ZZE`}p%HG;h?QyvejPi*uuC(}XG`MbhEyCgrrV?%$7%*h zIn_XN zUR+$!Jz-nnSmUWykdV@yY+(sHwZXu^Z(+?ch=HfM9e$13ky+vJOucg};58Dqt!ZZ- zcT#ZNwiN2yh*-K7oZk-RGpQVJ*J9AL7RhLa4K>wF!MI{r>OoaGwV+^}dp+ItC^(Bb zOKOm=QDU7W!`t54xMNcRJ+6eFTtY`7y@i_*r82Wp)Vc9OnBm0CcqSESfFK%H9+o8vUnU1M7zP5KrHjlhehqgv5JyKKdtqVmsJ2^Ao;cn+}zjtiNFDdGK zD3%>BJSCQWdf+}?u%#K@XY}2<(dTC7FhtZp=NkSl%h>A{pVEcqk$0&fqzCHUEJrJ~ zPU*D2c(-d!L*K#_!m`}HCbOLlw+GF{ZgDUjWk;(eN>@U31QUBPf4r5gl#HJLG^)Xi z+m_^zT?<$6!mOE=%M8|7@`LO>xwNtz;R?45$>sbqBRxYGGN~bzW4CBdmLYwX@`q$& z0YiX^#I2OW!q)=Lakt6$`|MO#UiN6vC>wsi!GmGLH(WGv826TUvh^3BiUEIs>VX|) z#%<5)0dmuXFGPFNoHCa`%xiMXebgI|dlLPw35cY}pg(*wseV@i?AY(8ikv(cHL8yM zDPJU@%Lvlrh~Y)jJ*s&*k8!2iU;slLLHb`)qMpAQ@1w5jX3!P>z>2h;Kw^!1`wNus~&=a!sdz zNp(ccX3>xA0(gLtJc}s9!30j)z&u)_zYqREy=mnu>-`>jKWcYZ3B=uI z=pE@ihJW4sK=fmKQJ@1N_b|UG(Y4E;qKOoeij{QhH{KWc#fMNT^Zy1BqkhZ_7Cvity z^6Sofd-oQI6E@SXRUr3F#+S6#S;*3fB5KBK0kbjmLGZQUk~|6CImA(FAAd&DNHvtW zrrkU@|D|qHV?<~tteUpZ;1H4Jn&eEXLE{#r#^69{IE(60Ew`)}`qMuJeCix-;asrv zH__O6h%+^aPn9)H!<#|$5_*Ul9GT`P!xEOi5&+>?BZzSaD-yYyheZ>}F+ufL41iJ7 z9BLfJ`m47=Y~K=qqSr9ItNI7wM&sZv!3Bk{nQRvtK-AMhw&w+CsH>vvx06M#P)oot zNoga_K`xRRLgyH7f5SS^@jdSNm~;VVT--CS?3Iy$Q>rEMqkf`N!yfk-l|+zWEoGOy zX3)*!_&y{0!t*~Q%nFXFrhQD-1J`oIB8>PQOYiheTnldq-gv_NMGq|-fnhdV(1FKd z%BzIY_gVB!l!8f`8g)k4Q+T+(FUCjr$ zwaA%5d%u<$O{N`5G*CzDj)@jB#e?dM69B4)!K$)FjRy?dTzEsvLX%BshAqvYBUkC9t_i)&m+@8Lku67|9tePp*%u6k1?25Bi2}Ddy-* z&*TAKHXz&7k7uXB3C zh;HX&2Gg(H(4(ZYf2xK(NRKz(Gc~pxxHdOf4^1IwbZIh*b=Ed2&!gbfFJU)8l0w9O zUZ+EJ6;&R%VrgOERTRTY2L|l&KL&{IIWT5Xla9|kLK@e58Y!*s ztNqT?p}oHh-U^k<^W?fnubvyL1|bV)*@UAruEzA~gyNh=agoy&1D<2_ZvBMq{ez%| zQBbKPhjCbWFX~U-KDK=YuCaSUTYGO+S9P5_=MU(9`aJzn zGtiTrca%ah)9wDi$tw`;(p;1$vn5=P>>SxOvXPE$(7_E=nf^-+o$?`Sz*I?g1r?`P>7<;AU|80M#XOQB82QR~m7Nz>q=7_}$()+0QP31Hv zK;!tp7dRi=G#9Y*TdfRaU83S+U{}ti!_0MYhj!C+EA^&=xNmLa5JW*4_SdfXD+J{)$IW}VXY{r;2i_cmLDl1Vd7X}t$^=vC>pTkT6-K%KR zQDH2zIH!v%o;5`t5vNF!e45pZ(f$(D+%=`+kKX3tYRcCR)q0L_-op|METx2r^uMDD zjTOdP>G<=un9B%f==H_NvR03YAa4s5$FyUb2uMeO1Pq0?gFVCVfS#~%W5qGVi_Jv4 zw#1rUYCsPlW5zCNrsf_yw<)F4w}Pg=>W{9vM>~U28T`7#Fbw240%6UifI>snF^qx> zms><0-S3}^ozXEn3S)V6zMLm6>`{i%0n@uOUEB0sl9)H;S3CqBJv2Mgzi)M-VFE5m z7(i)x1)*BqKQca$a_B)+W`s4Ji5a_q9aVY$UB9plSbG1srU$m&4aqK9yV6vR8}?~o zl`dMYL-}rz3i!a9!xey#9Il{nL zrKZdka@|WQ)P|er5CCxixm>yx?GmX9sWPdm(c;na(Nd~}3_Ind636;+oki}H3_oS1 zVn+&vnDY`NLMSyS#V)F8YR!fMngC>WX{EK%m)wo;tx9zYjp2z~IeA)iJg|8U5EDc% za!xO5?FRHcoliyOt{uTeOb)qE)r*Kju6!4hLJR$cxV)+|NP2w_@KjRHO8p<#JyiFp zokeJbb65*d_28@eMM{~dI{sUE65aI9%~4#7M0Stk)545ZCs)Ocbp*mG6V=3*ak;lG zgLp{F;w`z^iwu$}!&FPl!xE0@>C0Ub=y=03GUv^iBa(Yz zoPcAYp7d0Z0?y*m8ep~B;upgocC}blMiOlewp?(+c`^qnZENLU11&xY1Enlv9$euD z8YTi=eotU9!%0Cf0yv1D-?Z93d_8LI)_FLb+o0CBmYeVAQ(Oq^_TOwc@zxP+e8ht)VB1l znyUA6sU;WWP$M=4`0au=!yRCnsoS+}VHh46n|t1|!?(cZ?FAsCc_qyBMZk?r_y-z% zz5$?vqN(9k2S{HMp$iYSh3_So;x4Ub3&TjG%0^R6Ci!@D#u^5PMcU#2F?O9~owQ5h z?F7u$Xnsk@ZEXz#x5VFnrTF*ee57{fvI~iZ2E5WEQC-G}D~bDC7dN@=)r)yI3unDW zFgOW~nHsBDS83E17^YxN^Z%)~RZDprDV*YCQn}MzcY~0xXis#+_Y!qECbOJHd2_s~ zh2*POGno=&Y4=wg-6S8QJg1;+)Uo`sC~iTz2&D>c;}0iu{mYR8FO7Ip?_M+`g=eg}3HszlH|3Rate!@za$|(lM z(XC3WHUFyl@rKc@X~g|!fGtheFzj(~s3IxI!E%nVan|sh6_sNkv=BK@U&BCM8}s1k z;U5}0J2kqV*rF5_>O3Sk6AGH9ltc_BOJjay+L#4oL-2zGNC0M+BgJXsveiJ}j3+dE zqbut}y`=w<(OE4W0?BhXMcT^Z!a{>NQp>$08My(rpytV(?Jh?NBcNZq`Y1m{X7*Y4 zL(!4Hr9A0|Q|6#zSrnDFY`KC=Ek0(c5Q=-^A%Cl@#A6AxIoZyGh{W3Xq|55Awse#; zh%8HR@^s{3sxMeAXfM#blbY%cAIUvXO2IZ^nyxEc7-WN3$)!V&NpR;oBdjl356W+eNW*hOMYv&rN_f?ET$ z$U@c~qaHmfX~s+XTNL|~Js$=`Aw6ul{=tB%D_#KVS#DD<^cQKgV|Llm6T?3|++bSK zgth|vGuaIaIgJthq&7bF7_4=6Y!Y_sCiZ3WLN04#Z*C3V)o48f?eH=k3g7$rrQt8n zDxNAzjG6n`R6m8CGsHSI{!Ib6WQc^N`xorFkIB5`YlJQ-DRqA@|KieFmREinaT@3} zEIT-PSLkP0e;DnQ$+$;;ANlDxX?cC^MW-=>+S_;59-Xm@lu4D+i84ipd8Q)K(%RBm z53cn}cUvXU!t>Wg=dY_I7jCc)Q55L(kGt^ zzvBW{Om)$j9{xaUXL;tg0N5Ko_^4?9SzP?Nt7Xu-&YCw?jUw^AL8d@tE7}Qz*XHgh z5`R0b%=@HYbyo1FzF_Mi*fg|O?L@_fIfWuk@Nn=$*LL<9PeOlRNiFhjQ&=@>KS8uN z;iKrLX*hM#Y(ZP%36wX--s<8Q-Fy=B#$Fn3n;=TAY|4J3O?h*TNg8p7@Pt@9w6t%P z|NZ!$5Y8|fj-e-1glkDmN28;?rqYt!bU6F7wIlYp9J`hL$M#FMpd1{RVR1`HocO=< zH!*$xU7;RGbMR8;4ry+k_NhtNK3j8fQz@L#u+G7o3g!-%zOJ?~L`5xS>9taL^3LZb zemKO%?_ytUHQn`cQV-*KBjCr>r_R+Y=x0(b{qq7U-|{|-<@nO}%<;b?Hv{@wUIG$w zcpGB5QpMB1j57=n($*@mPEgtp;SZ;jkdF$^KK|4LjS05sahxdvaMe<#fp=Nq?^55NSFVE)A?uN5r&%?K8A6IRRiczv!K^@Z2c4m$z+jPop5_b{>$K7 z7|7||ZkVfM%EJ>&?dI?k6e#6SmPJyTo;a>$*l0+O%$lNmd{noFohFLsEg*~{h(eGZ zQOPKn{+y1kj+=J!FR=PJ>qkNoNzo0E!qOv%tYet~wb_qB9-}$-Vz0OAY+wf4WmkAY z9@AP9^X51kUPbzrKG>@kjFxE>UP9;#>Ucxw|<;oBzrNwLfd9e{CUA4<3TzPN^n4985s_EaV$*iFP|qeQ-QKT1MYRj z@Rl|c`wEx4%nm!3Vvb)O0q{QQI)+&?&MQp!LH7^}e@eR*jwYK%5jTTCM&~sNxca~` zAa%AMJ)_##4AZ?wj6y&GwF$L}bNqVTx&aVI$Gq9UUILrf0O;){yp7RV)wNHyXBVHh zVUcvr1Vp`d>OY$IJPIzf`MX1R_k!+N z?u0n{#D)&>-$o&pdlzk|rqRIabz(X2dz0G!RAKXY!7&-d9qOBo4fBA9kd7S;(&A%r zr(qrSo>;r6SbKMt@%x39Hx69`m=a6Waf;m)hB}9p%42LL5^ateKZ}sVoVHqrDj|o@ zJ9SFg6asw>uArT2^f7(=ihl}wJEjH%)iv^u>*aGm_GD@iil?@y5+~$Hl`o>Vk`Ixs z)O=kTtQLP>42a7dPEP}v2anfqxglA2@YMKJLm(zF6Q^#tluavW8sjxV)zFFCP_j3s z%`YZFm%V(aRVyeZu6+`th&HL8tluu4wK0p6gJ3xM-*AQ1$}c8PC=LU!??iOSi2ao^Cg84z^D8~#iE zn28muz6IwCIXFdRpA0_@e0DKHZZr*pnLLFExjb;~e3f6te@o*gYum^$T*Rh$Hp8lf zHnM>dvf||N6Wji=Zt>_8*+zGhSxvh9eWlaBjY|5HAUI7u@l01c)g&neZctY!K+2U67Srzb+bp3ln z*6WD&C2_3ZLT*T0f+dm#(vU+;S{vDTMX-WW368MaC)JGoiUi0sS3KfL`Hhs>jug?^km2jF4^k1JvtZgAcUkId4^NHGd}7NdquFnY z`X`5bC}mOX*Fh9ql|2q?t*szdFBgw&6@(zXn92clTcKU=vAE35QNc0sAFig=d74D zH9kEDc{yc@pi$=npW4_Ig||$eZqjwt)VSKqo2r}2-5%c5F&||Yz2Bq~oXb#wQlZVt*xSVjfIDX` zB#Otk!b~Y@OHv>~vZ~lDpHg_t6a-}1+!C9|%3kAPYx{&8+VxsJBo-3q_7vhz({{wb z!bpDE8ln1DjdDvG$TWg5`CqpjD4k9Gt&Nopl;88GndVDUyo#IaSy+)8n;N939H$VYSVIZECGt z$(nwg;O6C8{;U(l_)%{AY8Cg(tcq|h*b4g#9u--vWKz-ECO-{<^(G$ZX}%CYIpbun zWD4a|R3BG(dahS153E*0ZNUqXJl24%T(YO~Rpo@%a<5!ThG%>Y1#l9&LlEvNG@6{^ zbXvDzM(Sv*=5smd_xaXs692QJa1xqh*8e{9LLdSJxz_#HU)ngZlX!(IHfXWudANpuU`^ zwi4^*Kk(HO9xL;Rmzo~9zTzThj#ztp1b>HbMRYsOU)tPW@o4rrlofn$l+*yat_Fp+ z3k85)SWt$E_DsHfd?Wubq=xF|SV-^g`E;!Ry%sVJieoK-W+V|)t~WSls-=ozpw-e% z=T%LFcqqN}K&WS5Byxc*F0o?{Ix{S7ns&}s?eTv+dvsm}9c?)yULTaVb%@}1|60?5 zW+!ne|3RjJhE$Ljv0VGEXqR<9`CZTG)V|dxWjrvz`cC*cr6%iiC zQ(Jgt3)r?y1e4pz+nGb8~vs}#pbY@cZGVomU> z8@yGtweE>+%0^#;{ltsUK*T6fvnNw~Uw+*Y)k=D(1sUh>tfb-+e~puJsE;9%s&h?M zkSewK46)dUE~&+xXwq=C3^q!2WWuYEi9$Ld=BSw!t&h(H9Vdsb&&?cHOeK>$Eu`8t zBay}jS1vE1m;v($`*U+H(v(Ds>w5DF`K{;nWOPUBtfe_CAcYGjO>blSyO%f}?A?JD z1U?%IVn{xX=U2fOnTw^45!|+p%J;^PcifNv+9dQ1PhQN5go;;G@}GPxe-KB=3Q#y4 zMas&Lua;az?Z_x$6ZRL{H!)w^%iZA?ynSHpk{E_Tct`;kf^6; zumkm!R(LF)d5C~5q0rmSzfRdz)E58r^koaOi^0Y)*dsPMyGiZ~V`B*IliMuXIJNa0 zs={{Fj;MeoRo7PM>B?(Q{fb-Ybno~tDZ!0?7-hj++FhHO*;O`H`<~|zoATT$%)sQr zO<7R(Vf@EBpX1YcXVR-~(FI)+`cB^=pypJNFgTT&R8~FkZ}o6GwLd29sj_5&<_!ro zTeU#7q|$azr7)H#^8lrRnscg@uSi=4DMF)@!tW`&P@wl;1?YRz7btA6%#PkBGYtW@+7e9ySXW4yuXDx)#*~!nQ9GMR{{! z7}RQhV}pOWneP}$!Nr=0BypwxokM$v2&7!tD_^MmX2S#`xsF~!Yhd#fWY z?n6R4HF>K2vZ%m1m+=kmrofCk$_vaPU%%%Kk*(xfL0ry*Zg#s=|1_#zTBo<`*e9_w z!%|82eFzZQoumL)8IC=<=P}vIXLYQQtmeVN?^vW78%~CV_aq~QOg-dVc+gwCto6d` zc*u3vD>98a$X;Oa^_|5wh@JFIF)3}VSYMs1b>I0tn!T{GU4oI@b%Dj`k>W~@C51%g5WSHYxjARyEuDxrF~ z#^l&}9}G-Kr|@;?WT+=sD!$U^A{6g{Tm?#N&(|dDRav-rlleI@c2L7^{aO2kP-u7? zU__4XWwluk3zm~M8qi`gsOQQAUys^WCT%@iwU`2CLcOIv=1AdO`|u!E6@oT%vVdeG z>E};JINs>*#5a&~@M>$mPq|5_Bx_lNFU58jkip7njmu{01d<$AK??$^papLVia$^* z3W~o_&j^a&Q!@&RKl`s16u%2?sVw^M4Yv8rsjvl;1k>uhx{-~WYzbqDJiehPk3u?j(7{YM+jb)gROlgjv6nWyrB*MK7lX%kV{z)8{xglR4ws$bN zpMvt+eEY>zD2LH>*s2{k_R-2*R%m?nty9OS96)l~KeADkKr~?Gb;R3Sl#JZ5FjoX^KQazM z$u)~yfD}@RGaLotfy(iM^Fee^G3E|3{vw#Z8|qWoM;fc|Fq>VJdK03*Cok4uBpWzM zjKxOe&IewRJ;6K;Bu&$1oKTGFu>jl{{#NVRx1Q7tA3&y|xoMh)AG0pS6FcXv#tEw~ z=@k%1^U=n6MTWQoCrRf^`GiWLk|>scN~TgFG@&)^B6s>$Gl7r}m2HXC^W<_enU#Mk zAd4w0Lg6dN;9GX1y^us4P41{~K4bFGFip*onBN0d{dF_`fxW;32_8F!5AO8C}?r|Ap8p=Sdyo3xM zE7?~dHa$d~KMPtNv2w=6HZ-vtR|Wd=orNvywgpkb_D{&5m@PODDPSx1 zH7y3_sqR1rOSJ4GQ~GD3n76`6q%x!MQ6b%uWX3D-*+&MJK{gZ2gnAqpE_ zlsH%vKe*u89t!6-z2=6El^^3)Z%?%x&N@+P63!hJJM^>qO&@aFdtb16goKE8a5wvf zi0>>m?bR^~(}-l4*24h7klO*`X;6=NxF0T{*?JO_aX3w6BRbFxZy7rckW!maVeQmq znfq5z=L2T=!K8CM+l6qHn^`PBcEI{+MCL!HX3qfv?$TMj$IJy7$;$({# zAhQZm2~H%=XILa6jFOJKpvIdN%@KN#6gE!S@_t1^gB0{88zNda+Rx9N!yY$fI^&!p z7&mn~Q+9zF{%9{v5l{%m5kwu!><_$A7vK1Y78G&ctb!4Xe-U`}GRdnZXWbaSsbzhY z+viLuvbH9OUOp3~?|*3p{G^y%9Eq_dfAd#wv?@DI&HGZYbda;$#QX!1;0^l>!uhZQ zEqJk-VGpr7Xq6_EQS&kpJhIWt9MCcKPgJbRIMbV7q+()Kt;7=J%MTlI{~IkE6lEfE zGQ1LwHoKK>DiS}t;0N@csXv&A-I+!&fs)zMCSt;qKJ&&bDAWgXf4TE@!T#yWPYQU) zId?pJa5*^*ep@;BhZQbF??8>$B)}J)_6Z>1m!y2^5+U_?$|+#$CE*zFNju!2fBY@&V z-Hkxp*mAo$=|WVOi7?Q;? z4_x5cj?L9NpDE7;5_#}%o4d5gZtSlYzKm{bg2w;J%&bTC z&yuf>$CgA6k{P3w{2+UTe~}b%L?q}zVlKr4!W15@0QnL8?Eon|x6P0RK4jz4++`~? zH6V{H(kTU9KsHiN^?s>ThEK&R|3v36()Con@FB_>0gj5`rlbn zkJDXYQf2SuI6VRNPD_yuwpb`vOCC>01nfc8bOd58u#1*iVJFdol!vDRB52$X#)F$4WLXNCWjR9ceBrZS4B=b9(3)+Di_X^X6mF6Q+K2?&6bN?{@yOJ7JS6~|z{v*>k@8MOh1|{y(4t)O zHkx>3h1>{r2}mwv;#`N|NXE3Y&-*BP5OLxpu+Am8^du-n1V5n;%1Xnr&8qn2hFlgzK9gR;rQOqp~ET-B5x*W%QWphnER_!)tyo{xBZ-5fcM%ywM(HZ^!?U;XIhH0zslh zk>d$~J9VO#=t?%)j2l+)Ar>Jg-}}*W#ZF84g4;~UR^^7hLX3f8IXk8IME)eHXQYA2 za8O@9V4i>TP8c&`=~BCQt$Ln?RpRI>g*)nlJh7~RZ9fcae#&K7@;AN8mRf?|1mZ2P z5An23FBY8zr8VVxm%47wr4byIr6krtNiXx0i<379$~QfHybJX-fD-1A(QtT;Z{2a2 zXxhn^3^5CYa|6dI(CJ*Ka*q@kEEz{xc!Q4f1d8yO==p}oLeAKp1~kUnF=@SRJQXbd zoXA8Gk};#5EqmB0P`f}3H|@ZzrDG$#NfvhIOa(3(=MJF%>gM&)r)0X@I*%0h7O249>%alWDj9WAI8CDopk9<`bJs0^L!-xsDFx^h? zh6wE|a3nq3TJL)CY@p>^Cpz2O??Q2FpcPohe+$e|gyHuF%X;fUraOhT8{OA`3naO4 zS1}h(Dx=R&{3&Gm$)F`&=Q~Ki^!z+lWcy=&LPOW|6WYg~IeY6S4DlYL2a;ttQH9vZ zNX~Kg1kR=ZNCPwOzM9V^O5x5U)9957;4vJth=Y7H^i9sJG;gk1+ zszgkcjK9Nzit4K#EsTjCZgoq!BQm1v1^a=>IxKTYy+P3nu^pvrUUdf}M9~Yc3hz3k zJ1ltDcgOxo9uzTs8QLH=0xr^$@qikZ+I#C&V%} zfn%GI0i>^P*%&7fXw0=?SUM(xRkl%O!Sx}LWW68n4x(i*{EvaAMN|q^kgmfzc8n@K z-b5T*6I#)U)F1~NNYs2W+;7X9xxtn$ZF#Pq81cx4^|&$nqPtAazBH(ZL0ozW?~L(R zj$L^X5i(`K{8z2Cv^2c}<|Lk7OihMgK=O!t$ZaJzcCU?_PNJv&TsAb2)64*`>c303 zE%MkE6#jgl$-_2DlqzBmzU#CR`&c3s!Q=mPl|EwM$e;i6bHrYiFJET?8Z9*ItK$Y8DPQpuSB+w$LMMaXiVseuxG?Z>=2a;9Bcho0v9;U&#;=I&P8sBNX>6M78vk4)Er8~ zfFK<3CkgD9r=kK~&VCMV1FchrY>Wqje!?0Grl%mUABzh@(_RfQIQH{(#2N{q_4RI2 zP7+qNK;Gp_hi{JlObt*TaNNHdQjh7V#&(#_D;ao+`_Y*XzKKB^@W$yogxzCS(8j!7 z_H>e38_a7i1pdb%`j?J=@Z(B9VAj~pnr<~D-bx>dtk0J6*BP1Xf^cLLJTyJLyxH;OdF`ssU`%=f}=Ym z;LiPxT@23~eLQ5jhuENRh&BdN-{ttx3o)C(?8oUA*Vo4mjMk~?G|0^TPOkwzGa2-P zTibA6QMp+E1S;1L_;C`_?G4AoKRYG)5i;Vq+H#HwZZNqM=CQiiaszjrN;U@PaeO`Y z^5YH<#PH^Cjzc!sCat$8*DZg#aqPnY^trTJu7%K&VmUXAcVZ>Sy(&Dgd-BwY_L2+6 zPgYE(XTr~U&=L3=@E1LgmyU$-cue9`NV<)PE%VYBq^k%55q+;+P#Y{L8=O+<`nlcB zChp?X@HfB0RY!Y-MT#b44nm*fm2NPXv{J9J$D#wJ^;2pf{3vI2j6oZ<&ndqQZvXG8 zirCOQ(z5Qx%W3VulwScCU&D;k2=+%KY*?+RWnMSp7eP=JkLrN=33Y)Yv5O#t3Qtyr zvlY66g<>y}#N~G(g)>CD0@hNm{-ou128A;b!2G(J!2b73%!HEe=FmF3OEj46{JOfMZ+V|$qv8&w)i9~udkri$<&TKaV2 zG$9ab4fBVgf<u-weq+Qh(>MHMdAZ-El^Pmy5COkC}h| zcmu@@{T#4Gv#4qDJQtMwZ}POcx9gDW)n8tQyQmHEPpl~6n#K9lm#<_ZSKExsObKKu z6)_S$q(#NeqRNAKE&yI%1LrBbrKE8cGe)70%=8jjT7xu){5krkhG-5oa+t@3RCNZ- zkiG^>eR|BG^s-u~0s+jryuTVNa;)<*T&E%dG^$+Lp}hU~jm#ujRBMQh zmow~6LEMC7KtcG4!eA5a1dFX1-vN+6ZmY;2vKL$wDU;6hmhT0;7?nSYrO(IOT|fYi z+85Qk(Yob-6f>D7v;^TJrLn|{F9%Rvuice;A@@=^hw+vt-*tEi2T|>YJ@`?Ae(+HG z{~l~y)_F7T#z&F=P3G@v{f(UGtk~9X^CEqe6V%UWOY}~=u{ExM<-3U8@N&dIz9Zt- zf#|j_@JnKp5KQv%Z8a+YN@RDh4M4)aIzpoq29ICPOk)y; zzOLw7)D9qse?Y=G(Vt8&j3r-AWK#%$&$^na)-w$kuqS28*mJXHKv%fdOFSj$c+LWI zz&s`kSp^(N4qC*b-wdlihxNFIEN;RYo|j%~;c6c_Ygv=m+DYz;{BWD=sJASkzN)sn zcWGV9ur50xkV@notqQVK3?N;4053g}l$w!^%T7gSE+R7!fi8ODFFirTqYQ?RUJkia zG?lD*DsZI5D4E=|uj=Z=u_O;%)aGgq`?D7-=kA8#Uw=*h;)W+vUS?LlI1blsQ_yOh zWYi=4p@%mm!XP8ylsY)s9+!@?ZD@9^J30wII_VmhzK>2BN+$D9D(N#C@12l+ISP;e zJCH)~i?wi42jl#pWL}7%DbsBkNz79PfUA#i?zzEO?goL3)q-Y_^790RyKe*V>f%?y zG4Yt9CNzX*lQg4~I8@W>X-u+`f&4Jt)6I*jPw<8VM!b83+m4*3Fa09CicbxBOvve=H&Mq0r5YyL7q!{O{aMu0iy&~Z$4Nsq zO>2KDc5mFB#l@`<9D@N9!@;X$;d`5e*CX9Tro>ySL%8QT)IiHXrwBY(C$L~CS5WmF zo&wOB_1V`F@^;1t7F}k`bjxbOE|1p?d)&@2$ijir3Hk8L%P#S4Vo{d_X32wuYLb#% zo&@^(cqxtHOfp6YC18eDJhTfgW(w0RUkF{{SU&E{q8d;&2;t8F3?VS0QH@Q0sBvoz zB5?YlX!b)0lO#h?k_W2L&HoLaCwUtUnZzo!l{Srcd*~V@AA-h)?P9HZPbLD{;3*MQ zszqV<37Xp*!E55c+2{GooTe}M z4hKyEPU&IEu}JH6>eS}p0>4wg0C zmuT9Ss=e??y-!;R#&;1=@gs;DQ4Hx+!f8|_{A-o+3a5q4LO{vN9_mRi68~MRa>wAu z7R$8RD@SCoQVRz}h6hUZ2cGghAHY&iapn#fzXBM|@7 ztyE!Pq1`AwW+c}2MwG`-yK$nZ^M3SWKXSjxxc1+Ye4PSPDRg;63QmpAB4@LnIVh{n z#B#j8gTIo~6!Ki}pOfA4k`*Md)`!X@gfqzd{UJq>ypnE)N%vPjt%T#u8<6%X(@dqY zZXr`Y1-!ENqY57k7iB|mJx*TL)I_2n-YIkFLXoT=Xze0IqE8-dzxQ838&QSA>rQ@{ z_kB8VZ2etB(GZkG-mkM68eCt2no^33k5|M2QZ~I%1WxH2a-}hOJzUYS%c6T~X(8m9 zi>oO{of11*YW(n64M<5Xqa!p`+w?N})ue-;%~-T8jKGXvIljLK=Nrdwkc0F0)J~PS z$Yt*IKP#7*k}pG1x}32fndrLqGL>VxxBHGQ+u%o@RGWprD*5fQ6_{0r9E2q%krYZ3 zfkFwgj#19!^t-a^RiB)353I$L1L4$PDTQ<5=QLl*B+8gpQ?cZ#E;0Ajg*0>!N*Yo* zm2wBVR&?50)mli^>PmXGqk|mOIDZ)2-F{-AuG7IciQf<6R4_YfW)zFt!>ZEL-_>Ry zxYA!AQdU3)m3l=rX3e{aT|k5~?CJr4mQxBeis~(TwA6X;01_s}i?P4-eVcX_s582M zTOdxLbSja|PNw6X`Z=Q3=p{E1s8fGw$FwSDse>G>nQYHAoprp*hVmi=AUso22J?SS z(7zI;!qC5Rtg}*V&zh7}1SJu;nl%EAv9p_9oJfhc4Y3dm@1VG zl=4Pjh_`ZU&@mni-0b0e_yeppa`g76D7g>9!6If=O_yingu&ksl|`CRIeZ3S-z`3b zpN@?JJXlP<_Tk5cvC{Xk4IJ*5j;5{H05yxMKT&Aus)pmI?b+1m!_%jg=+r*t<}`Au z0nzaPsC4sG5HN$F%R|V_OV;MZf8)lwXCh_6LQ6Y$5~-#EZrs;gx9VRKcC zNYR6VRe``%L9j*7y(rF4*iAP>CaDh|3Gg)Q^kBhatTXFwA)t0eUZp=9(w}~BGUx(p z(D^g`JRR+p=z$K>V2O#%Qape^(eTshA~Mlw5R31@5YcIfV9lyKggr5MgY-TnKM|l| zfr-yY6IrOu zzl{~QahMqYvF$XpFlxV`Brb!#0-zZC2(74J`bQMhzeX7ei!+la?SNmzQCr5yKG~E( zyrrgwpmd#65?fdgKiG%Rb20c^v3Jz(fj4pWD)_w;z3;w3ZO?F{5c)jq~?#OL!UY*JzeHj_JH>=epDS_B=*k_ zp-`(Z1{YwfhA5gSbWar2D3nU@CVd?HW8|FVWLY?&&vw9ikSq2^;O`{Q?)SFSdF+f< zvU1`WOrl!D;P)@M+<^rVH@lEQ_>j(IMyXs>KuhYAQ|6Kb`SfI!G+@k4r~+-1)XwdJ z1YZ$#OYev7DTyzshZN~U=%r-*x#YWQa5Z{x^=j+_Wfd8$&}s(co&<^?A@@gMT5T_? zaTY3>;yW4)9qEYOi6)(vh-A+vKY-D6Fz7^)&+r|AMXNvDd-}KBf462m55hZDpJ1sB zqC<+)tap_Uj9dGVcdZYE8ehIN^r0<&CuVv?$KL#dGa_C(ntl1WP{+|c`M6SSdPHZ? z@JAgZ`MAeutVnPUVVG}Ua3*hY!Jr(Br}}qx)1IaYBEs?$I@ickx6r=%nLW6kF- z=Q5gi73)n*IeKC3<*qe%TvleN0L+d3z z(CQE3sd;|RT#a(tOzFqtmotil)9CVC)y+rPI^{&h5f@NyVHfwyj#9`6fZbY*I*8v# zz4zV&d+EluhK|;lBGsE3?&Qq`6eRUn%^d!0N1vZ5;(~NIo<#vhLjzBz2Rv zh+L*L8!JGgMge%Oc0Q|s!6OuqJM0S-d}5blzOTD55mXH{+y^n*ynD8`MkE;@!`L5s zEL7<*3}xfmDl)niGJ^t=4vL)1h|K>Tclaj_&8g33H;4_eBWt_5AV=9<;hTH~Loozp zd7Vz(yQm}bKb%m^FRRMuq<-aZ6NHEG0<}wUs;6>#13;UNI2{W_uj3M{BvwvORD{Z2dJ=@|>D1YlXlTIH5i{|=}_GMO+bRU9? zW~0orFS3&^?;s^!v1r2{7%N4JsU%Tf%^p-y_3y!uXPr0gK4g^I-y`JDC|dE`IW;b} z_m{>@@_n(-I=7bmmnzwHJT1+aE;{uhg9@v#`al1o)oHzUGN9v6X-6S$@Kzt-Ed&GU zhM_@*w2Q`QR%)}s6OhI~wcWC+n=k;x0sCqvwdIghca)5`qhnLobATJ0(sVT2c4ddi zW*3iRmLe%q3|~u$_<_)MP_pv=>^@Ow_Q0e{`hh31UQl6U%9wiZ^Kkc2Kj00Q(EP&1 z&ps&oH*DYSO>*c@6z7sCoCN-i$$g&(y0|t!F2i%adoz`W*ai~%JWp{Sp0fyvV~8_h zoUX|{O2tD~`SxL>n*>5q-I@s=7d4appf1@ibO9nqIADv@vNcMc^heXNddfkoVhQKN zrYBmR2r9`l^?7lBQuZmf)|IP->$CHDV?U(iYN~nEU-%>)(deLOPCB*M5vga!!hvl1sb7;{7S;q5hs;5~hj5Oo2znv}H*K!B9 zGqOUw78p`|0LPHOmhQ943^%+chA9w}Y5Sy=MxX10>k6$Oo)csQpY-jh zq?QTB2ox6%q|{9)&}`+yw6b=m!An(2%j!0;BB`0Y*`C36<}kGrQ@%P$;E@I9`jl#Z zH2-ikFbNFm6F_Zvg2`eI&DJ%e|8ceDcgft@uO3=2(#O9%u-b7>d_!ryeNkNy)8?$> zkkc`z;4HoUu+G%x$JP!Nw~j$B?})f*fbq1JK`#3^OvVfi<5y9?1jMupTo^!;I>(79&{}BUG0h zgWJY_*OHCuYIk%Xd`-2{m>f&mF7YPK7_r}$`Lj~ls*>j?wZn>@ptFGDnoZNqmVJGd zj{sr$oE0UPDB-U;i+2Nj#y=2FF+6$i?H(Ocb!Ic|{!Z;WQ!MMJt%Pk3K6yGL9ggiz zKRVcy7)8;%mN%$VjFt#@_uaY(l5Q?&jTlia6}!0PKZSaJWlgj=$TIHZlw^H`#R~e( zJ!PTGR^t&X2Ei`nQB=rOyp;+WSQu#;0vai?yoLTVhn?W<9_9~9yHOVBSO(XJ)_$mq z-V79L9>q<33no3Bz)B&N<7usRekgTYhV%>0s<>qg7U< z1*>+v+n6wPA3q@pybNv!1w7zC%F8K=Bl(N%c3+VJ85MoSREo&I0({ZgJO>PVu+003 zfNhM$$sH&e?R8|zJp{|`-}ANw5tf}`qt1`cLKD*MBk5z`W6m@QPB{?|7;)7%?)tJ@ zab)QMlq$B-LWt>EN5~VapQmJx{Asjtk8(P0I8zBuzgZrr84<3xqLpI@%o~kSYkeR~ zzhnTF$_HzUp(`B{yw^07t1dB^Tpx-Mme(b__Q>8<+^YqD)Yij^9X?j@x^3^_rx(#j zs$BVKyEUJ`+eFj+8WB)$rSM%fOD@($DLF(TOrjB&$e2|Z_0o-4>2AD$rC{6oO~lRC z?xLh)*uSk5w%4Fy!JcsOTUgJO*T^o@f=y&En{{F!XcKy$DBd-Kg_+hn?7!3A@N01{ zsimt1`Ui`4CU2V*K*IEIW19r6Ka{eShz>`q9M<>1(f~E723vdHP%`Jp_@~MS*{$iD z*(bY)WfJ~wSu{oxLr6r?pIVOT!M8|tDPa{Pi)&JW> z(0kt;ObO#U=|vgo@)^$?(&Ad}Cs{(sE|R(j*QmJS@kE3f&So1>o);;wA3p9;+)QNW z!4xq%eAqma)mD4k{682wr{G+eXxr{&$F^Un3>Qwb} zKX=cy<``J}u%EO>QJ?RfW5af8-}1QQ>_c~lR|J#dAt%Q*Zi~A`V||*TpsbpLp-nc^ zeIv$Ht}T-XyQAjOCCsa`v3}qSBy5l5af@q3by+%o?Qen}?pRQT;@hCNu*>1gp|Zxa ztrJ*`H=nezQ`T`owY=~P8_?y@`hm3@)bRy9a6K*T`FSsBFbg}O3me=D`909g&9C#t zK7W9&i8b$~^o<($+Uf0q@7jc{CO9+yh4J~1( z>gZcXE+_kFXwyXYBR&1Ikta;?^TMa+7j7L`TfPF~hB4&Zn${o;fgmj;Y~7en*1Y34 zRNrSN6(7RqNsvKcE`;#I0HX>% z0P;g2y%IiX>6s_J20o1Q!-7K?|1ax@hDQ16kmd&mhdBSlv)iZ;*{&R^wR7#KZHeiu z;0FoE(7Ky!kft}aT5zpHW|PepI9a`!TrCj8>`y!qxvcp|v?8{P8`s7x+y|%E#C`$2 z*&m;s8-idzBdNkZhtv3i4Z@*~U-j`j$DxIZJ?GiC&gJyLLf{XQVlhS~V*>+!2OohPmpFOyg-O2$78 z1R8=>qz3lg?gY0eSI8ftD1YE8!romx50Iy)??L$^DUhKJugf&Nm`wSGrZpzL?ebcq z{J2qTW+q*ev}cKba#ZZR>wT20Y&O)o)3AO+kR1xi-;NdG+i`rCP+il4u+CF}d*C=N z2-829j`EM^<@ABBpHt>V`O&>UsE+ah^YZ-gVi%`Fk{_TBk-cbAPtb(<`XJ8F((zt& zL8KqY4z0a#vw*r_)(?O~mM^W%D!V|CFD}c)>d^N`OuhOp2t9Ga&b)nK+q3qba1UPZ zl6{c=)8>A@FF4EjW_tDR2un|Z=q0yCVsBE(#cR{-$6p#{zj)J2ueCqlifl4|)4E<9 zpxv_zQ5@-0?@9p)4#1~8S}SwT>P-(@#@PShR&!zHIp-#6R`<1%jve$`zB`ycenKF< zJN75ZmY>UqjN@Iox$R|dOkb3SQ<{+$qEpE&VOYG6*N%j(-dMUJnd zC12`h9-l5V2m6N^8p7y|^}~c?h9@x1(}L%Tm~t3iZO~y132n^h9TRe$8+D0jjKqPuS-Rbo>}AZ{!P*{5WNh z{RNf-ybjTPQ=9bK?*o5(wTt`$(XILgRz2nIYkjM?|7Z2idfwef`-V3e?AxRJwqL8k z4-JC_i^B@U9*-6g+8CA(R?K!Ji53szqPkSM1DAj5H->{gug_wJ46uqG)o_8U%hL_zFT&8K2yHA=R{Z>;A{VkQYHZ&-qW=o2OEFkt5@BC zh}3h5wcjjef&FVv{1vi?C*m+9H|qR4SWmDT9)u_c9L5(J2#LKfF$t?U5ZVM=kD6FF z345!$n^g0h+paAUx;5!&Ns)k=N+LD);f(zR|FZakex6C=ib`@9J&XhR)XdnUQoasmeF-j00ty3RefM5<2)H;fBW)dA@ zH_9>2Bp2u_26TiGGR}Z(5bel>f`y!5NHzpx45fmlyiaq8qG2Z!)-qb*(4Yu>8J*#f zq6pO$^XH1uY)J1A#$$j3S&!{x;8Tp$+i+Suv?3HgT8qPg#w4&I+;Y?i&6>vWepGYX zn#TA#2DLh>A<-18N`wB8C)GH6E))a3-f&d(isTT9ZK9o~c?703-$6SW`mn>PUDTS@f(nPvb}SAysk28??rlY>jrz17$XUv|o4L@q5{j?5&h6L!>$$ zk(4lKpLMBrHp`%&OR#z5f)2dod@aXiAz~>*Hhj1DuHo}qiVb(ES22GA_ zT>|VVpIbBf`_!R4^=3jaGX>B zepY@pD8rPOSCm=AksyRx9i;O*cy1KL?BfZnj}3}nBex5gJm-Gy|C$v^H;!#tOv+dp zGSFBVL?_8&rJ=3a3iV1#Z7hA54eTTA-d?u*UeIN>fgas7n;@kWd5Z>DT*C_`9L2-1<$+3y8QX(7bS!7fh0%Vjc3e;oYH*htH8`i*zCC)=?=;O(3yGfgYP2$!s_M1@Y-!; z)XrlU6n*XDWW!5?}9FyK&hPbk%ZOiN;#3syx zK-3s`|H-^39LB;IO~W-gtGzK3e^T=L<7#hXzVQv4Be^>gZM$Qu_hBFaw^29~?{Xx0;^~=2W5sM9 zfBlSb9W$~fEG#`d{c!^5h7R|59(Y5OIpmgL?iF8p_?!43PI4?CZ~hhNI}S9??i)mO z=>8=9BT(`{?)0Ny-_H>~d2G+I$pJ$hZMNDc5u_Y+3k?o=-OIQL(xb^D-6SC{PCz*; zy66BdxfyHlNGd+2Nrz|~!Vd|-$rwMjB-PW)o z1B80UM8mkWAJnWeYR!dXTlA`xVR*FA8gCWkoTij@dbBIuXLFRMNhm$0fz|)S+JtfQ z2by~HhraraKT^=)>I6KN%k8nWz9DOMVQmIIEJDym0%kTSR-%K>AX7KNb34Cg9k)>i z|A~>=Fgyd)c*X|9{w0{GiCu>6vmd639%R~=VV4I8Et9i;`U<{k8c3o+r+pCzrY%Ew zkItEb#{e#fe1^wk1qWy@t7uQvnWft_Hb8#5;VvfwzAyc7kN%Owf(<&|N)F=lMaZFo zZR*_x%(+(u7tjjX>Bz|Bsf>jxcngxYlY=YSdGyPkD5A3>q(VmASe9QdBdW*=Dr$-q zIq8CuqO7PQC#=YcD>@Qa$OJ7~f+AW1BTDLD$b>Cw3Ku!4gOcKek^&{-ZCX|6G~pN} zWrW}=M1E@QMeK8Pzef8c&T-~UUE3fM47&wGt)nBwT*l2ubkJaov3c=AZZxQ;+OQDr z{yg(l2lMp_ca>RhhopUe@@svk<((Ir7s6^yFj*Y};*40F8CB5K0rHU{op4}2VDV^E z{N$8wR4X8r_t*5KL&5yN-TY~QLvIHd9phY>^)$3W&_6^QCi(#G8R>n(M<WgyWz zlT(G-fJ{Dw=KE!zXbGZeSoNVS=aNCtRw1NGqdA=4UxS>KV(C&T_l+`)qD-OCr!0Rb z`|pNBE4D#HPVCYR`23%|5#(6$f%`hZ zCuhV97QJDtX2ujf^ZWrPNe&tBC_1J$A(t~{hE?w{%UN?nxF^sz+~4Q*i_cwpPCboj z!L1mn45!}R$Kx$HRZ=zKZi%1jT6&JnMj7_tQK#f*H2OAkAgKmB}nPqs1-3@$Q^QF1}C3pR2L6)@MrjM!&(>~)L_5$jUvdwh%!nyBog_pV_051ib z-Z-^mVG34$IPGdmXR>VYoFO!8n0VyG%zWaeId3mZ+cXt>5N6(;s%FzN z=ZqjjfDe_^CT{k?9td)WPl)UWdQdOTW2^ezTJFDBZI>3v{yX(kura9KOKo^^jwxjO zHZl^*%@1gLyv3U~nPR)zTXF3rm+CIn3?X&RNQaA)R;|L>2&uLwU%(`f))vOTe=|rEPoMLMAR#5_g_GGYwURzSQ$tj?iuASg^imD>B*|s-~2w z9O|tEn^A=Pi4iUST*NV*?GNIg#+QE;WyA%EX}S8C-I}RspY=&;+WbkdqttSvjl zrKf0UX^*wE$Sf=?tZq?CxpLP1|1;v{oB4&B@tXp$5z`mV%u}8A3UbecdK4sj7~`E7 zgC7{;K8zrbjX6;bKv54MFTzw={a%A)rW-cb5aTag%uALGvJPK zx&L4sx)g`4bH~sV*Xh0qMPaY|#+x#8HM#=!NCgNx?@>4l6u39&5-<1Q606w#H?~Yx zy=bnI3N8J>E$=J4xIK43n>63R;H;=YaYyUdr_bj9Y3(@H;i9n}?SfUqS?NC3uB&X>GjTj-yRCY0_kT zEi|)(2zypKHdE2&EM!g6Mf1)`W7O4{CGQA1N6@6@5kyZjno7~+l}#LUU(Ut;bt1|? z{llugfWk5$#gv}f!*W$&Az(QVLUlj0T(a-cyUuM9nEY1iZpl#~ZRuJbml>3F* zv>?{Ym-UFaaE#A26#k}(U2rx#?+A-ciWow0ewKA+#bo`kqQYzRJZ~Z+pT0T>25g?V z0q?ZD+nsL-MqHF+CHyCj8q~9;vk{Z2G^buIKHsP;3#^qvy(VLa0Ef-DghL15zl2}? zi2@qJQYmkx#E_(~5491ex)y=!86UMnm$Gc5{%c%PP^>g%3-@5dRkQLaTalK4-=&gb zPQs$x2XD0*&D$@e@xux+UsQKS0iszNQcVHOJ}?H+JqU4S4B{ICvk}L`n?44or^LPY z&glQlI?Y!Fl;!*vV*3w?TP5&82W`)kec!9bz|Pnou2CUJoVIyLwaQ&XEFb^%Cogmm zXBZG?77*RFc20z3qjKm#lN4kf)BzkEYQ}dlqnm}ron=SMS1e2VTMy#jCbX}yKJ1ZI zxdCB6qXh05qE~daPUin$?3lZK1&OnUL^)6-jK5yE9c`jVnT7)9+Apb7RtI}zO_VC>FfsCRwL z#JH{~8JEWWtq$niROEV>RVuGf8eb1OVNq$8AL@|I|fyc#TQfQ4TS%&PQ> z7qt>Ccc?q#?BzB09Zx%bBXsqyv+T({W{)KKq+Hj}f$Xj7+`sra16HOtuj;Dm+1%c& zXe@K@-lV#uA(;S2h<9EPo)u5f@n`BlC^{mFPK7th{vsTm8quJ@XHtGA>ft>V#O&&^ zQkI)(K*!ub=WO0o4^lmGe91D?7Opn>j+ItV$dJ^twh)7U2(}PYf{`H|&EGDFsx1Z2 z25@-M2l*5i*|wsY!Xh0pojf`fPoUEI7H2V*bVWls^Nip^*}^jOs#(T@7b%=nS`>;U zp#RO+hEQYlsM5^=lPwdhTE1D{R$o_t2Apd7)a>`J==tfd$ksl?no=mKG+2X@#ENFQ zJr%>B;UOLS4geZBpnA z49mG=?)+ zU8w_zH{m2?RE|m9gQ1$P3Iku@A+N~XV>#X5cC}qw#J9r7EJ=3U=2LyH$=K@E-H$a> zgk#0g9IP%)U1DG9C?jsiu;?DN!LjSWtE|ptyLRMm*24L|cCA;SU7lARN(zRCqiyrj z-&RJUwIU=P5D(q?=N(E2HoAPMmmNx?5DOovFckUbm_Cs%zwAuLdnn>#FevoJBD_I| zj`>;*>x`ne;vgUXR2~VcOszVW@dRf)$ZpZ^p1htLeo3$usQrMsKD4dT><+QL^W~`nITKlKntB$tcE_inzQW-g-tPYov74>jqC zlTkDm-F-@agylUWot8cl{P@%;qMKx8(yT%7N82V*KRj;=twC20vFlj1VGi7J-aMks z8_#h#jp#qRbM}MeeFMF2_VfElS+Csa3tBk4i-1Uk$9nDf=|E25Z0&d%5`iv*<2bsD zXs?IkY=x;6wK9Ei1@ps-gg!JFWI`#_HLA-ea7sju_*=Gp8sm*!Ok-~Wt5>0%OE%t} zT|k@H-^4EMfZ&lRUA(58n4vUeV}I3HWbq<aviS{xvvmbB;X>bTg@aCHrjX!^S z+W$AYGT;A!uB`54>0;_6Waw;a^8fJ4;-+?{PKGY_PISgLhR)6{-jLoZfal-WURN`w zbxfgg5Tq3bNeF8JHAx5r7$70wNDGWXkV3)%n(D~N_S+R$mH*=Om6Adv1!^t!<&_@5 zN=a=^tE+Vj9mI+ItdIQ;P4M;a=lAoF*Xy?XZqI4%Bk!*BjgS4q!Cc%8D1(sZf37W~ z0PNN9q<04>d^FGD3M0fcxx=AzJVk0WXUa1~X^|Xhn&)}ZaQJ6PqYRDN60kImpgD7= zEHS$tB0-i2vsSM!X*ksz3b3nW`_yVFTk9j%!X)-6xkw3UuwPrkev)>8+|AnEKW z^ixOk)2}v2Q=4z~08%@1$6JR8Te^lE`<-(n?)GE)_a9xn z1;U$?#k#jU>)!4$;+vB9g<~I@mv6j#?E63XZV&PB4>4gp2Zjw%@HskdS)14Q;o`$Z z-Wu0PaUH|<9s7sXkv(+x!O}bvK|itNZz%Y=CqvBM9;w)TW4c#|6MSOveo?>a2iVHq)bR}VqgRy|8=$Jk08`*X9fF4Dj*1rAwPiN`wKcrLfOz7) zTtzo0+w*8j)klzIWogjq4FD~yZ2?+9awKzLRiG&Bj3~6pjK@V`Ye$c*sh75-mk%$y zWPP1^aG*4?I$$7F3@FY=b)`8OABMGswYdhCKV3z8b!Sn?)wITSAcZiXFtYOmRrGm4 z4a;ICa5W9=eI)LK|TskYW>AX!zI1%ND4 zWnKoxJO+`F=x(NHZ9asm1vrXh-NVpn5+{Rb3rm|XK0hfamy@ooOkb>AY^*dx!f>9v zL$+TC5466dBEZ(H-m8Gbmgk;HBFm^PeWiwM{Fn9G6f_FNbrYuYVFk%fU6GeNRxZsq zT7_R#pTH6pSHu*MH8y}OHis(w_xsy}Qi`Cbuf*PrRcerZaN8(wpO_3@Yjw+%J?Lgj z^ip#uS*{a#_k%PswZ0Id-o%1fFMX3U7)B)DgpCcIW*>QFv81GiU0D3DRY%&cHXCgB zE%0|rJJ{$`Oscq|B=SzCLb9ExgU$Dbw=3gQDAyZ!qKilasgfLM;tw>a7~U<83IC|( z^^C0z@HNe1Z$#F(Kq`v!iO58Pf%F_alY}q~1M}_j;)Bz=w6l*7^`?%srJbH&*~$u= z(<;lmimHRF>~nL&e%N^h(k12bGLmOpOwactk#!i+AaKuRVLf2T8LI!dMZl|vAB@b_2!DY0|#Nec^~8(-^#1pdg{`LW0rrK z^1r3H8_&xMxYyYluQND4sdl^@(XJ5QN-ghyR_SDFBwiMrbT0jDq9(#lMWpHgCicLnrt51 z#Hxl*;ZBS2=HyO9B?Zvh+jBJmh<>4fyR`YV5G%{@rheM4gm}ij4ho`5_PeKOCq}Ud zDiS(##o}{qoqv{pzr%U*Sx1*o$e0SdQpNK~jkVo&_J?WO!s};+Vi)@fh{IJTsuz{9 zkG*`X)LVnqkmAkTBu;|2f1k*k7o60%lPk`v++dQOb&iHr#A@j#nXyf{?ViOizcBM=ye$QJei zhTnic#ZJzoU1A&s}Oa)Y3MEP%(t^F3pEWS0e6(BCFUuc zJEkWmbml3kvK}XAlV00$>XFJyzEbf@fQ^iW<*uENC`*N^pO=sz>~a#ZPAyMXnIv*} zWDYBMHi3M@F$V*-u>Q^|_<2N}RK4{`>4%8TsDAttrB@r0_86#oGAI27t;?MJQ^%x$ zd87*V2=PzKiKBz~xMdR4bA%<6k5@V-%p>KG-ZRy^M`EKQ{SMK73UJAM)T^ema0=1Q zv*Bd^kPl75k>RFbbicTsDTeQ{YA7}FnUc)OU(wpFi<6V=kNFFnb1BZ^qfjxqx6$J@ z$v~AYiN&~WqPP_;&Y9=td}NYk3R9QlEm+H-*Av&wD03wv-AT-BEz44)08r%;^eqw^YXg znYtsH6(|6Q`^}4ZkcG`t6bqginR`NeaGvxxYSap3K<}7jYhRUWjiBjGVIpkZJAFtX zTlxj%+$IUnTXWpdcMu$=5cUi#+@;n~JKK$OKzAzEB!UWtL4^1idM++bSMYqa&$< z6F!dPf(?|~QgE4hSZOHsHDkyIDA^gNq+X6Xp)nOLw82`ld}emTm>oacCm@=u5q-=r zlHJMh28NO9HvE$`EKA19R`;8U+A>ercpSH$m=4N#BbJ}Z;qZf&he*T7Jpcp5Ojy}O z-H4Dr(6o?$@TovY2v%~kWd z`Jpkgq9sMyEMcoK3-~9-w8$q}V*Fbft9>Wid(X zT-|w+VgeA@DfqNL-d2&6HJ6%esVts22~h*H{gBruN<&J>g00RhUYn6I3IMD`vP`{n zW|pqJr077<=JYIfrIPLpl_D=TX);EYYDxrvp_kp}tt z4@r(6VD0JAfc;pVD}D)+SPbq}-7>boRRZu#HG##+V5|YJ7R8tu-6%@k#4*dwCZ^A* z*0Q!An$EIRe?7DN8w6uSSm)$sYHK=E-B|gc#Fv(QpX!;sU&hupB~i@YtOiD1V+$V` zSys@}U6G3p6K$74H&bg~_@B_#EQ#242`ekecExu>$k#xt4c=su{Z9+&@lsi8O6pvu zk|MXM-gR~)<#EbAawEGOM33!^Ggc6+tfAALMEja|w%+FAmQ8{)%AMx~Sz_^l{d2@% z)mC`4eZ1lIo$HcyCFrR{8_dZDTkJ*kcPd$G>uGaj=09euQ<)6*IvXq7=c|o>098|E zGsQk-tFy{xqnGZ+jf}@}u97C|swt|f398vySCC@Z8r1@|4xKDi8z?&CTltuad`~IB zQ{x2$iSZ$gppu=I5&|a)^O>f!^m-`jH8l}8-jym3@+YWddr4=YdT)1)o$3s94gk-p z68gT??Hw^ltBqd5Bef~e`ps3;V~GKYj#UL)xLhTefd}Aleg%^m8PV>S)UW@z6hW%*DHIB7wGMCU>6biZ{PxNMWDP1 zN*lim>4P3EuxE(ja5ZkrW%WCkmwGh{U82(3>8@qjHeu;+_oPyb%H? zkaj;*XJJY6l?|e9bb-GKp^|=GNM`BugGEZ6V{kRg+XTfPt<=a5YMPgRuNSeBpI2C0oBN-+OVkCy3>vfpl4N9?@ z#?PnamVev|l15#Kp}R^lUnEq^!RLit5;Q6!#ASG>@-;%}@W^ydQSg$?(BEoMejT;H zyln5oB<}GA6Z;WQ<8k=IR7rlVij85J8e(O7_^jX-N_Rv(i0S!V;4&1Q*RXSkcE)jD zA|(ht;pF!uz2MlB2yC9t1DccNikY~!b0juJnLRMh=Oly5!0`m(Ly9pCw0F0_nCBt! zg*hFd0JO_!$n(l_H4)SG_&P4#;a9$lKp#j?gC!W@Q;aa`2vKCsJ1tGq&(~kOO%5`!NHhJq4#0q=RV9VRYvR;)`)D*4^pe<>zjy#x${(Fq0 zj3LZozh*%&oGL*uyePq0&O|}C1VOF|0rI)ngt2&AGT_fNh>DfnI(2H9}>`%mDpkN1t>o?5Pcs_bWV08%8 zO$aG?h`(`=$n=ozDjI(4jDu5btIiWlgCLVydd1zsC4AW9)7j?rhDwHsh7=&_Z$m&b z2)qx*GEYhveQ#|syKaqw={%uK|425_MWJkP*GGgq&bdIe>#BLtTPX+C6sh_uVfzZv0CefmAqo2!VMYkz5f; zHNZqMV#kQ>BfKLxjw%`rz@fNoP^lsC#=%L|r?WTh1*DgdUjJ9kX|X>&`qZ==iijDgVa#V(p7mU6;_M6QT3M~`1ugJwXX0fjsqfh^KAoiR`*>-rGGA))AE8=&V5WrNOmTjbgkVi^J{t^r6~t?m zBGHOLs74f2L+;z2&EPku2HEUL#sN=rR1Al_j=$`I&=v)qQ+ji7{ZFTfgi>J9V%A;g zQ+UB}UbRlhO7OEHm2AMxC+5fzg3y)t?Qk*1^G||M1!#7M%Lwl!OOIj#AWP>>fna$U zRS^x4v+s)aBgIz$dd`oHHBg+wDhGNXfkaL5{z?v~taH|)6)H`8#=II6p0{29SuAGY#v zUBuIEOy;DEIn|P_xmgk)MOk8W!(wyl#FhfQl6her8hcaQbw-a>*I+h<%xCk}wM0}# zTJ=_Fws#-Dm*dx#O*%RF(Y9Q4Oh)1H5j>F~j||3+D8`LQtVeL^D@EjpF$HQ|QW8HR z>alT7_mbO#`$0BOKw|4^4#n-ke--t!Gz9j!JEZ1iy)<%=!OJ=11E9zM;=d-v3fk{R;%silCQ8iaIx8P66H9GFQ2)ubq}t_fXt@ zr#KlMO~vk%QKoSBiIZEz>Rs|7Z-kOH9r0G3ZgI#q)F_qkBML|q-vax`XN|=Ed~S5E z&KwU8^d!zF5;x^O5L*6*zeVpV)u-m>pDvL4@9|q659cq+-qwlokLOQ1;;WBaYEkx8 z4HE}z@5q5Oy9?6ZQtRX9!54l6@?S}X_opa>z5OQlq^6|$1ybHINh5s?5?|ng_pqr^ z_7MerMKH%+HVFI(!oL)(ED>Z}n8J5J>tTYf1w~cRw)%GlJrG2|WTFSjTUGS(B=JM!tmnn$g|xYE;cevZ<1B6VBPwF;jE=MWJD#+1qk`y_s9i zl?=XU$eeTzxvAb1q}{JT87)>>sugYqLB04mIXX7)QMJjfLF!jz%bpu%E=JOtV5xN- z3fI)T^^xu7(_<8yP1iiXMrs9?34v z;%%EnJA4>rCq}7r@eN#mC{uzHs-SwUi6Jghd~^!X_VC$NYGKDNrC{!q{k4+lc(igN zUfIH4{*?Zze3Ct8s)p5T$LhwhhDp4}N&aHhm%ThT5c&er-7J$h*X1|>^rktJjF$It z*4q~WEwCs$ugQ2$E4_@jBy{&&MHiis25%{n%iF~tBvGYo%f3?6Owa@CwI>%kxZ)Je z(wtVz8-W!&nY0P_NW`96IFpcbBY3l6kA|%q#qrzZ35ox(@0m=X=aVW&RHhi^GGi8| zVkqvY+>;cees?i5x+IdGRxtm3F30~h$>uGUDAbOKkLqWqi$B!u*x-hs0ZV~G>P7%f z+BAOQ$S9wPLE_|4i-4&83&E6y(_h;7vhbvBd&+d+@ywC;)D`gL%@E-UdFl**^29oC zNqy>kWAOZzyYX|cTfN2QG=9!}^Q&3qTD(+3>dbxWjDG6Oe%f%r=n(_C5v$|p@N8*C zKX}@3XE)RGd>)Z0uou}&>Rhl!K5xl*>P!^jiF(?Q^0X!IsU_>F<&4(z8~z!(cqSL0 z&9ddB?J>gPlqC+(CJ_ZmWQR~fRB&q^Mtbgha9BTb9-ZU}LxylUi zVh5R&z~uu1kbAs8F3H|D$sRAsUJuEhPZ**C>INdnvMtc-f@TX-ipF88=I9J*#Hn-y zugL}|F2lLYL$yFavwN(wdY}PNgiX-i5yrV`V-1f8fk(PPeU!j|+R`;y=Cz=NNn#Gg ze<c17!{Z$WO%O6;ouS;y6Xm){M4DqNFFg9 z(zU3@#mRMp$z_t0=HvHyCEHb$c#zz za;2YukV*aqk$3c2h2DP6$uvdkPc(6O+Cgb*X(0ZSD3OetQzN<(;r(mLOutb<6r_zG z1_CkBiP_K62$vHRTEh6&c-7&}M2Nb7No#eCJbaEDjQA$Tlfbm^7;>ZgR#s_c~j z5E_LZjdHSm7FNtCfC`QB(tPQQKv!mfsukI+y4Rr)Ag&5vW25#dvThY+Tt!QyYUBn) zTm4V4s$YDnWqTHh8~bKBs96Vjy)zfi_p*AOei{^;NNd3|wlL~yuVH)TTI6@Z<`tz;nI*LF)c@16q&8V4GXKsAd4_E!Qq4LvSEYANCDqk4O z&~l5KJw-?VT7DAGpU?`=tQ<(C;=NoETCoal1j!Wx3$SmYCT>{6g@s-*(k_M@w7Go0 zRw@_i8P~9_c;}`)K&Rw+G~-L81I{4wbnn^2>osb#eLr^IicHg*L%`j=^nf$7Cm39v zKY*H39!IR%f|JRG40$05k_Pn#SXaDBzC`FE9nBT(5*Q;`;d^rerFP!$?VY3w^dS0gSl4>@qZ!F5v zRKzzIH6ufhwql*JA)L8jaSB{Ys9GVC*NrA(4NtHN&o;swt(aoewCz`UrpYdDji1q4 z$ZsuB)eUjI;IdIz% z%G=hxO2p$0SYAM~PkqdLm=M{QC{vU+A=6O z1cT1m-of%}OFKOa@cna6G?Isgeat*0P1+EjyGLI}cPME>ds5%t%Jh}H)`x4m4;f3f z;?pU=89OYL$LGQv4foU-;Yv6#-xp(D>gv*i2jRCp3~!T?oxh$#!ME)>ftZ68O~nSx zS2S-9vmN7#tD815qVUXjaP}EdIZlmBG~zf6vbLFhT=8(uFau07n2p2D%!GxM`BJpfK1 zZ8;wS+ecp~(S%xw;G4x$wom6L7ELd#W2os_R0(mTK{&W5juPX`3VBcSMJL+kT*c92ZR;G=>-4zr+$v&5Wox1*GtJ@dp zC0W@kDfff^kkl42xFcHmfoJ*Xvv>lIQROQk@fjZf!ie~=>rnYYDcUoKp!BGN(6;~LYlUCWHT8fAiWH0;`5arTeemK0xE+`6D?588rnKWv1O(k#0{gIl zzGIbqWyUgQ1~_UVm0C=smzLyT(F9WDr%7=5{~U~^ z$9R|Weu{?VuTQ}H>p>=^dmDP)%rZnQl!P=qx|w~VGwZF!E-|(AjCAHb`9<}ujlaej zseV3POH3|%mzu_@%*Hj9RK~>C_I>z-vOx5~?iUL`XDoP6refvZG7n}SGUwFE$Xtpl zbv`N$n@b39Y!~*utDxknfq;;$S)hV>&aXT9F^f)PPvGC}kI= z7#6X?u39cRhOr@YHz(cst3~K;*jz1C-W9XK_pMgmH>wfC>dSjGM<9W+bw?mOgqQyZyGe9A#mylR zt%zHVcws9{PxJBk;;e|DEh*=*CPqz*LEws%+bv!w4ifz++!;BfXmV)Gwp?w zS=Dwp&ovo}C3{i<8?u+(fXKC4vQ-;mkez6U8+c{2?Qk)7y~HPJ!PGb>>6AvNEm2Cia}i5|*!x{aqQ0eK zc$2NMDH3}hv2OCrO5RK=WExABXbak^SrkZ?jo0Y9Z9GN&^$VqIw!kZ%`?$*7^6Ll7 zly|6>4O5NXBYIc5+5|9P5U%uVM_6N)tr%C<%*<{4gdG_zB2DhKXVCP?Yey=Ymv=72 zgr||j3bEwMaeVa{q2?SR$>qa8B9bW+ynIDj$=WDlwjKXo6Jt+-O;C7RdQU5_@!mKk z7w>3@7f7O2a>ep*xT5B=aE&~&Fz-~GFPwD`{Pj1`X@H(c%L^2mRb66?zIf9Mm{tqF zVay8|-NMdb%*N(gVNXz3bKe2pwa-?aPjJr0n1{$GNFU&b%(gEPB{M3kBt!>8L|iN& z3!+dBiMngz5Dp5@{p`sxOb);8JXs0}6N~pTUL;hm^eTSb0Ocy)qh4ViJU1_aa>ky~ z#(w{K?d#(&rytE9sGO@4=5_9Rdamme2quS$r= zM(s;RJKo~I#_Ov?zB%~gEE#g_h|hX&I6Rd6V~>oaQQXFF8XrD1_+5u@Yo?F)lMpDG z;gk8_X>V`b9xb;MBYpw`p9#}__{1$i7t-{w~Tu(5!iwqB$+nBOv8lJLG+_t<>XPdUZkrNBIPoLO< zS5D0DBssC)^y?QN%K|G*9{)|7Sh``f&1>-kPev7#bujwCQv#;-eQ8nj1mWi2ETeRj zo8G}oZWvd1cZ54!023$=;p3*T41a}zeXH!r;)RWGA!wf9C|mdb5Tm=Tm)AJ<90KLGeCncR4`4P1q815&_v-zoeYacSgeUdA{|8VwJ zL3M`DpJ#A)cXvIw`@!9v;O-in;O_2Dg1ZF>aBz2r;2t=*v-$0RW@~n8Yi4WS>Wk;% zdHUw9?u+ivx0{I=k`LqDvAu7SHpr`qju=~Lw`?(SoxwB0(Jy_}yjtla)U~;#L)oW8 zJOU#0+9m(;VbC>QiGzpqz$qe3(zzoal=~YU2g5%S0U>-B*)SV8`0aH2IQi{GRb-X{ z?)KCxtzlJ+#mlv3^^(oYy@s4hzft1$TLcF{mK9&QwF^2dHi$yZ@J}>E7!#&AX(k4! zrzOiGK`JRM3qIu^9pWNY$3kB5<-RXY%JIUani8NvLJN%-gs5FN! zXe*V+7$T0fkVfZ%Lj5&N4*tU7;B%jLowB1VfDV<{u`g)&XYNTQceUlVCm#@axM0ID zOay0zh!gjwY*<#$#M2z`l7C~)NEv>;QoWX|3E&uNjo7s?Dl4%c{N^v$3g8Z@0+nFl zVd3*+8;RWVU=Q`7>uX|}ENEikmXzA}s7$nFLN9b<(ORNl6e{$E{ys^77n{%1xj_KTK!?aS+^5ua`uSz{sxP7iiVy-3etFy^f3;~QeBK@yB9_!iLU@|$=Xg-s*)=Z zr}esB-=yEpP3oAXy)!K6n6>1G`_shGkPtjY;!}ZB;?O|4(V56^dU@ohCz)9c!~8y{ zLmO%YQbM+(yUhA0mgrnBb0uuTr08b9rUdgfCrlDEb?qb4LWivIu~|1rvA@bti3(Db-Q2T#m`6UGdSy9(!VAs ztnZu*%RJz_^L^hg+`C5c=_fkEizqPTgDtr_hywP+B)ais#jNQg9(1H7D}f%5nM^tt zS$5=%h!qwA_S*U)zc148q?8s0mZu@A*K88K!K5*Rq|iw(kH)P3nZ*pK8AQjTj)-;x z=>p{TxQ(#okh_y;U=@(NY1|?Q1}DBI-qzv;ebUruEs<}%VreslqN&<>2bUZrV%zS6 zh1P~|VR#B|H9L`Mh1|CnQOdH_sk68XjXN^I#kaVnq_EA?E%=exj;XjXR^M=tj!u3m zRlEej9NFQz3I6QHi40L#ZOOSy`#xlrxqN{TD+jj~vJzMHz!*69^HZuySgcA|w(6ZA zIzmiEQk-n?x7Z*^b}-y*FdiWSE)|7sJdRqEaIA`B-lZ!!fwmNGn%95z-+HllY1lTx zp6lS`=*qZlpSkOOno_n8n}a{XRCr{B@8EF27ZV~Va1TH>YxwIfARS=-#QsP8Pm|5yA2A`A>7dGzLaFlU)yyicB>E;$G-jbN zFeiRSWB@CC#=oQ6r*nlw#GTo{f{faq6jC|-b1{u10B)Vg9x2+kncq=`?V2D>&w!$) ztMnYn6SMruV(fd5+uTUK;X%SFF0AF}8)Q?{TJ!`T*Y&!yl7^mU;F!;pUz%(Rc zn9p8>KW2zpnX-q2cBTTky%XP;U!@}I2|mR~pkW_szBAwCepiyPC~w&~mOdsPjd_I^ z3*0o<#27!OSgN8Zo1w#D5le98_;G@b%!zAOl$NJb)(Rl|B+VcjQ0%j?0L>(IH;nduY;X;aD0l00d;RcZ<3tk z+Z09ZRm8_M)S7TwqTBvgD2gedtJ6tSY0*;tCPJ<0J>s0!1N~Ol2)R0%Np+(pi>~<~ zG%`DcJ20NJH^VYEd2d&odrd?BJM%;!qQ);(+T zws}jcjFW)?H}6uGSZ#?Ls+4imGS?o@e&<{^<_pltwTe|c#R#Lz`lKj|>QiR(^0qZy zjCVvOP2?#^3nT0Dm`yKE+GZHhC!V&9XzIkWMk;8Z`GAOpo_!s#sT)2wY!}D5oWfg2 z=ingK?Fz9>lpAHiHgGsR)Y0DoEf}W&Zg3?a%7ms8ZYEQ(x@`Q^N zTLm92+B!aR=zN$J9MLHA%Up<3goiZU$(<9RCcshNT-6dd-P)(s1raLMc@XAnXtu(= zK~xV-o;KE9FG#f0Yw`g!42+fL_aEeXNm~9)Gl4sMwq6g_Kc`Sa-> z)|mkcFU=ER&7TN@9>L=gRQN_&7;`lh89J|5t(#qR-Q1s5TQ}#fu+Fk!B)K4~nQ5-o zR;9i~Gg;^5y2Ka-x|Ev$+Ru;P4#|&XnD`B&!$hg2b~VN29k?wY(y?JASx#fA2(aHB zr*TOVm;*6hhhEM%KH^(`N~vfHS)Uxjyura>(D0986IJV9@tpDAb9TQXQHD)i!@(j> z01@)fcXX0rnWuO#z>6qouz7d~oC9Xq=J=2soA0|$2J?$>_LfIq3Vu z=!tU%k?$J-=AYP}|9T&E@5FWvqwRU@%gota;MvE8n&l(7_A-F(D;S-4xf=($K*ALa z0!o=alOD0hQ_$d?>=R~`nViHS;ZEOcJV&C<)iPbhm;ajSDj8A`uT$z|P+3guAd?0eHdm%Fct2c_4SmZe$4zhz zsWMr3-kYcI+~npg%I-<59zTegjQ&Ef$%yve<;spT*^~Z>~$s0dgo=lSU}P=3S%OG z+n_K1(e&hPiTc}ce)%G4_djZSO7dA{{>ga$pO5U{$=unI&C1mMpKiy;(Sgm*)ZG4` za)-^_+0By8{hK2j)c@`7KQAEv+cQ-KC}`|2@bK_o^8Y7y!2i8FiEkd3YM!PR?vkcX z&Q7-GrVh5gmTuIVre+S7a!yvx|D_bF)v{N?GQc*f6mC%@iTS0ef9r&+c)N(d%|+sd~Kl!xkh+zdf1NS ze64AH;6GgZL@R{k3!Y%`*b9!}A-3QHxn%9a52{6&Bad+B{U#qomkimZ9%LUZM5bc+ zt|1pk>nZ>&%#+)z369$|NC;+!$+`HtU60tJncr}xzq<#jF{tS3H0%8M#*~8-rF0{* z^OG-GY{bHKy36)Zc%pDjMN@L6kN|tOl&J0)hByB@PLw6-0W!!cP6VGVlPa={Cc<#1 zwgCHND!YQ;wr(E8^;(bFJohyxs}NcG-i= z?m6UYp1?wBwS6)9A8=7yJ4TKaBU8-c;t@|`!|HXSt5vc$?;#Yjz~B7IYZC)(AFbBQ zxq`nhR9z9@XPU(ivZKsGb3Cq@;IYnmDYZq`~dPl#W~Z;Vr%f};cOvII|8DCLqT zD{JE4bzC*5=CL))#H&^}ba!gZh`$R{Y)UVggJu<7+g-^9Mwih!eeI%%dbnjv4VGsu zJb0Iq*t;;fspIP`P^P?XgOE26yd|Ix+-093bNr)Q{KHY7(Yg-p9g>|JBzuQ~{Ub$f zt`1-LPX<}VEGJE>;&4Ek!-RW`<~Zt>HKlTvHPpo%%PE@jZYVVEKcF7z>1m)IiyHA` z7?venNfb(|n(1R$m}AXy!qps%fa`uK4-j2%QOeHEnz zVu4hMJ7Zg9XH~WLw5z373}eYX8W;0%G6 z`kn;8OMy0}n1VncXGM;NY=eUiY!R^|Lu|vv7-HNg;ST;&?Qs6n(dg1?qqf`b(!lc-wvYJ^$+QQNX%xCdlPR?u*6{uTU1H+ZH{p2y29E z@(8e31KWpP`AOI%YS-U7EH{U$Q+u>k&5&u2@;5N)3dh}%YemA4Xs{KtF8*+xuP*+0 z9lB2Gpd>9;juZpelJsY~;E+YHb_cMWZ$@$myH3fHqJn?u`OQH9Pm6g2xo+yfy19cV zHqDR_Xn`+@T`Jhz^) za70qPeLo^&jWbW&qib1R!xiqjK|KF9ZP+MS*NDs&U|%oOVK)AS$)77I&`lJZ9sqi_ zR%g^X7_V(=_Bka7SK*BsCn?_DNn`a?m*xim@-?k{gRS*0X}sz$EbmdKV(oKrt9c%; z5uQ3nN+Qyk&hWUoSGenJj2msVutbR)^?tAY;$J6GxI>)OUC+7r>5%wvH{A8wEx^Q< z*yeO5N6ToCy45&d;AoVN=Wrg+auwTl&m2XY676H(!r3dlEF39i^H+(@;%0uL)Sxsy zpa-l>m}7H!ess!I+A~(?V{cj8RTI@Za^hqk2iu*yM}#%E-TOD|_fenq#ik0~6(7+Z zKlhz)X(t`7y*cq7LJqySZ2dk?tIU3We02Cf?z^FrYJEX%gCrKw=KNfPH^+u2#E?*> zqz%~J&V4W4jWCjDl~c(pauA>3Be>)X8_9ZzlG zK z?{Bs_$*hhb}kgA1M~oE9q_#@L6Gz*5+mad8>C1%%SU8-_zt}ZaxO@ZoiW- zT=I@K_}VJ9eqOhf3D=e}^)%v)Q7Z{md(2nzFbgOD`i|`u{rh76MMX5eo2iSTt%zz{ zE)4%Ne=Z)B(JZ)35c@D2bFU6Nuz+*Eopsi7tufE>j~i!FS+Rh$=fTa2xw4v4L!-}Y zXreculpF18(tpwC9rCR$D5yJW%UB)o@xJ0&3W-}NZ!!Fl>Fw_QD;9a;>_S%Gt9WG9 z7k?R#j+CFP5h_i__Vt7rP716U~NP-uWe457(_CESn(M(Z2BExTZC@=JY7Lb zogHmXnQ(!P`2tPQq#-IGw#_o8m2Y9?Bp<**UD;XjL-_&|-&p@s&3vp&W_BUbS16vW z{xfRC3~8(f*rS|NC#7!A=!b3A#(n5W{jUyd3l8+M`&Cqd-2koEB-jgBS}=FB=^9OD zUY=!REt4Um(RAVjV>s`$E#7>)s9e64DudKR+*;i55A{v?Gi{R_{s5XsQxUmCvXnp> zB|6hPRc%HVo+_j04!r3l3y;jr@550?tij<;!day0)`0k3`c;mhbt!T`M19*dh69U> zP;;X~Lf+%niX($-6t$e@Ufx{`Pew2gx`^O?5SmdM*W7cunj@`2TYTfUIJ zc8Rk_jje%>LQ`|3=OVJj<@k%+0>+|*lZCstgL_lAwb54=1fZ)Ec>v(mPPx%GY zO#Bi9+QMS?MY)Jmn^W~)Tloji_TjTVVx-uJhbSDyGQ7eO47NJ4KD-hIN#qPmrsEo0&VD98m-E#^PKpnitB#~32$o-1kBR2}~e zd)`Fl^~j?lBN{`Hh@byP`GNPm_WG*Z zx0==!CMUc??-(|pAw1W0hTa1l?=`|OTx+;uyQ+Y#SCpbq z*>|s29U=1G;h|8A&_jxigX*3qTxHHvv~S@W#JhWi(6n3tnbfseNnwYAVjs%I(mV-S zM`Z~eke{FgwNjM!DoNsf)@CIAdu&9?<(-9v-B*>U`8riUGI!E)iLVv+Ha7>VDkd{l zW&+qKYRW`04{q{AcEwUZS<)1F0+GS(!+~j8fG*Wa7V?47v&*b6d;o_||@)F-ycb8o0@STh4Dv!6POzX{hwiLF! za-C+u4Lm!z&TCmJB#2WC*S0l$D7uWTW+GJ4-QHgB^O@PIIzZm8w6L4uNokBNNj|*L z9_}`q*o(^=zslenT7h8{vEn8Oj&J@_8fCh2b4H}isy{btsMBY2I&c)RZW(KH?z%nF z&j|`6b}~m8uBa6;r4>o@gceD_O9`Z6yWhl~`<{&Tq>|ms1ZzX@tZB!;e@2qFpj(gs zU2r;Gj@GkE%x}^iT7#E=g3u$jsEopjk)3(4&DNkj*>SlueTI~9LyI+szj!IM!lQ+* zySv2hoKwn+Gb~TiQqYntGy^g7-mbKhT)skTBCa|#c^SV@^o@k-6o?gp?j{@Uf2wM< zu|={at;)a30>EYD%m-ORrOHR@QV0{u)49z*W&r)h@;u~QJL1&8UnblrJi$QjQasg> z?P>R{&*u=3P=KSgt-hIK(y=f0QopZ?E_zgJAne;sCr9cY&azq#&~eHriUZyusMrw^ zs3{t<^$FWly9G;oV5#O(=l+&^nMnIFA@aSK_(D`Fdwj}!eli}oN=ti=$z}WYN*dA7 zDW3V(-ut(E_DpvfI~zUf>d03w-b+^pq;~z?tC8mr_Ex=5;R; zck}!cxlhdleJ!v{`e)pr_2&uiQG`l=W7`RI-pDRt@T+N#&PZleUOX|QNx63qEUzUw zzYodt69FQ_LE54nZwPr@*p7ikFUos1O!N;bp`Ij%axsSYygYIS?ko0# z;YPjoNNYDdn$l9Q;-iPwE8m@2^oFn7-r|y9Q^QpaQFy5Qer-0 zViU#n*QCu|iG4L6*ramCZ3v6V!9>c96EZQ>6}Kl9r$l6Oo%?H)uUS72P{>WR5Mlr5 zr0+uE7c)}9sp2ogu`?>xGx+Mx4gF!ENQc~}>EEWh{*eBYPeH#;cP%0YV6mV~_9>VJ z7|1RnK{174oio@vmI_rXSeRCi_NPnk1x*00e|>sG@cQq9V zXHvt+#H&v5htY*!sLE!nmI9E?3x_-Q@kM=ZY};zMLgH6_gsRe%|4*l z`>%7-qmm7V1%Q}al}$JG)hnY%)a*3u*MX!^Ot_RX%o3`LrBa4zjX90WNLSkL2!ipv zG|R7lOARK+(>T;YXLpo@kg2D`5TlV$gVGKnQW=7U$ZibYS%zN7smoSjP=q#w(?%z%GMz`UPmddmZh?8wrv^BFBhGyU^oi zK2&Nr6Xyg}Qfw+moyh1Ulv9{|86~aNU92r@yz+Y1Q~Cu`)0YX>4GeDHlea<1$NFyZ zmhM03>nqIMP;hXxQpU#_sjh?yj}a90sx{ot0E+hdOlxd;zn_)t)0L`oN@b1mAUs`R zmWGb66`J?%h^&URu%n=<0to=QPPZQjiYndT+@E)7$(~4jK%CeGAK_JjxWK*6xUb)8 zTQx)7x`MP7?p2o`9bx2H4BE}$O!qBf3zI}O4g~9=P6vKT4HwK)k^=+yQkXSMy@wE}Xr#UD+5S>B<+JU1W zNq2cUBB5gv%#YM^PmyGGC<3J>-q7@qCh%E5VzUBa%!jJ!@kEEP!2%W0CSMDla9FYX z`Z>U`+R?mo%-bb~d)_v9R~BOPmXV>XLeApzcD8b?tb^VRYD)}mb^VXn)VHc3S4^_H z3jRrCvkLh>;(XIZihS6rpLP&h3h!et4Vl4+#DmNdKO>TJSdc7}GL_{jUB3(g7i;)} zzXsQFsGIiVYU1PbIEZ8M$Q0iR&WDa*yXFqZp}GK3cmW<3323-53FZ%9(LWUlKXj0> zu97?RD0c2eLLMQkG&0y#u&S1*Gi*_7mJL^nIve$FzjhxDaqIJV*>xgi*?#AXZX?q_{wq&J6152A(mOye>}=|^YXvDSHK)A;O1p&1jXF>1n(k~4iXPE z%QK3_OAN9RV8fZZe>nth(ozrj(ySnIW5yDNqYpo&k08+EDr>Xv z+ROvtZBzc##Dm~%Z{^i7VAvP`0L8P8rfcJV35R&;5JO0pK7NGd8`mvPaoddO4VR-< z@8VtI+D9M$DuMJE)a>$!dhe}Ke+8EZr-nhU7!f{k7sH{aW~E6ic|Z5%)HK2K9N#X% z?H>PVF1;l%P>GKZTTMK+q%jbVg0QR?S7$`6Tjh|oFql$jmeRUrC%s_k+h69;QG|?S z2E!!UV~!Y@+3Cn)rAV3T0a-`d@9WHIcJ3|(+VKSXD0VH+x>ZJEM-54e#i;q~;j2Gc z`qS5ePjSn^M6I#lZ;t$^c1+h%%V8s}OHUbXu%9)xS|CSuh?eMAk&k?MjGqsZz)j?o zLz$Qk!u7Wt5DPUGN3?--u5)S!QR8pQzqc(U?|>!4m;v-WD))TrMtJ3Q0*+J(u$E@SKeT@`BkbLQXnyC9%<)?N!#(`2h)rmK;RQVxhKEwjSkzC(x@HiE- z%!%gPfmPME_{h}{G`h3vBk*UI7 z=WEDvV)?ok^Gcl*)|N^2rBrtt())Vr!Cx=4M6Vvlumy(Hrvfum%8H+g1AtMKkIYNh zLY*&%=GBL=YtPwEF3904Iv2Veuu?lxz`~*Y_02@8tBWEbg$#Ve!!+JaC9DQ@;V08H zjW(-(MTGDjacN0Bjz4E(UxSgVX3(@_(RyoRLM8kx`l+jst0&w^>4%^y_ zn#kVmsEtn{m4^+e-zv9m&tr=UT#xQcZ3!o%bQD^{o6{gJa2W7+LVrOwshmEv&zS1r z*9Y9Xy8n>t%@@}qq0yaH#?-2e`bqcCqJRE7RI1enAf2}?Sg7t$j2HCN`nCc6Pz76# z!NAMz4wF~Xxd-9|TQ)0Io}~(hMx`}`+$Jm@OFB)ySFA zW-^S-_}j3Pq^4@iYHe&x{lM&J&}Pc%lmiY>*G4o<@)a=jr?ANIRVA;!=Q~pCO4RVm zT={!m)hkUoaUbPbVEjnS&L6+^T!M`pJck_P290>U8qH99QH_klBIX%npws$mk3(dM zkk7UZ|H7Zi=8w6K!piGPXrRvV3Pq26#`B>Q17lY7o&Fn#%gox2MU4&L+y!N!}GPbb-kte|}CwO1iFr%%W{T1Po znfix!25VA%Dti}*Z|k?kRtV!(^m7*ylBf5ut9gD;jldgXpZ3JhW<$fI#qCLi8p+@O ztw}q&NZ(f0tw$nsWnDzaM(p{Ky|Z{Fn}0qT7HV7hvh|q|tx1%sHqI*c0r>U&$2Q7Gm@`F^ zeLrRAbmhha=e334?%tR`s&c>j42n1d7AILGZwc-cT5;a8!ig~YS^zHoZph!m!~v%4 zIqdkM0AB>!Q*(e4StMbA5bilvgG6BziZ27@OBph7$60axUW{hsXjcUJjEf9fPdQmj2ni+5lK-E6uwplo)D4rSd>cQ>4 zhgmIMG3^VaKs}9h)vO=cf58+gWgBw$g)*Ke0%Ha62UgVo&h^FmD60qQ1;o3YpG)=j z8pqA@uF6ob6-%79iXS|K4ctx05j9@KxE08%hLx2yTFDp#sw#YZ=e-=)Tn^xdmEVc% zX1;b6B{;8%&iN+}G1qq(23oD^;Im;GDkGS_*Wk(LFMV3DUh zK4wSOOxEJJ_u3gEZcwvGnsLu#_O}uBhQZ1=ZT;cb*e}iIfdm(6*hMtkwS>U(U8=VP zKWq+Iwr6}+?O)LI;_lq1=y&#iX1$YmuBaV*aRc9dZ>0R-!+NkiooJo?kq* z(JnhL^*s@0S%9d<^C>mGx~AC;2detoTChrxeEKT{Tua|-BwKFHU?#aU@14<7Nbroe zRv2qS;L^1lRRF$u&T*pLyNP(h2P5L$iVcM56kis?`W|#GlsH{Hhr3%K*yOS>d2-T5 zUrmYqWTJ<00Pj(&8$MtsDq z(fA=4w-S`d@$RTNw=*UiQn9wD)I7sfsdt=CSfM*&%zVw|mkis>< zy>o)v3q3iUg?esV_snH;@0Bxk2USpHBCJ?n{#}#krEqut^SjV{{lWY8kj=ZW;_Roi z=|1x52wawoLRBWDQrcsA^U~5oj`oJVzGGp3UEB0mBb$bKV&nYsXS2NYmHX>&cFPPk zhJM7=1&j+!4o_RiLD@A?t3q=ErwM9}3Uio0TP)CUQF_A1O zGDg*O8DbkU)~7h4cnAh)`C$z#qVu1b#aXvChSent_MGi@TNH_Yk_t9nHO5);v9_LA zn~#;W+y>;)(U*mt>}G4q7XNX)&g9(_xb4QoVHy4NZ2#qx;{lx!TYK#5>}E?Md62_F zEx%MJpd6GbM9k`!vh?JN7D?9EU)ZS%$+sxOdSSeLBg1;AGX6o=pbSHoBT?`6;-Bbe z)qTg%DVXfzQ2lbvIFOHqYRo>xY<`B4C`c;*X3mT~qpv#n4^- z5??>D^zw(tSCOgMc1 zfSZ0H*N?&nGL-rlwEZz!i{a#;Epx!*cPqtb5R{6Jiv_!-W-$v6ab;t>A6Ti;wMQK` z$<-vk?{Rc0U1aDmZuP+Mo1vcWy_Q9?Ro8lolx00!wT)d_N(&x9k6(wEgGj4`&_27QH_F=8 z6p(fN9Gm2c%c&mutjv`~=9fR@W|8mC7NF0OCov^enFKRbzIH|V#2V*j^H$z@~;r$ zVdJ#1Tn-U-#&(o~AcCIZ7jdIwmAsp$Ac+Q$UeTuLB(|4Ra%o?c<18C`%N*d~BQCr7 zVyB)Y1{Gq=1Z;q{T@+Xen&kX8n9bOejGg@s&Ey%WH*@5>`BSjX{oKv&(6MAd z-J9skJwu|9SWY0CqsZSWS^muYR|XYa!?!+IUG>X`3_Xq*EcczaQ1(2TmUF_?d0TF>$qc4gTcY|mf%UpE*B6VBg7H<6Om5;77ki_|5Yx%z6DagAT0VDadK zzlFy(c_dGD#1MOg%y@B)AIHu`tCgr5(mhPFy_x(66zEuplK%aV4{{d$Ux5Nr|NlS% zcTHzyQ%B4HH}fOmX>M=n@n6J1xrUN6kruWvXW)#9r^tDkV%}_-oPpooq9dU?{16uc zP*+J^ueOVvh<3UxdyzDifT;Bi%j<%&5m6nB8kad1MA~?WM=nBBRdn>rdIho!w>q8s zF~9R_I^Z$y_H8Patq+nt@mwxXj3R`Z^{0zm_%k)Dxp?skw!Y?W3}XFA1NLApY}nPJ zA(ZtBYnf2D7{kkzP&5- zgsW2zT*nj2$=!qe+UFbCR$r%Xx8kiFCs3RO4YaHxR?e9F_Mr=Wuc(3MD^#Do1}Fus zfBmZ#^!KYbH^Fa?P+o1CjEBD10>-wm{Sgn+^s+#DDYFrz0qM@u1|tp+CeNVmcaCb` z$IZ>nzOsQ||C$FQxjjM5kKZUeb8=f`FBYh#-Kw{d8UJ<{%$x1$-59UBi@2%d_Zu*j z&1Oo7MySi~Q)|f=N40C<507Ejnd*h(;AorsjEI2`k-6Ec5?D1!KAm=tmJ19_?YiK) zU@7%H3HHv^+t{G7&g{B0i{){s!)JPC!gzE-r+7MUzH{zVE{YPMG{H})22fQPoe1qVBMZ$l$z)%zn3X97BBm}qyOMOs;J^g_nC=iYilDKonmAOXT z$1k~fpn43Fka&v=1S8Q7)sM#Pe02?K+RE~@Lk?g38X;}Rg+&lQg-aI=VkaGhrb3Ru zJrLEPg<|709y*=g+-c@d9O-&TpPQ_db>|+TOTc)Ab`3`(pi~&ZO#Et4V&owY;V!4& zq(RVnP(0pvU38!Cx_W4(p&Ye?ffq#1LOO^UWGXGxpJ!t#4hgjVn%zmHZdV6HZ5H!N z^{0-UG><_}UpzPZIOmguLXNM9R*bibqSTKTfj?J~RnPa03$yZT8+?Fki*aS~UQK9Q zONcTDeGX+Vl2SO2d1aRecVf4eZ0YYwrdythpKp9}WFUYnF-vctIhx3h556F}p~t$x zGr8ffWOp;jaPL3z%~Ha0?bELr&&HJ#HcfPFS{e>_qV97{+YcjJMuRl|X7fCrR&Kh_ zxC^L!VhZzb{qXNyaEtrJDLdh+d&6aQKz($8oi8F;S=l(biSq3uJg*I~;VSUST&Xk( zuvH%ruagVR0uiNoT{!LZrSbPoiA6a7v1 z$l_`uGU($BKqqA<^x;3=K0DKR)Lgm@e0c?9eSyki6Q_CM(kv=84c;XlBp>`1frKoH zjK__XPknbGgB5cA;0foGXB zkH6(-+J}a`RFK=40qN9|A6r~m&4W=UwvqkWoL=?lNFA*Agj~a<97OY#yTn<)%Z2Pk zv-m9(A9^g@<~dM0!az*Ke`+|H2_8cuiB!`v&paA#$ag>HIh-d@)|P?gqe*x%5-NY; zg#2u|s^u4F6^C;A^Fq2J5gyl7kV}Nsv1OX0aP-;9@0MI)>&1#V8rHW5pGIpmlf5y{ zEVu?^&#y#iIZr6xN3QVDq^Ky(*`-!KtrD+I5a2qq*=w|lzy(oeExX32 z62PWb8Xy1Q^|4DCu_8D^FRk`IsKut=$K1D_Fo>ODbLQhQYG^Dq!dc%&-99Lm9G^u| z!4WV}sJ&|S&>d>I{SnYpQ|{%LMs{&tVq;eyZ}ubf<=?{Bu^(min%IZ_JlN^CVEPIy zb;ZcCtZ6w{jookVAqLoydWio{`(fSSFdo`3j`G^1InUAV6f5+~^t}Z)bA2vP z$D9=L7E^jrYk~?S7|nEmjAkb4zzgOY$_MQlN-sP$jMrF3ZzCA*N4eOginQ*!NP5#y z(8wxP<1|lnVzb&FmP2|++7xDHqtV_C6mk&tU}4e3OjU}BDqCNPR-k12TY~sAROt;J z?ID|Ghi_$+@Sw(tG+H{oME!i+K9?&D@cwSZhP)dGlwb7@^`Fqg`4RjA`!Doz|CijJ z@c((}{WtK|;NOV;!`9EB$L;LgY{eA00d(5bkdTHjIazA4Br!;c@6gTk2;Dh~DIv&; zRs$B4v5PQOTK4DC)n9R>7;9T`ndNNMT8LJA*0mf>&i(2y&(FpHE*a~4(Sp)xqTFok;!YN0U0K7Dtlk>nIsRfqGt3x!K zoEst0C3!#i6{jriNHuU2r>xJ^D{$Gh#ugHeFZ_R*P=5N%hIbK0g zR>UOA*QMbBpKHDOa%-%xFO5Svz7g(KQ}4IRW4DwI`-$t&S6rJT>HMQQ zLw}s>r4jiY#&2$x#rAZq9)oBBoJtqR$B~_#{7U{|h3$NeYMW=+?a_&D?%lqFv$NVpO73&i1ysTupNLvS?BH8;v%9#=gQ_ zD7*@^g{MN+b?Gwa>Efc?KScP!5VI6N*mSVA@v|m%{_+A&<-BApXDlCe#kWFQh*~hm zj`*e)>$*A8uj6Tt9cRGv5!o#pGz-0{Z>%}{=#6Zt!8e)RTw zu8rq(4KKf}4^QZ8bL3h_dqdsV)Yuv`@Vi##YA8by=+)wz3FaR|IdbW66h^m;L$vlHlXLcBJaek+-@=!m>elwz^D|nC=O} z+HKl4+OkyerWx#E0S~Ks`{>c*CIST{=0^Xzm{FWA~qIw@V%` zpQyoozhU%jU#}Tj)Fx$9j3+)|;^d5^d1=&Z>3`-vvzcC8$cD*HFM;{Sel?r~aMEbo zG53ZlZ!(4e$;1RiIJb%&cP)*Q>DM;f_zBk~P}Q_rT=(I2PtRme$y+lc{V;b?=kp$} z>nawoPf_d3*~LZ|L1wN^BtYnO?_aKjCB>^5P08FKRh6*PT~#))dhF`;^uND6(Xhz0 z-OglupgfIgwd&B30yZlMfGfn~7lVN#!}x(WCQ;1TV-$hpUePSrQZ4*TC`I;f3Kl(e z#n?4DnwHgw%Nu9qu}7p=0tn>dppXI?W3Rxcx3QJFIRuF`>EkT}*f&`}lC4?L)#QS$ zXVbegT>S8i-fZT237!s%MRI;`)+y(Z^}t+p1^<9I-F#-0t=1UKbFS|s8Aio|jE z8LDWkN8gZ}y_|DV9O*eoELO%k4hJ%bY~(3QnHk_FpdDi$U^OnraYeI$1y z?B8lsH>*zOO{!kU*YsVd(N0;lK&Ko~R=%yjK=OPT4=Ly5$3WtUF_#gVV~8JH`^L~% zsv(&@Pyqk<09-pYKuEOGuxr}Pf=;7LDDgJSthrxB8x)M{WW}PrRk0o+55WXkKj9~T zss=E#C!{#la1uKGjg~4^vXa2j{rH>Pm#Z@lnpcKnnEctSSkaf-Wi^l}BS=&w1ZdDg zVYVs37Kn$P>Y~|Vw_wW;C=iEg@|~UHR5{bg?9aCzd1(trK|f_lO}tV6nHAxUcWEKo zoHxG_iO0WgsYc^>sko9ndm7Ma%*vxHox(OPKJWOT*B>zuw`M7yi?h8ZnN*=Tdh*9i zXl^B$%RirE3eNT6=Uhe~Tu_@MuRkXn#@}eV6c(_LBz@aNO8bh7dmAYPv*WHq!Xu5q z028I*?bB!Wu7Vyto=B{7mkX1V`!1^C@j!mZM0mGrrWn|dzRu{0V;Y?e%z!5nvtdM; z_-#uv-Y58n3j00zU(emt#i&8PfAYq~D5{Q~aLL7}NT2OWpKY}YpKPD3A5fb@qh=&W zNASF8jltYxeD4U@3H`7&D*z+^bsAEP5hEYW8TiSdLO;&!#IwC-Rxm#}OTph*=r5+p z*RwFbF>@%^H+0cGl0uhVgQqqHf3-ZfUF(va@Xw)YR={s2Sg=9hJ5pbP)mgn_Kr}2U z)5s@T#spOV?T@pNO9WiO;*bWbtG3YPfE+kZ0UBh17jeRe&JFxJ9u>O`EZt=(wox)u zFyYPq5r@wtsAe$xA9kr~2MciO%$nlljC*WQ=Fq^^~LFpYH)u z6H4KgJ2>vI zgSX=zeHBaQa+{|h#1=R@l?Yvt(0^{l8B3Pv=)^zsKDK%^z1u0eG&Ezl2LmqoUDi%u zjO)+9H&w^W+6Yk{gXH0%7Kbw1CtZa$iWE>p-^>4-#w@rYpP)!y7@d}NcY6B^utL_` z#2X=g5_K{M=j8JI62Tk21ft6ZMnbOF8fN{+{3SBFceJyNe6V}s=;~r`I_~_EK|#9@0I^yX5APd^)Sq5JMZ zv!_*A>JolE(*BwE!C#LUqB)p>K}eEA-7I&yjr)DdWz`;5f|46$#9eE77FP3$A>3S& z(KeK{wisDS^$+G^GwTxb!W_*@oa>w+at}_bUkbd}M_7*174@mEsSIJ~5qnZt zudED3#60Qc%k+ijReH=-dJ}1m`*xG!LJUZTGH)V57Sx__jRLn^Qt`F(;8x=TINC;6 z4SzpQRuGP+?XLAnteL$NFujk=l)abR*JQ%J=t_0+kAxW=g`$GtT}zOCOD>Ji$350w zEQAuDWoYpQd3f}jRx21Nj7=csD*w=>e|xdhV6e5(x>!MBPn%&?c}v!nixdCI-!$*d zt=@z;UZkZD9SlZDiguW)&YOH$4TZmYFgZ3XGBdB8j$?h6iAIn`a1w@e-1$m{51J#vW>mdpbrbP&+fPUSYtepC&rGCy3`;)P9&4u0`hHlfI5F=vbb4 zzfE|a)&p%++Eq5sFMZufB z(3KXL5vj#3Q?{a} z<;9N~P>Q6$QzU~(A6Af+!>g>ITfhrb{5R{DHTb;V{4CuG-VWfL@X~pMKL7?jK&p@} z^oTQJ%%1!&{RC|O>PzH|PqE~{ay*Qv}1B2j{0LcL@YWVvaC8Zq) zhHU(HWYutx6>3!d^b&#S5|M1Rh)sh~5Ry_;05=@aP{cS)&>K#uo^z>Rshp8?2rrPj zBrr9092pKiTNqLsIdP6JSx#?RgyCgnoPT>DBoVl5@oD1$BiNGE01r}8on|I4DdKNY z8c1yUu9!*bvfRdnTz3SU8_d~MP%?%R5UNtSMH>*fFGmn@P+ehcG6v@#l7s>4DIpI! zXAXF`W56&>g~pdb86FMvo5fvd4fBiyGGD?5jewj=N0?0zy#VLEfKqU|K^`F{ z=*5SBg=O^)@K1E4xZ6S^&QlW??Uo}#Y#mt^VA`8Gfhm8IE2A}jEYdsBC^cG)2#9nK^ zdeGn+6(MBkOLX3#vDnJ@LP!oFy*gkM-$`k=!7vEk+ zp~YPw42jvLZiaH$b!53zj2NMtYI9h+qf6Ag3^}Re3&x;e{~d$*9L#Mh!99{0w{*HM zBOhE(T$+$i#P&2=y$)mQo%m!8F4~P0Bz) zt5^4j#wad>R5jUh@9l+Aw#G~%v%Lb1>tkTl^``<>N$ zTSq2l+Ex)ZtvmF%7}43?AaHMX)vyWTxoOS?H(DQiNmt$AZhbtuE8}L}uoo9l<7rJ6 z)qgq*YhNuoJ~Z>#amWAiY$@14zMMa*e7tkF2I+P7%Oo3~j5@s{4-zO0vOSMLu(mg! zok7^1pu{LgYIMMAF!D!;L|KB?BGJA@YE&?u5r8HP?L5J&fr2+M5pW>kkB~75NCN(0 zV)i~-pfuL&Zuf37W9gIH*LHyJ=x?K8l@97pJ|LVI*Hk3#mB4TOF|jh8m0)tF^~r*= zeLlbC*s7IcNpxT9zLu<_bLP(?f58MsjIsTMA447>^6Do^DJu3dWA_GyDr#`$Za)ix z{IOrFoi0EsT-9m)Eo&rItU#*i1BpwF|9sIJYFYd2ut3&2CR9xY%U19!9TVuQ3#+LZ zGB9SaNWj#pq884t!?sM+s8CfwOmYr9q;#T4Hf&djwoC-w$kC#(*Osm=iYwzAT8z3R zt-9c1Q*YTa+8bN2C9Z1yD;}u)Qlm~-p-)+r1int(=W|k}!4Rl$LORk<-X1LfRT+9m zsv!UX=LxR<{p+YM9b;#WxTR?hvVB-)$AcMYvlLO=U;OzDw5?5xBYJm{q{9VBr#&!P zh3~KU`z2_HOY0RjV`rOa{5j;n-qIwN?O#1XdCifx`-{ z!-|YnsZ}p%A=ENCLSRDWN|}|QR;WSq91%cQSd<+{D;`iqykQ$j&xNul^`B?8U)Kx( zCTHEmJ+KcFB`k54<$-G=IU&RgE)b2;neG5{!S=YIoPxDz;yJ#ifZh>FcS9ji5BcDz zE75W#bSjeJjdKQ?r@xM}cbWm$A9=Pu^(0SiL5|MXhS{;fYr8g{??w2z4R(bGJh<8PWw zH+*K%JRMtq*zUvlP71vcfEJ13$xFbWK30spMwMvF$^uyZSZ?$UHUox1_8%LB?1{g= zV-fqwh$?IR1$=(ON>oaV?;N-&DYt*MTQcCJ?ft%)%c!iCZal36)T9VLDhng;(47wN zM-;mL2pj^NP>?amx)T<5buB1-D*zs&lztV?aiEBQij?V!U0JmpP#5e^GZJRUrHV~T z9P{xI!F&xrw1yr@SDqWdjDS#mt|7F!C6pYP8KWdDn7&(!#`NQmTzDOB9JA?4t_UAH z$a>TSGV9>8&=N!@M^xE!U;sics*Rb?y+999$o7?U2bqtlj|s@m^M64Kk5%WVLJpQE z-XjxaH^N>Z@9CSV>C02mgf-OKoz>Z$#lhx_ojoHKn?MzpZ~Mn1HBrmjJb_T=nH_%b zDbKGFX!JkYW<{UJbt;2^TvhN`f7o5*Hpe;;gapaykS>1Vq>lN@Iebnh+;Kcc84RFg z=0(NAySI0ztZ!N+mCbuE`tV&gG_UFIWNj>xPPersb3O7r94)(>89j$$3ngsFH-Gu% z9pLS%dq@6)1yIJnaRLE0F(^|- z@mSYcq;3pG1HQ&7&KpOWVB~-8uC5NfkAOR_P>6~qkduV}cE>Rv<0GHY#h-Qqicer; z(8lN^2{Z_ztPxtQk!Z{ff~BEiS%#lfu*fW2;H0vuX6kprOp{u#_wcQk3CP`ojp{iy zt#RtdPvVi5Ul!Qt{TrXR=o8j06qgq4{I`gl<~YWG(Is?19{A%*Tze2X)_vgTbhYGq zRk>9ix-Zy`sdH-j3mU7)h+`2XJG1?|0NdGlGJ{NWH>S_}w$6eV5(8ox4y6h+C{{G{IEDUn=_C3h4* zB+n;;me5HF8R>u$rZ9HCTJ*k0-1H?ELnIWmgs*A6#bCsGQ1pRAEzk@B@1U#M`r8Wz zBTydJYHxU$VR^lYyS4NH2iWaQnf%yp!CPwuRFYF%>2+^tCq%3E!=#1XT4&sRD}L9H zkNrE9^V=0%fwT+sR%^b$7(%3_C#OVA*ThWMdHXeB0FR^-a?c9PE22ePvco(5CCYsM zq>nBY%6uZCyRc4Wu7qVQK5 zkjF+AXj4RVmGA8n9==Z@LRN3<_=A|MkWKrMLdcAZLW|jm0j5BW!5bsgX(dFH$4*9( zLeOzU6N+<#XjH&Om!rgs_;C5H+6xU+VGVy-~O6sLOT%{gXAM{GTrlwWL>&Cs>Yme3aK;ECJlYXR|^6Dj72}KE?Cq7&p1suHusH}MaWEs3MnX$ z`6=EY<x#XbknN3c-?gawDU{z=(=j0g`d2WESK;STWpQi{vY>+d3gVjR(T^!fZci0Z~^Nu@;ON1R#s)LGHE2qMvOciD#S^R+LfHduoRcj zm8waE_lDLz7wfDRSuDCJ3*1|bN(JsJ8pHsN#FxS*wX8%ud6IRBAUx41<}zCzMjduL zkj-CT)O1bbH9|$~?c_q)5i;rqc-)MftrV1A%2SfX-&10=v}Gw-FMeW7&n*V~75|^kERUG_e$h%iOmdu|WaImq~w#`e^p| zD-AM7lF$xCg$hS@U;YjcXvK!Vi^K75i??hK7`em5PydC7(h2#|?0w)(B-BPL+=UMF z5iAj0x`~vYiVtA!o1J;lFA`Z9lK=b>zR8y{;&Xt%hYTa#udrR}tfM}*U7`eITa>aq zGk3a~MJ%2jm7&dETE%^>751TCQt2tu1}$zv;E`wumhaN0`e;@* z$vq^K`S=XFx3KY+X^|*ZF_tMjm=b>=KSI{ruDehY(hP0;6HbvyYrkZ^D>u$-t3H z14b*rupLt+M1vDM{qok!n8iQgL02oU`T^YeCYyhpH_iPqsnebs7;;6k9w95($| zG}-MN?;p+CCwYcUMx0;2w0?9`{(E(#e}gL}Xr}M*|H+H^FI=fOepw`W_~CEcZL0Mo z8sr*{L`uEICS+8qGk(DZQc`JnID9nPjw-menoX8=&48>=Y)o0wEP4PbZa0?OfES7g zc3Vlgd>!KS%v3feE~akx_rv#L*pY_?3`x|ah9PTj{=RE!l#*X1>*qvQ$*{hPvMCu>-YVahG@ zj~6tjR-%5kT>K?glvZq9j1emSB&*8Or(j*@V$Z1THBFm z=(wt18Ak=3W#t3&&{^ccyFWB@$xa*1Aga1c3TZsKw=!sLZ(fJ6mVHE$`ReHy&8X62 z!B=JoGN=X&H&KNSHFe7-jm7TEm}XBb=pl`G0+d0<0u~4VqBL4T7mkylD36^ppF&@P ziL*LX5qeXCfQle~XmxavEYg{`G+{KK%>nNIzR{+EnD5Y=lFq`6ZEbH#!jco`xP|5; zxk=9iGRjIy`K`BU1bWeKvos$anSwy^rN5-o%)N1}JtMdz93sW438Uh&OT2#;i=Oot z&fa$#-%L~XXc!-Pz-znUZh0v@!Vb&}MhfIx{h*K0_W+T&g8&Cf-v-G=n-`WaF#SnX zV!c48;mJ@|~E^xxhCuBiC>vfC?n4V-4Crie`@e z*?W2(-1sY|$*z+9QG`w>cU5sVcyPY}FTuDY`Lp<=;0UK3Q}zVO@3~E0!~hw#uN|Og zbE;`c;b8zLkOG@XNB16NX5))Tnbk14pJ70;@-rkytHwuSm#FCFLxT3;{(sL*UOP4l_ zO`4YN5{VZ-w7^yf=C^a%Coqm`n5?`!*`_2Moc=pKo-nGoM0S1Fg0i`wyBNUUJOkHDHA7+=4Zc}db_5S@_5!#f8@K_1{J)OH)o}mq^?gTl`bQO zT#OY)%hV{XRg6L3%g#LWPo+G|NY+f3MB_`1xKX7Cp3_bnfqCZeq|?P!ma$GFO+416 z;yGH0Hbc$esCZ}))1CgHbjR(48X>!WaT|)xPn|f=mI*PhDlR5T56AOZ8VeRP64;ik z-})G9rnG~S9)}qrUwbV!KNn3(*;4i@yb<0SCASuHq^%APg%T@_;xffo%90@7N^vJz zg_+jnNvLvX;v{UAo=-Tr5;mqEQjU%C#6*&nu@2N*hsDw*vF58gQemamGCw%j-H# z2QE$+$u=b)o|{Zh4$=$cc!_pytSjXP?tLtm23}sV&P#cU^2{H#q?@co1#TcQ@F#}> zcl6z@ZSkZc7xPYeL~M@$pC<-VAz##>mJk^D_J82vtCAqvQzUJ^Oro0yv=eM)n1Ga-J z{yhwCQ;@tlrjL)1Fs;^jO8#z4vzVt<1hl7KK#XRMcrW6zJ`!tX zN&<1J4R%o56hO{pw|**~TYXY0<4D79kS9HMk7mp(W=*Og%&DefiHS;0-$Qhe+@7Qz z7jno9gGrMH0D>@r(F(-@wTYi~Ua`jahXq>RK?JhL(5A`%Ve!@`%efVuf#&If>)N@X z8RG}j0`c?>CmaF2$2XUcrEtK8x)upzH&yPE6F%IYZ%C- zP(qg#6bhK7`t_qPm5${cHuUw#TwpeD6l7S!CtYDBMKpmkou^hshVe8o@lA>q zSDQ_cBqrd(4l(GQbz>a(c9erN7LJi~FXJMH2y;iKlgE}WGH@{#fWCCw{;f;mtB#=2 z#+-mL@{nF@MUJ_aVgV&w9~UQ(nSs?N#366$uYSbr)#P$@5Kyr;fS9aWy4hN0#Q4+u zk-%0f9tNF@Q(NEnHgVK4D|@IDCVQ$jz6NNc;a)?IG*&$A4N7kr!4wN8TF+m7bf&4K ziF|aH)*=*TWnpEuj%Zk5VQWB0>Q?=e?oU0eSe=Rt(}o$}S{GEG&82UQOJyKFW7uAN zUe`*Kp@eNkkwpCLT}D3%;1NySFqHHZTuD7PvP8Bcmv92wv#e-wOt>vL} zf$N?aYB#E!LjP8Y!G*H6S-ST2o5=h?R?a#q%p3<=YHHw6MPNh>(f&b9v#zwNmSS!V z(R_WYBe#(vPe-9LnZ;^zVZr0o+=njMRi*b+;FYM{LoVnq_ zwk{F{@kLMk6`76qb~Rr5Fo_*5S=M}?0tt8B>~=d?yJBbA6p8OH4E{G2?e6hKA@_U@ z3W-@dv+eO~llVR6#E^0PQS$vqnE3rA_wm7?VX+a!px->oGZTqlsq>Uc*)egUhYV90 zTjlkp%C_NSrwU&4l>NyOFF4)t81GTW!751yZS+#AtUqmr=lDk744Cby-BwN2fw&o1 zq7jA7{bH8x&6aN7FS^`p)B2Zmq@Wg5^DLB}AZW$;9L8EAVx$oDb38w&LP6jWHwXWpO> zedL=GOZ1>VH;*XK8*yY9!y(}B)|poC@Iv;{<`-6?LmVBhAVw2aek0B3Q_T)zr%r(Y z*)kBxutPb%sH|N~ul8$Cn{`B*3^Movimo4F!v zOgott4bk0g3u3?bRq~^6#D*=p_M-1b`klUPu>T$y$n=%dc65sPl6s-fr?pa;?V5Nr z#%tO(hHL6Ja^>)G1$JPjtEV0W>c;vkje zFa8WQ-pI2+n!$WH;rcuA9x1|%I>VHfNp8FJ4VD-XMKPLUBhTQ{$Et&V{r0D%dM z&JBN#!Q+;5eL<@w1sx!7D{g!||5#(|9gZF#!ai5P?hSKJE2`2Q{OsrBxGbGFjKdpYoF!;gJJ`;j~c0ZLwZ@An{w zbzzzw)&m^h4zHTLVh0@8!r#Bx6zKNnX^($4T8&y>daehaQr{GMnXaSvB;RIQ4`a6> z9?!6-i6d0x$yDT`(-zQb36W})VkIlW5iW$|t_1;;)P%&vOEHTm1TL5ttk7wyyGLX6Uz0;rwSpWya0xY~GMh2=KngIj}5o3~EV z0xaCkg*K5-!f}krpLtXi>ef^ap5b(%j2~&CW(<^F4@uSx z*#xXKG|l>YG2gZPVCFL}(!1oizac9!;-N3x*kXd)W5-;3tts6qI%lxfFzrz_37q#XsgNftM(B{zm=qi8?4Vi_*UOu3mF-kaNf_ zo$7e!INWjCC%zQnOJ9QMWs13vND*__v1Qs}$Gbze?xeGD3T&5_l85{^*Pjm}`X<$c zgeZfn-kNO=e|Jh7nfrE?r52zoq`x2=MBs^A(I8P4JUdV4L@B!Rd&^uZ+tL2sclny9 zpN7@I8v@lm*A7?O>iJ*~NG0GWQZB$y4n`Yw0ce14`U#N+yQk%dk)pLHIo1wO8cDD4 z!&_wN=h$?AI|HNi0dS5Z-l55Ik5|ODf74|CM)F2lKhbRQ?+QToM(cdwDL8#!k*3q5 z`~1~B180x*3En&}dqJ!`9(&-EsAHfO2KKT?9K3D${@UpV4@aT76&_MK;7rF`O{*xP zE0^5*=RBMMrJsuZi`!qc5}g;zX8J)fgV@O{R)+9}_2~R%PJBr`zPZggGnx^^&se?3 z9q=AdW?Tz0;_A=2Ue9PznLTV|rw~%Gd?EN}1kAl7>lhtIG=Fm&mcQKx!X6c^Ra>+bOd*pG z`ZnRt@n7cHt(hy;%C!JAW4RJk>sv>csDCnCBM1aBL}9tQapAqbKvxk0_Ma|)7|j3E zZVj#pth4xra9|79g0k_Dm|t?RaHT(7`SjKqqzy-uO_lz~6j?Ha9jH_qKvr|*8l~7B zah$!G{=~}D=FkEA0qf)e^6o@=B4>FesoOZ`(+}wbOHIeAEr2gn)GoT86BeT~??ojEGtgFZFwwT1)yRH4T7ueP~TR&qNA{ zO3PJf<>`9kD81Jw`3iKA#0p^1nxE;Niruo$6i@K-ORBqIsCE&%sslo{WrcmP0}KD& zsImSM8zf1vQt3^6x&)_D5(o3^^bzev?Cl&Bf#srnF)D#lR;0r<>Wp#}!%9}LM-2$t zC4m;L^k~Zl#)~=BTwTqI35+oaTdWI>h>{tKe0kQ2BIw=V`i2Bc;<)TF>OohvL|=Mz zYU-EYqBO2=S?Mi~BA|<7xwx2bSXuiki2yD09omo^jc$)FQGBL=c4K zO1G!fr7npHE=ui%6JGE>-Su`pwn5vCZTV}h(}NI4DBbtJoQ~nOe2#_66j84X0QGgKFD)VL(w{R1B zK-Kd&b0|lx#*XF!ilV66=Q`)f((3=5s|zLIWRUNr{c`jr0Y)h>GZcmRd|&MPRX*v?B0jGz}`=?)P?w-s}bkfl6ZjY5M_~^zcwkpS`GG7C{=(BMud>n z!`i39hIJFEQ30%06_%^Uk?h2V4XN3)2qASw3iVO4`^d1(J-A%%c1Y1BVuMW| zSj{k{T9UNr7CgjTPTV5gY3i*{3tsk77T5_l9-ZUzj!?0$=fXc5M5IPHPEhvTf3yphi$%7O$U8D<AJ6!kN)iBi>&`akNzRogkpXOTs!5ptF$Ql}X36H>i zqo{e}lW^H$mr!~monrYD%39f`sHz#*Ddwepn7OQ+0GHHzBSO#;0<2#2-M)NWR5Vb$ zE=eZ057AQj!0zGm_~9K9FIgV%fFlb0WV6h{EaiEiUvmp!ytj^znXSC3w_DIQHCzet z6O)#$vTTI&INOF(vd8LOd$P?iTf%u&etBXyyPRw?m9PCBlw~5Nr}m2YxP70`vrXVF z>=cnqX}M$c_UQG7t6f!sf^F^{v6d}Ub+f)*k|)@>aqFG5oBJo7+Vn$qv+wwwI*mhljZ0Z`&!RWasG8!Mi@O~L^ z_KW?6#nzqmkJQUdUR~snegXOG{A}fRT+=s|9_U~ zA2YrGQL>Aam$se%jhxYl!zH7Y)@J@fIWvcfty+eFSWFlg7>JDAM?j8fSHe0Zjr{@8 z6tDx=8w4b#B!>M0@IgMX-l!~*E{I}$e0ep|;l8!)>+=O@hb9BWvca6IFG;-)>H@uC zP=Z6u4U2y9714dHGY}ujMqNjrdcl+erkEv*S6Cg|;{pBlNe>YY290w}-MNgzU`FEJ zibvY3hZ`Mm!GR|_$M@*Yyr)k7w3w?R)t{kXd|h1YI&x1q!aESlw*QsREzQk02}t*i z?gg2zT(mrPC66d>WC{3H+kx;JJ%v3n)T)KX$SVXw)cRol;?CK&e!%FkcrbN`7T=bAkULv?V-S=~*&)RpOm)n(&1ESgZmp$_uhN}?xUG(l3b90Wi)26*IH~=N1bxZG zY@VA{(?UkWNpksO$zl()eEJp4tTGWoI1qf%^@{e7N-%}w5$88X?=b7ozydH(0R)WrV2ac!xME0dkKRS~ z%L1FOSB=h`5E5TcG~<;cJK`PpjM>5O?pTK z$VvDs2H>Z%cd!s>%|w-I%dVQ>E*`f{=SigUM~9XB2^Cwt^#1xP_4+m!`w+j!Q(Y7A zE6%KaK0P%?O0p%YaVMH;>!nY>{YKZZL#qIO-vzEF3`CUSddvK)SRVG8D6KJKs?MZC z)(StOEMwOtu5+s7VULI@arZmXUa)< z)6fOaeExBt3-GeP8>RRIL-2wO!QgoefeigM?kF74@B#JESgK~GV&9j}##rQYWC(e( z!G_8;iV4W&F=*<9zXUV#OlL~s8C$)M5UHELFg^sPNJfTADMWW)*EVqTNF& z^N5vGBT!4j$H|3bMR3fiDT*R403P6Gw&G3W2*~Tr>&DgOGnM<`$!{As$Zi}1ADU+x zT@z-DOn!dFsr|80dW(@s0VepLVO&Ot&Z3<31zHk{6SJd9z8zKK4;be^x;Nr+2#Jrx zONDB}KTa=I6nSI^gPASBM~Xe=imC@ldQs<)DM+U;Vc2YkC?HofLGM}+V#W`S6UU8x z-!ciQb1`Xhg*ATC>ax2}4Z$FD@I$CgD9fxQgLJnjZ~BZm=E>kbfiAb}Q~@o;k1^mq0tBKPX-Lh zpFU=|GNPk9UmCe#OAH_La-l&PpB6c+!&XPK884oLXII?GikaxX*kLo6IK22G1x(Qg zvzR`aU0@Ga&T(fxWB$y&4QI8)W<;Sg#Qh(>Bsmn9wQ(Hu+GWmgKyTKjRi3%lm|OyOv{KOO zc`eR^@KBtz%W$GjTESE5M{-8TiEsQym^mS}mm&)9Xc55*gpQO51inotFTRQ{Ez{h1 zsdE~)2+~~3&8U$ClktvsE38el=qRk3qf<@W?m;70DaC|J*<%V^Vo`BwZoHCVtX-fv zPms!wlkw5)MyBJDoM=+4PgWW%^efkBNv)ys`-Z$%Qp*kVK`hjib{0KFbYZFgU1;18 zuf3$1_t|ZIk!XEUSQ?3WRnXDdCM|7SpU<@M9|OGQhXkl-KXAMHzmYMS{$IHLWK160 zE;9-me?Vd0iYH4GInsvE^t7VT&{5(QX)IJ1mO{f+PH4tIvz>f_nOJP3h)8H(zkCyJ zw}t~_)Z*jpu3N9SJg406eZF5`p?Uz)%+XhLgJ9zW276_4WBU{Vj8_ohX#;>@LjZ@u z@gawX0gdau_q}g2X2Pp7>+P|HmPKhlE2929IoKUS8LjglWXrrI`*>Yx2Rp^t!nNtF z-0uB3Kaj(E_K)q+Y3DlOvhAE*iROC}JRUml!h#_z=KAYx`cQhE;o<##^Y@4daN;qV z_t9gkL{udJ6^s?9#@v_vR$y*MYS}|Dbc_mM)5*BhaaDrx61}K>A?Ne4o*~u!vQrit z>u7N9*DWO)ZGEs0aSSh()Lzv$<<4jW^QKWTM#Zi=C`E-)%@{!>ieF~CmWJLttRdjw z`qsc%j&QWajAQvoJ#Q|zW()^Sz05a@(Qj9hhg4E`pLrW4-`^{Z7|888lR0Z3-k_IQ zkH}VX)MJy*X>n~1r>V}CgPI6hAr;EmuW1{Qxrt#3I4B{8A&ehYqUsJ-(p;0-%i;p$rQeL3Jo;D* z(l(baujMEe6UfUKDe4j$*N`bLp_oexXeky8;&`^T$QRKh9)&_@iC&GH4$jFJ<6n(& z$?h0nYPHKPq-xjY(ya``Bm@l$WMVB(A{xFq-0Pf7Eq4dzLyCyuTM`14!+;VB@5O68ME9(u%iG>#Ov&BUZ7egcF68+iUfE!XE8=xoh{q zfU%(vrXxX?;p-{%B?R6>9+?bQ+Z)H<8`G{Qk2N|tst_D}cRofM)RlSB+o`r3#A zq%|)-V9AyzZXi`ZoT_vtQ7vNm*jTowX+D&F?Fswn62Vt}o9(O_+Md_?H?H2PjGm6D zB@h}EdRUjQnkA+|)`yIuomQ9ksF_zXuzr*YSd@-V+qh%3VS<5x@idH?9zmj{5CzRf z4@f}fR>k^fS$HGuicMR0`8Lv%&?N<+1@ro!IA6 z-ri)Ce)`ued40wK8k|4$$vz~r2a+vAcaGu$>a189J#!qVRAd37BvI+$(h2h_PUPDw zt;7`oH0WZ9{=h33wMmAlSjX>&FJ6Q02&^B28XJ@QrIy6W^?euCYom-sFJ_!g{^6GR zSA^Tt6~`3|(kH;s_p8x{)TTL?wbMxBr`V6Eh~O&raZdhAROjN9Zpmeik+CVcW%^+H zp>F$w*F)y1(=)af)3Enxx#pLelJXD{h0Zy#DbhUo=BHe!;6{WNU;DE&Jly#gHvnj<|S4s_)=u#Zr1Q>ilrvl&45s5nl8i>BzMrMkPe zKfl!qyuA=m$?Jmltw!vF^6kloBaYZnDsXp3f(u1s=4tS)js==PqKeD7+RK7!` zX98Ij+{pT$*hgDWR!$v#|J=h+8@f)6Ac_K7L9zl`L9hZ@K{YX7y(hiP-Xnm_ec@)4 z@ZPV{>8;?bi(0r=%*RSMWx|kivV>R%&6i}Q?oz)jfSVlIv~QBe8g+~%WgSy!nf7n$ z6|$Y40@5iXP+28Qd;OWV2h-i7?HURJ+t@OHug|B8oHLVnC!&cHAk5miZdja+m8h+M z>89cSQ!R!M0vjqjb!KeHI{ysaX^3%*M8kq4_Sq*lt^4Kk`v$^W6t9L3@2-1(82RS! z=2r}xQK7dTL!Ou0a>yEDh(IXp^-xgL0B}S%ykglqTvK-+*PB-HH^4uVoU);ie&kPr zqXhro?=1hPB_962zOy*F+Zq3lJn)D!yO-WTG$RTHW30w*Ncat$YonnN}VPAlabHA?;$~R$uGNkD* zR@=xaM=M9`bHV59`MT>bwcuiPa6JmBAA`=GeQ0h1`j#<}WlP|>!!cUF9MWfWzgbW; ztNL|whDJe62Fk(U2(u1J6t<0UKi(Y(zaSA}u3cVfX2okRdpEKCe4#Ms z>eyR|^>zL_0sLhXkMyi1gS4I7TZck>FHQ{TE61KK|7G@i4Sz5v3Zo(hQo1Q;89X!_;$HVW4~lGDCgVP1DFo zv8s2{k-1$(!@RHDvM~>tJ@`6|4~MY`^bv$69l|J=JH%xa?PE?!!nY{*NYn;p$zCl8 z+_oZm0$kDl?xTE_R~(h-uLLyJqg8gNOSPAdn!rh8kCM-F?8mjCK!_>yyq%&p7K6g; zAG{3}@&q8!QeTC4zTtJWnJ_l~G!NTNdSxN{zd%FuVND<=bc<904LjGj8ene|128_W zLG*a%e@8G>VHgn*@?)3yfZSnp7wkY*1*l;A5om>I0~is2!NVW8D~VWLlHW0qe;f)Q z?90_TBjJ+q$hc=bxh?LqL@)Df-MG!;b8ZVbP4YfZ9+m6jKLRoKf`QNB$%{R+bj~e1 zZLz>KU;ZlHVDj&B?f8y(?hZGmIOn_mR6LmH6Yn@@l6Ifh0ese5;@o;>KfVP>p!uPm z-x6%;-5^k}qzj(cykPw!a3HB>_CkM72V@}sd*J+^o^d~BlmANg>7Rk~4}dEen;1J7 z+Zg^Q(leEQtR8UlZ0cE<&+>_%*G87Q{-%*CLtBeQ;7!y)8{4<9OBIKG zAtCwt<1x!eq`kbHMJrreshYWa^;o%FPi1l)XYe?h`hI@h!Sq015zqM9Kcc0bKO90HaO0;$8)t0O!wRogN8;?@YKm4qmQNrw*&VpuB zrKF)obQ6_V*afOT>yIJBv|%(erj_i%8g)8yqELPMJ-D>Y-OQ1OFFnR8}Gzw?J-ol9PvAr=crR+>$+%>|%oa&Yo}3BhPeq*jW7=F;iU#1YLY` z_0z+=rVv20rZx63djQoBB$qMa^D}luSQBoc|3ZpgK6wc{*}rO%o#`?i_Qij~uzx$A z@DkeVgqxR~CSE&9&6@>xiave|)lSn2n1DU-5Bi@>oTv44lB7@1U^h1YP0o7y_$BSx8My6;{#-y;$ zy;%oRbCezv1W5A0Dr^qE`)obf(uzA8`gn%YmK<O!&|GA!k zv&l~sD;OKP8(JAV{KuY^skE*5qv80)x_S}p1OzNW15CZ73$H0a)sU!5qYfAtTo9MQ zI>=ztBnc5bFd8jUzWCUQGA)d|8ju0V9$MQqMpQTxR~sC-FlpH z&2`+~{v6%y;|;mPZ38+Jl=!R7UU_g3)*+7a$W8lDEKE9Wl7;oUPTeqmH-S3+oN`Hd zBW4C`+<5=B@#RB+H+E{cijH<@nOF=0g1=LtYBAEmdy|}nnhrs*?~hn_Z4y3~?CEKc zki}@#9<+F$xN2~g%;~+l>V_kH^rYz?8Y#IxK~?*n4g`U>yAMsav~FZ^hKt9*Dgraa z=H$T3WPd)deL|Y9@tGyZaR-Od{5aWuY2k%~h`(t-(FF=gB>|0Yi)yn$R4z zpX0H2xtQ3#czqqxCbNZed0V?;m<`rZNTURYg-V%9gFIbQp7b2cc!z0H#aRRJwiscr zmql)lD&`^Q768v%s64Dd7DNWbe43bZsz>J9^iw&sZ8@|`_1j9{{?ZLrpc1e@z zm@@myFx9)xF#B$r{oDqasCF{_%qA=+7qkW<{S?raZXo@LLtpEQv*;5TG#H0mvrhW! zjOT&#!oG|-xp)K*GrCLT-H=i7+sAjZG2e0HeBwUc<9PUV8wz|Y3Vc7ar+2Y$0JsrP zK-^fB!|L$0aik5P6vJRnc}e(xUP;flXObi?J3f#&hQMo1Fu#i0O98KFT`3wTpU=4r416mDstrqU25>J(-{Y%z*kC9c&<%oVl;z_=!TY@x=xbwl z0^lY1CtepXbXs=w^UfChVO$mr7Y_}6LvT3hgBy^5!uZX&8wVm@|B=FpHP zIoXB65{!bD0XK21qv+0C;S^EfRk7eZDvb9#mtwj}es#IeP-iHa<>xV_uKD%ey<;W8uqyY09`@4qG$jl&4u#RkTH4 z=~LuZxCARvF5biP&E4=m$7HLaCkK%UTByz`Ib-x3>L}L4U!ea=o>)5-?vX!mKN8}f zPz%d{lI(umD)}88^xXxV&8>|7ce+bf)pSxaMgEdG%Fy?VI|3vkC+8O<;qxO<0G}n2 z)-w{&_?_p!bTBa??x4qjXgc*P-_^RhX-iHMs;Rhf(aoGPH6ai0k-yx<-F-$m_fb5R zhSu^?STl0_>-fMZ4cg_F?)~DM_kH_)effK09rxn}(hnvLHV+{s&gz#m+eLr;uMIY> zvFt(t575sN1WHo86>ywzkdJTbn$2I=8Rs~V@V#LrY%tj*Lkl*%6YL@_}=C3FYGEWn|M8crJ(q*F~%UDbomteF!_7EAgT zR~l6VI~b8m&w>|BFUDeoqn&zir0q(%5+Y8+yFAvCnz~M#MWhQhZ+5R_)I>Zvs%4#w zCWW-vy*&3PLB(&9g~C@i(NKK)>e8D9mrQX8v!Yq66;9K)P33DuaaDE72|RQHNv(~b zB?D=#iJ-X!A9cLFHpGV1IY^?9Q9eZ#_Amo?B5Jma@+Y=%q%lM84f;inmL=Hv;o&lh z=(Hh5V@We4rNi3<1ch}J`ke$@6n<0pBsV++NtCAcHb4;EmxP2u%!Z;eDN#0Fj=s3` zpQY42pc5L3Bq$*FOWBz;CaNE=t#${;W5}Wj{rKONJOssu&kDm4Qud;dm_)>rh*rtN zM2bLH%85Fc*x8D-d&E3UV5XpBPCF7=Ym9CA!;1T(80U?KDhp^CzR9L#IUg zC@`gniKB4!hg+E_RcOe<>&Z%J^rbSz99Z;jV@R$bW1mPG&(jyKCn;1@QS~+bKE~6S zB{%AbvyM`!Pl4PkTtOPRTp1Yy-$M!sSP3}7yXwurYld`3C=GOjSPxhsKQQk6EhN#3 z;{<~6d)IcKQ%V^=k>E|+YdZ8A>=vkVOhiQl(Ziw0*p2xLf*4}}&R*n$7gGrLEf6i_w7(5+YCjqe7P8HcT&5}W@-E#jqdaA+iaDq0#4kVA zT+P$bdhC?3gl_JQ=ytOaYS8VUQKb-%at6424DG$~BA1yWqwQf{3L<@;mkjuM?Gec;R(xVOqub zw;OQje&lxG=Uyf*)DyjX5DHr#sN$y7&%_&6&yt-UKZW`Og_MdNd0bbUs=opvO#yhS z^c4neJf-vX8)hANS$brBuy>Vm4lv_8cla0mq~Vbh%x8`)5=e@Jft=Y$&}-ynFl{t= zct$!WFm9#rT%*N%N2mcCQXXKuXU)HjC@soNS>&5oMzGJKRQe~w46THkU$hW1{sK}w zYYW5R7OTqRQ^wvXs-ewA2$f{!Sea&D_Ev)z`qNBcXxn$qg4#T>wMpN!64m&x4Ytft zmZnFTCqdw1>>T+#!*ABGZ}D3G(c;mpk9_l#59z4K>bSSa>l+mUGA;tO8aFob#2%ks zOX(PF@DyA1fv|+UOnHsPzRra*NdQ0GL_!I+5HsncHdY7pto!8&p@(}<&u8~;{=CH% zw+TC9vvKI>RA}@E_|gXKFq360E$?9>?;vv-2sY zb%a}9D77xgy1OxpX6a5<)rT^jLq8=xUEq_+#&iCZA{XiVj8TTH zy*|t->oduOje)AG-{~D(^b&aZl-_0KGs)c#GloF(`$SVPBOiL|)It_5q(Pb^i)*X) zns#v0>Y|r1B+MT+2Y^?I^_wvmn^Ad{ppu33=62rMFsYod33+^pBKrBnWtyp&pr$m@H^%mR$E8bU zpM=iA^GnpI5n6Vfts~+)N*&K06XUOtt{ctZ_Gq_*^%uP2jk7T>A(@)Uuzm4?C!yA$ zcBH9CuVCR)l{dFtY%iUz$j_uj0YumVCdCpkFsm0|gg}^pl_UnT~ zIY)=IkDEYWGKV^$ucZ|**_CZ33IKrQhJ2_9h}KwYhtF36o;eN0?mJ|+an zzJ;GJjX;j+4t~0dHRE6RWW1G~>5mTN<{IuPum7IJy*yZEivIz8zkcLR|94#q^M3&P zgp5t}ovob2ZH$aHVBtgfWH!tR?d%9 zzXwlaWS7=Aiuc&|iRgVQsM_Im8n_gp-87Cn<2y6_6C>U7ng~2GE$uZH_>R#L3tW*tv)qY*2{A>WmHRb5as2Ef|SwME$>(|+Q?(6y`S;vqnjiP>z+COMan*x!Wy8gAudf}ff_ zc?4->5;RJHpQrAxsE)^!o3C4M5P?yt>0 z9{(EMBz!uV7TK(n-YTrpYlO{KOC$1;FnA-HSX=t~76D01MWA9fYnPfjo*<&xXPTor z@rXxtn2!VaR&tn%6l+YL3fv&g_qJW2h3~13S7U&wj8m<$YG(xqBHSw6#>zdOnruB^ zx(66I`W?_Nb)Mi#(T z4Eom+>VZ1`Z5>9|7GcX)KaGS|06W8UT!uFcN1}f7Y3S2N`H{Q0ljofkHqju&U_eTRFeeo!d(k=(sQ7FFS&DsDAyU3k>mFR{ z=Bac+F3@@^*z#{&onH(4#+pD+1)Wc)8(#8v4qA%JdxtBT&Cg#U3Aq~!i|@}0yFNg< zEo7m<{!m|3QPF0XZY4+K(0oz9;Ws*T_T7@$AJ2qqT0Od7ZJO9$$(?lolx{)VaQE3~ z^}qU+T7>i5DV8_mZLFg1_OLE^!ecq6%F6z8P zU1U@eqj|>+Jn>P&_^(y^YpkL)alW`KpLWMQ;m*=Of@{o;u1R(z@O-ujhXc|Azm888GlN(RlanmQ;cfm^#A_1=57xi`(CHin& zfZNEq(It^Td6TEw%vbS$=er8i&to+xf2@pFLr-htjZXzHHb$oKj*YXOvPFQrEE}gP z;h;#e?Eh+x$_=~hy*U%=25%Osn&9E2Izf$iReClkW|YfUM*5AC`MviN_D6X%At+{# zcv>s#oSU>UW?P61)Ik*#_zwK3Kb{us=xpGxw4vEvFo30)GxvU=G4DvwTIMX>(_sVy zB+b`k`C!fpGAxB1)rP~&KxZ(D{v&VORd0ZFt1m%olNnu3E~^Q zdV;!wgvJGySmxk*kRUO{>3@5p@ZOeHo<>G>q_QNzD|B7-Syf zi<*JM$c};r?j&86#T)~y5>klC(|RX8<77f5*g?vq7%e@|N8TkBXivphvzSOxM{M^H z>XI0h+%x;!4K1g4o7=3*{&l}nfkxi2ScPBh@a*8AnJ5FuDLLY%F5S%yj`eXI9OK6a z#jat^62mfG$#uA|gz@$$$AUs$1jo zcMU)>KpDyM(uCBdY07sSFhb^-(8RU$#nfYH+YBK?rX;Le+lQogr#U45#{V^(F~t^j zOJsTW-eugVOtaZ6v(IH&K5wocn?&tCM=LppD8#2;Py5ZhRd<+0TI9uetPaU&2hKGV zm;T!_hpr7t68cpXMpVO@-u88=fSLqrI9W@hMlhpojKX&iCX;h~s2dKU(SE%C06WAj zpKUrW%_)^E@+sml3@rMs;0DLhfZj=2D{=jPP-I3Zmn8FKTGdH{XMd)_Ui~cl&u*$+Yrzm}w-&l;5MG z!K_72qxH42!^#h5Y$5vC%XA3?&e*JWjN$Sj>4l?Ov-cb_yNz#WOZkP_eJ|r&rx8l1 z71NZA(18ffkyo9~R0oZgj83Q#@}Jjits*pg#)0c#w)6di%KBsVdx#*j>jEi|L2MpoED|a4lS%C>qyx`fvl7eI3tgfa74 z+uY%ZLL$KG_V@VDH0pOE5v_;dXQ)K0%YGT_+^7nR%i<5eDI;Vzi{)=~Lq4?H8iNN= zG`0$g8*j1K0LzJ4%}8;|n&Ls;{Z*O+soqzM($*Cxf+I`;X;UuK@bdrU&scL*#aI^K zp(tQ_nwRDEZZQKiap#3}|4J(eaSF})+JT;_FxU`zV`RwWmwB&y7TfW{o579u)|BIH z=ODw6eE4@3(v^`P$@$4b{r}iu7x|yYg^aD;e~*Y_1x?EZKBO;_Olg-tvrEl7XVt3C znneJ&)sF#>0!HRg$pPM((xuKztK#A&mdL>TH_I;yUSwo1Kp*mZ=~fph1O&|bQ|yi= z-Pc-2A1|+uoPL~XP;!GovE{#DNzRB$yeD4L9_-7UdI62+q*U3x*9cpOe(bgXnFS8O+U1V&!QV z+$0qw9dq;NvexzNQs=27I2RH$svg>{&LnGVGfA7|oxH=b3AXh#5Xe5=9=w z+v3Yj)Xcu9+m4O65tX1=&70BIdu2>R^}n|Hp_PfBf(-QN1#gUa5jt3$uJ%)`^>HkP znUS2W6Aa1ajr03F*2aI|Dy=~deJ>OQ!*1{63uN8S8o9mnSi{N-2Cf;I6AnJgG_GBR z4bW|HB0uU8SO7Uz>7|-C(wsymc`f@E%x+(~J(h_=yUHS>Dl(NRYv6dvom(k0P0_3_ zP$Za|qsE&QRo;i{ff=!(5uB=%ddBKE^nZb5QSLBlpcQMPeE6vhzR3XcqV$e_=|eOw zp-rJ0L8IEm!>5jU4Vh~XB{P(+8_UGJzXD&E8bYuW+rp^ER;1(CeqwCzbaDwDLTv;R zZ20W~X}78L))L}z3#15^FP%P%ZQq>r{Cf^aB9|T-@aNXO{G%k9<9~ST{;MfmtZwOw zxQx8HoWh(!rTG^P6H^dN41-X9pfX4g??qfVN}6gPNo+6bupXUIQUt>gM>;W1be%~$ z*IaUKrcqiTgNYoT4r=Z=)v3B>5qF06(&D|#H&5IAxeFt9sNn*wPh%px&GCBmJ?qbO zI_1lKX^StI9%juu{DA65Cs*OFI`7zR7Vc#0PCqCY?RM8rf25oEmbbD_Hwmq7YHI3X ziS5W>t=UV7m)m0K`z^Kmv$gwc4DR;e^TFY}vfHoP(Q!D6TS4}F!nPd)Vx8q1Lm1xK zn~)Gm3?GWR0#_?dF9}(+RW*wRF?A6UJb20CC@E8gX_M%x5LOTi&k4q%G7Z)iss3r; zinlq%*YI2@rK9Sg29cqKL_rY}%MwLV18u;)JU(Yrj^w6?B<3R0(rCzoFL3{(nyZ{A z!mhx6pwG|1e!G+aldc}QfK<0iAlEU0cMGrS}%=wh`C>M0YH>Wv{EPAT*3;ng-vG*hB86!J3 zZU%j#s?N!bT`3Oh!Dw>sLQQiSp;W+h!}3@nm{8MCyQL|<9)_*#Jxs!JH*7(@_LMMlxwe!>&`{z*@wZ>8GM$4*j`{ zsf53L1(h0}q!05ROy#9Rg)H8q1?_miO;D-!@*4zG_}&unvo}yEe!b00oY1KQo@S%c zk)C-3ECr_M5s1VYWd4^C=<^)(bi4xlt`{!l?3`*;rp4%n+xqI65^t9c4GpogjQ%lm z2I;kw=*0RJpbZ43JgVT$pURO*p{0*$YwQF&*9;{LA_6T@^8Q2qr%A>#7=k8CM!@Te z<&DLfRstJ}*AXHW`#%$CNAid2N+tdVip4ec=x0y-DUGF+6ww}lIsV_>Kq2p_OAkFsuZCd6S+&`v8ao- zPc-mcvz@yt<*(Zn3mwriuX~r%oSG?;PjMYbfbXl4Q_9b=%pZ%=>=!MXD0mMElz424 zRw|FpRz*I38`-#GE2q#FVA&7VImi;2`(}FCJ8~6k&ZCz+KK*TybZ`BzsT4{{j5R(> zxk&buKs@Yj#u8m77tly-4=XKYgeV+N(w!bM$YdSQ2Cx!g@(Z2m2i{tx7rt7frR@N6 z14{*338=={g4s!RqwNLSU;5SUmkq!brVU^<4BN(p()<3B+#93N3A2NT6R(CVrU(Y; z2H7402lT@1ad0T{OZ8{BLu@as(pE!o}~HgLCS#d!|~ zO}p-<%teu$K2C}IrR25d;z%PMUDG_rTmf&99D5Gq)LJHT^=4H;?2p(plEPGyuZ1s#w$T0t3__t@zf&G>kDe6>k%F%g}W~S7tC0hZK>Ab z%Pc&XMKFE!3|=sMBx5xcm7Z>oj=(X9xAqr@+ITIn?>BWH`lRof)`n4N4wn^n2eLB* z#!B8%cZKnpH!Gmy+MuLj7ex$ex$8!lNv@YCd80C0wL@4N=7?#xc*mMwoT>gg3X zs9I{_wuM02JZ<^*<=la~>yAM`cJDCDAVqEP;-1a0F9GI_I)Ie3%8kdZdVdi*WXR{( z$7@{2X~-&YhLP99t*l@>iPhYN62_l{ZwNW-FHH4?-qU#c4CmnL9%xVLOf)~!EGJ2J zNWME@XL$9^l5X2QjHhB%9=uE6du>X=`I|<(yir~CJ1$Iubi3!+>J)|2lGjkPqrfi1 zW>$74%Ew9UiVm4ruc>dtn?MuT7P8zy2q3)DMP@`g9gGcw&tgREQj=cp-J{Q*Dp?~Hi1%q4FWft2pYCuWY3u(C*UI2Y`R z=CB#3CX)AFuG?eaLP}LByNaY*TGr0P2V)BAr;-GFKmdWnypT6VnwT~9dxPZP#yctQ z0E#w@BOyMq!Cb)95p+HTNrpPnq(Q3%+8;z<`R$MY_>k81CRrhkHAugn4J8z}s!NL~ zYU@#sOnnzqn3P$@-6#&~tjH7Hmf#)B?webE48-w(U+e{9>6T{R$DC@lNu25E0rQM= zthJhzK;fO`?Iq6BP2lAP^|DdWw0>}pdG|{F`jMmNixM@&8ja%Zg|MGJ&ym8CB=5oGEN@T%|0XW_3d)|%)S--cZb4!Crpvz zf;TsB>`Ku2RbkXQ=R0oLSDhx8MuEnVii3Wbe#C?jBB_2^+U~6gh}FawU`a&a*mO05 zEK9QtmFn~CM*higTJd7U{X%01<1bKc8DI5Hfx1%r%`(S}JBOP2M~*ooOnuV zg{B#qXrHOrLSBf>L3{wL!i-1;9Np=!6BjPbA{?5Ap5>Yx;eF$PV3+w_fn_z6J)EF{ zF6h6YsCt1wD?1L+b8yN?e5F_?qSo6g!UCBWD=7DJhl*B)QZ0ot7ivYbsP_!fhC-q#`N!Mkrc9;TJH7~ zwl}azrquCY1$1o>v2>phCB9Da53-zcI58yOIW!qw*0Tqe!inEP@dugEcfgZG=^x@G zypspH26v2+M80d{UsCl4lz;PGSVkFtNO*-IA!@MctkMczU=66cexcG{mE%;8?k>>c zU87P*$Z&BiUQGo}1}lNDNtR;B^!~VoSB5U_E6DwfKOWrZ-S?jWF21qv0?0i_EZm)y zv&YYW^Nr7=Z?c4+HVGu=Kk@MYLR z4N6r?oUDonq6%&~juD|IO=wxnYl<=veuUku7Zm4&lV({&U#OFbr?xJ)aMxCmV-igh zjmM$aEUESTN|i6^qyr6X5!k6RtM~GeS%>*lQE|b_1rF&bxk&mqoAU(l7H+W2;Lc2) zwjQd2Mo{1IN6u?#rSIsNtf(zJ zuZQH*?m|f!d`k>TP~g=X9esztjW__IKgxnADpw;_?o64K;#7_C9j&@0AS6a4PZ*9W zLi@=Wf;PQQomdNXA-sK`^XxwDKIJ&|{yF{Q*(wr`a`cDSN8)EqEdjazupAl#Qn*h) zfyfHSn2+Iap$+4u)-Z_Xw_b4sMXWPNDA`=tyXk2UX?ydH1oV z;ryu^?~Ez@^u-J6pJu0v^YLR!xmDSk$!aswq>Iy_BaGsxnv+qna&^(P1H6>x`oT=X zrkrj?M7f6W;p|&TO`8*n1bWKul>JU&y>dXw<#7^z0y7o&wRQFRR7AVY*+oNj`BB9g znw73Iq|GRqB6Pp(us)s#fpDKQbR`=m=k*>uQ72P>U-6j3S#xd- zFmbZ5R3ZxbWYrujYE(gSdyb&fU9wp>V1~7M&i+YCWs&7kg9eR!>%wc*F}LG@5XDMP z;i)7jW%FrJnIJUHK8DGNuZr@~b=+)BC4)&kM{pT%sy&<|!x4HF=Cd)?4nSz%_en(* zixz$#ttwsUk}r~qM9gQ!T#p>npCo5F5gUDl_po1zIq=zynjw5BGdQ+G zI#8rIc<{WyJubg?fdV>wqRt;|fj#v;<7Omh-)4n5+Z+&CKVGmNPfVE4Xa&I3A6|BN z1a$F^es9A|T?{;B*Bt5fa661Wh~1j}0P*doS>cU%*G= zKpRFG#OTlIy6389p#jJTAr!uame<$|$i(^n7EBw0o?PNmP%BV3$nyN)NU6+9Ukub7 z;E*a?Hv%c+nMt>c3JdEtbc#IjB{SGz6)5Y^&amqOHrD;bH&UqF<;HOJMn-krW4~)(r>hOnEBL8D8xz;7f0){mB7nz)D`u|7TmH{^gofFg0iand{ZBlsi4 zBZMQQWO!smWCU{H5fBpK5)fnHB=AXyQbcJ&a{P4ZdXRle0p`H-5GL>wL}|iyNPSiT z5&?w}G5BeMc2s@#z>W|{2ucVOq-7*!_+`Xue06boF?tAn1_2%c`w%JcRK#X@Z2o%a zec`~Q2vnqO>3SeXNgm#594?TW;?;`fhRQgW6Q)}NW`@!a9qD<&ddz(o0V)B_TrL_o zmZovIGXfg97Us|u>z{9Y+O-xM8TF2MN-fflwyckK*}ANa?JQQ+OMf%+HQMX5`UcXn zRb!!@%~X1D=+NsJ(GPO4puwsY(WuHWcy~Wwpt*Fo{TL+H1NEyJIc5scH!Wnrdy-nt zeV7~hnFAiyUr*}a0#9y(lz0kM=$Mw|6ALj2^#DMj7~|YX%&9KtscaYM8ta<)VT9#} ziz;3(*BAJkXo^DK&)Pkj&3&L&C8h24gq82u3XB4g@}Yzg-Yg=fWvJgq^?dHc$&Th@ z?=#lso`#1Lve8@4Wzw^R{zN4ipN??bSb&0*jT~PugDOb~P;{VdqRC~~b2YV<7^W)h zpfNryv!2zGIG+KJck)lt1$w0QZ7jH8Uf7RcJ}w|P5y)3+GS^M&34BNzHnylTGHI2p zD&K3Olld@rZY{u)qP9{?&Uh3eG&Wx4hb>to?j1L*m~x&j(6c|4)1#?G=gTZY!dm3x zgAT6DGQ&4&1Zaf0c-Eklbfpb*&^@6@Hx+==C>1kDC0@dmmz3}3{Tc2VjB#dT(3Gu8 z<@Y|~k#oQ^TWc!9Gh?}zqkAh3Elj4D? zjckwB)rU$1>YYo~ddlrs-wVdV0$Lu6iMVhjkow}c_=&4NV)a}NExB4m>yuu_&9dgA zED+X`s3QVR#(FiHF)eG53hmPKr`7#=0t!>3I`(3n+z?SKvewAvfa$;FC*yK8<-2R; z<1-*Ceb`DiUMUu8mC%CNdxH??uKM>fJt*~cN*V4|h_1j_cSaw!p zBI*|gA)a(BMi*c@y&Q`Gw@NXCQapbZoK9w=KsHQ%K* zuz1$zopp7QU<0n=!^p-v*fhv&)^~Rpt55uv#xNv_HVYtpuliDhMHD?6p0M|A6EaUU z!d$p6zq_jhr(rpYHb$Y&u8geShM~sCliJPz667vSV9P09OXII?$dzr*cH)aw+%7mH5TN>K zLtm}Z$DszK4k;vJr^5TNZfQ}1jmWP{Y>T4xZj!3#(-Rh^2gPIu33DmZkdga1TRrOY zgW|7Nd-T~sP+XEJm`-=O{d1bj*=`kPDN~d`&HCh-tTI4ephT_x#>kKBsrd~r)>D9B`$@KV@{P|b%du1>ffIE<0eq7CZ-R-&o zQQihbm! zLShxg1TNUeb#sHpB65}Y;=4uczy_Ft=McNa?0^KILd-lp-++PW5TMh}Ppgti*Z%Gl zx#8G};L+AUPm|T(d^m)0OYFOtMz0dy3ik5XXKy8FqRe(kzJGgrE ziH;4k8SrL_U2L2!{VdMr^s2XK{*=N~ZdlP=Wg;IUOJ)wOe4T{c(=AS-h#fwfk8S+(WxYN{U$T%4`_{<$iLG7Aj^{E{+SP$?|WYIj2KCd+Dd6dX@F zq$vcXDId{`&ycfK{EO8Pvq*!5-=ZN()W#2KmHZJHSBx8-+cbHG~*n*i?v(>(=oyLO1P%Vck=bBVFrbeqsIQBT`=SxS1|276f}t4AL7 zM~ifFKFTNqlfEjGNMHN<;1qOqU=oS+YQ08(cXEEyCnYTb5WERMhc03C!KuLr$pAj!AX!h*NeSfwUR#SMTl3Un)9+1h;yeAd=E#~ z@Ng7-@P-)Ax-=o@2D87kq;*teEAOI*5EuN3ZTmy~)Z6;Uzzxu6>^*YVwDq#V?fjRk z2(`mG!UoSNhCa1Ot5RpR7ezSTQ6qTv*GBjasyG5pKq(Pr6@OUFp=9owEL7xf+`|hm zKM{38Ld5Vlz8i^5#-!q~xG7veLwuu<#M?O0oGG#Au28&FK+=P%c+qqlc{VFFX?Rg$ zQPDJMeD_X?(-a*Qs(7iGxNo-5TLIBWqVU|Q!rV4d{MgwzWV}<#kMGj$TSBCF%Rc$g zNp3}guycf%CVBoRVHUobx44V1Cb`3uxTCM9I>uu;fpWFbR&GMY8Rg5K3#m47!q^wW zlj&D%ozR?WaZxnEX@h-YHwp1$MA7)L^qWW41IF=p?xWaQ8xB%vhq>(};!8VL$PqUk z%y%PK3<$=zlHvAQSCHk1C(E-=v@E{fWZbYuUQ%@k!xCuXiaA}Nb1!`rqJRRV-!I@Hja62W9MlqKev)xLSd4e-7)8G{0@XT30oMhiUu_Y2FLJ*}9U?8i1Lv zo07ZMz19R&U3A$i^g<^Dvn~ImY5q}l*(=t1-imMzc+b}eqW$NjL;Gqu~g zyk|3`v7&Voam-o_cPpj^EZ=Zh&Tk4+EBLWh*tEYcBrn+*&z#8D1m6xH9(a{r7pqS) z9JSdo%QCa)Z6}Xh4<29oZr-R{K+D6PsW)z>sjWO)+o_A;O?zkET+-Pud_zv{BTm8? zC2+>y&6=cI2rErAQtCIhF}Qt$eBVTRH|{4Pkuup&zW?GysU`40wa~wQ`BDB;&4ukh z=ug&ZbUpw#f*UmB{83tVg>{!mWQSgj+SWC@7Zs- z(}kXuE}CCGR9snItyx{KqN%C5E+WkoXQpArQfav+R)x+_(&mWu)K7xP*KnU#Mk!3;3%{5&goxA+ZpfGwg|=uQXlHsK3T9~`)k z*bQO84^;}?r=@>{PQAzO&+=7A1)%Kj)o5dYDyU<07i`*Wa%T3j1 zt(Rzv)Gv+Nu3G)&i+H|?=IL9(7)r`g^Cb;}ft_jDz4{Uw(&H;B;;tA|uw9J7x?>ub ztvP2i*oj-O!(6rNPRwe&i@(sPrJ^y5{W}66n}A`Hm^#&l?4ifcXB5#7vQ*_)*9xD{ z7s)pzR9c*$(CpzjQ(Fy&Uy&2vJKk=T4ttO;w)v)q-5v6Oade^idrh>e}rC@ zH~;GtXcd-bQ+N$9WjPsTd^MMc1~j})JGZF=<3LG~dHaXbtER#%r(4zCd|O1Y0Q|0H zxFfnz2Az&rIPtQ`c?(^fz-Gx|GO0$IuIOOYwQW;s$k2YXeSrBZ7oR=`nVB6}^xYLDmf54vMm}BS=eV%?pZRqiWY1%Xk{va1wcC}`=CqHm@$iH>= z7(Z4skGlVXbrY>gR%?^IRK>}pogy3RnGdxKCgJCHvG~EBqLCT8; z%er?Yl*EvZWYq#k#Jc@=EkBm79)Il;NLa4WDIE9$y3_%xU~UD?q)tD0t726EN3SUb({ zWutqeKR|y)Q0DWXm2|DUbY3j~{8;+JGR@a`4he5fa^zuLKqJjk3i0)9Bv#+pj!0l4 zK7`Ms6BjHrN3Bv*dgHG51HD_DsD_afy@#tgxq{vDr!?%-`@l|Xu$dM?``@|Gw2&~U z(?q z#Bs(FV#_dRqlNy80aN0`YuIYEGma$JW;Qe|oY&Orclnw$+*mbWDiW==>3jR$06f>9 zVj5!X3dl&Iaj^vU0l`Ukv{UcPCqIu1P)`ciWb>0l9bgB*zd>7;Jc!LkR+#ibW1#F{dN7%F_ zWXHI=C18RZtciY6?9-yyKfDVInu}M#32_x5%kYB4yaAJIa)aI)+Go1!2z?bi&G-W7 z72n5m=8C&9y#wGD*C%Kf*9Y&78K4guTE0uiHL(M(j^$5FkA~lk;Fi=UkMT@~WoVbR z!2v*u&IKz=$0nVTOXMw!zy&i+=aw>&L+F;n(eq1f+rq@>WqIeq+&Bc(($pzpVA7N+ zI&*y}hPYLJs&SwXvUAF&@0>aXQ3AuuqW2iZ4ak79o0%W>3qYt6)?cN`1Ka_2M-x^n zNDaCzEOMp+i=Ymzd3QY^kF~MS<=6LV^hktqL_@se(#!R)U}Z3TQ#6O?So)*)?bJ6Z zs+0b7CJ7@O-C<_o5uZo817l+0&yYVeR)=it@$~EnCw`KjyY}LC?NGq&>R`a!mPkq+ zdM&cSP?A^b-6yLW<)*D9ZQfCms81CkXK1t)hfZ4$dFaA-0KPm=1I)!>eNQPG#Q|U6TR1?fR@RC4+{eop_ z!ovS7;~@tzDru9d z?FiZER(de%SioV$x*)EnMGS0LH1Gxay1N-qepxS6U{F~Vmhpd3>b>>0NK{>eB zq!D38XXtS|h#NMoA6cM|hRaboc#;(IRJ8CdwD6gNH=HAE>Jc~gEiv1sY#QEA-tZ}J zRnRK`q^|hTA$hwNzr2+z6^l45@QWfK=K*bb6}(m^9)y%1L&g`k@1Q8F{T=90yg<&C zF_xS~OtFes06g8|P?B7bP$`ghr9_`i&7h6_H;B}leV)C*bvc-B*Is+7QDVW#8yqp` z^-v0#U>*iv%FRBGQ8_}2HI#1mQgBL%c<6Kqo}}|{6#Ze8sm7;YZzF3E#5KQzwB;3Q z+7-C|TIpD6lR?%Mr2b#b^onW50#*xIHvIe0XmQ3Oh-da)UYF41s}J7YEjM*klNlOQr~<#ZlNRbuL^%bS zy39hh*pR`!Rk}x}$U}|%nuUMMzLQw&a4{lFRPZ3%FA>r`Q>ela(ml3M z6~sNZA2G{`ayqR{w%r7c2LAY zQL_KpWA@8P>?KEm-Wnwx2TI=qBWG6%lU*vk)u2EXw?;G%5JQKx}p<5R-wD{O(r_NeKCSgaZ;cz6UgF_Q7 z4a7Toa$Hj9Dvc00I{fJ@34H&6sEmZAP!1WWM(wf{{zaGy!1O=v!#ycoMyi6WX+0`q zI`!F=$~{@mAH9w{v3#yw6@1hW64J_$SES4>7p=h6tZ60Ly-k9y zMMk0dnl6!mtc=tFHp%PXfoZJ=Ad7N(lH-YDD%!)eiT-8aRb#sKwd;=`p@F^K@y`|b zfhs*K6PU@zFq72IdS!!q>?T)aL0+6Ts!9SB@_EZND45yY7eQOj&j3rwzO7ZEdk8ox}XamwSL?FC4W^e2{%2U zarWA>r_4W2t>l=hi|fQt{8AnzO>{4YH!?vM_XwzBZ9%EpC&Zq|VkO00>tr7+>l6Ld zU{`7tTPgE73!XY8_YH7MatzUf@}aidK#-N`Iqt#Opm{ggftf&43s(kJDHPSac^ssg z*;bG=uGWDxguotC^@LVKqq9T7#bgWB2RgRr9~K5;VL@M^27=uW^Z#VK(O`>hBX*71 z_B$@-=H=vAO)KKlrA&lhS%MrbX*8+aMlY{ov;AF)72af&dfbrsM^!7dC8ThnV#_qB zHnjUJ4QYLqm>~5A!l|3g_h;jBq0f%>7q8PjE$Ps!B0wV(IbaP3H7pdMWh-Yeo1q_a z2{NwNFMW+?1jeTKux-WC?WAirz?0+ANxC`^?GZg{?#gr0df0OS#CN8xqJ9Er#(@kl6@0>jX#iZaawNR-fsYFL&gWxP8qTJFjNJfuxnrw z!bMYR&OM7i<2kxV7cBEb|G(0{0xZhrdwUU)PU%vll$36emTqYfmZf1y zX%LW-l8};8q(hL96andOq)QYLr34A#d(ijy$|3^)_Z!{o+G{W7zGu#yGjnF1XU=g! zt&wPmdTNrpM#U*8{sM!o_wijTlw_z8X0nZ(O=tWRMFAeBZID1)zU~%dnT-ANG+e&A z%6wl9@jK0jNe17{r_$K`*|@;7UB$Fp#34iWIBy7dJ$$y;#dyP(Gdm!y;*vO^?FW?!#qE(% zhwGxvEQbb$+0bHUO3~K@z9-clUN)(fnz!}iPsgh>(fe=Cxa;#i0I39Z3;?!NbC&JU8Lr#BlAVs%#1 z;*xb+U$R_#`_ZuU$_M@r6ZZGEegtqq;W{X}?)!1GGc>W>{~E6NRf1G#I>XZ1tUP~4 z5?zM)%gvC=ah6b5KfVGpZIW%srLwl0(WQ*)gfUr!-)O!DY_a%5W9;eUL+f2jRT&D@ z>Er7q3beZNA=2^R41*{%M>srLHYyF4KSE~WhPoL2S98E)ehXdaqw!E7P8vcW>;oSYTK)|NvRVxt^5rjKNaccVOJgBDpC@XhauPI2ngC4C63 zd~Gq1Tv?VrY#9J#6(0H)fcxBFV3?HY?LIN`HJM2Eh#l1|)d(~d-WfY3l=$#U_wbqT zY|Xg*mOrFFU3JMFsOn}c2vJ*U`GO(3vm&UP@iO&&KvQx`jPnf*O4Z5C9*tfkmgM5@Lh^u}*Sd-L>0l!!}Rm7P$WH)q&zDWnu zt-HMwQ%l~K536C#0e7^GEe!mbEySgM@OCz3`{lMAfk6uMEb2C=@OCW5TIYAxyd19$ z+p6XK$)b2%L~ge^T$qcC?CiZ5N!V}0?46g`>Qm7E?FEmIYV78=#d`)vPu(#ETuB36wdrbqk#~W-v zQS-AUUcHHH*e015kzPV3S1S>H^WZ5Esao#I##;-PA=B(7;@+WHSsSx_qO;COt!$xVOoqK7$KNt`T0=+RS; zNy^9VDM~zY*(Th%)gwq<**4gt;|K|_2_IC=1@s$B>Q{^8Y46hU2z(4oMZjhks&Af_ zfpZp)$U?C)l6{;x;0=Zg^P5#R;D!2s%!};r7WkNm46ly?$JNsM2`;fI53{RZ=##e> zCLF4rIo(Q$$tJSKCR6`nn1f#&YX3er)mv1%oqWXQo!HO#5d{Z7lhg9yTw4qU-ei|NHQvw7bDXcKLYy6b1vvZX)g4W@ zyU~M>43-;+m2b8O`^a_uQ)5^8Apz zUiD$Gt0Kyz*3%j54VwFMBg1$^u-5pEPK9bq*L0^?f&>4mbf<9ks`Tw__ATjR$pk@7 z_Z0T6_9gf}H$}m*C2^rkMwTfA{i}}%(w#LDB#kU<^V|k}g^64k5X0Nokuj4uo{qIcuN(Osv^l&D>bGxr73QwnuHc409E6WO>q731uHd0{wr8U3c7zRth%u+Lh zVjpwW7HD8|WVQ`MDeL&)Wk*n0xY1&@nrN)6c7v|&>TPa3h3lkKxIs?C4iBQTO%1_L z>YaWwE#j@tc{Df*VivB-NxB^CZoItDf*`#ukca})SzH8t3lmFGg*H<47B>CZ%=(~c zk%H|Z+)ybYBHdxK(DX=@{S4HG*avb!>o`Fx5V@pQT)+2BUv&sjGhK0%{Q4q>I&}LL zUvTMOk!O0O_5lG6`24WET!eh_I^|a|={XEJ{FkfW4PUJ5$lndKfP( zKbNI>LvZ0*O|6fcwMibE+6x=QMlOULyL6vo;6YFhhhx*TPJs!Fv>^L>i>hZYxiC{L zAl$t-z7D0bmA;NDliT%j;-#(Z_0h-b;O+DgE1@Trm*|vgvr`Qu4l5NPD@l>WtuU2x z_AMnNpiRrR=TliCxCg!6J0jwCcYDX?+GxRawnl%?$n|SFQtR$yx^^$OH{1Nb`#;s! zn%ee1#Ytt6PsiE~r0cW>BM$}n>ottL67p#dwsfnaJS5 zFDWmHi`L9!b)bne1xJz?&MJgbk`H~vxMXVgW5sG>wcwry)5Z%KM-vB!Ie(ixkMAN1 zP9_}#*J<$-`1~_zV{rEfb!L-MxiWAJHowK);G~uF9_|mkoihnXHP)y-#G#f)l`LYAcU_f!>-Yq#gSXt{ z!d2W&BQt~(T)5u_P@8TVWN!?$?%<1gXfPD3&t14O+3e-K;*B{xCwc|{?o-U#NVQst zOw3y0j(~S-@873Jh&Qa_`+4SqT=Z^bZqwUR^mA<&>WO(iIEW4v+MJObnQjQLL)v~D zFg2rMw%;C5j&{Jc-yER*K5eR!2_ZG8xk#Of_n%l+ctd9$lbp* z5Pa_oX!tHov9Y!O0gE!Wpynp=Qw7-;wD{*9uKabWCBBLVJ6!Du8|cAteg%DeRrJKe zALAGX&;%{po;Ul1(8<)}P%*_*P*$?*+CgIR1YEMqZx`}+su?`Imlu^vhR>gogqDm< zQ*(gsnY%~gf3JzrnV1^iw8`JbC%c)3$&a;n_C_axQ@*V#lLSgjFU`f)KDiR|M( zf6XKoc~AGHrPenKJN=Gc*as~Xm9--YLj5}ht**2tA3rDycrw%qpqdoxHoZzG<@(Nm zhJMSB)Xm^Q&St%B%KlxRF`OIvwnSriE!2*Mk<(HW(>}bD{sFJvo}<_@f*Kx|NGVrf zI`f!Df%wWd7VGzWpfxsPIf{#KtZX9Msz-#=pv|VApWmsgVA8DQ zPNm~<7Gx?^-G)=ccAzz}(x%qBC|+!*WKP8>t3#fOkEt9CXI>Pp#V^LV3BE?&NX4JQ zffQfAOqpOw$xf8NfiAi=I%5C)+mpA8h51v$C|KB`G@NGDb^&Sgct2cOq~+JIB8t9; zzy62~okwf)nIcvJO3YT;b#MdPEc{*wC%-sJat1o0Sp!?i4A1Baf5z;GYW|uxBQ6oP zD>xo|?-`yDTmA2UvE}Tx0^|IimY8KGyMQ43cvcQ}m|j)$%DPvQR;_UU)bk;z(vs-F z4w?B6rUQmz&L*c@e8o^jy)_IhGr^si*kO_V z_a)0^%Onczsdm#!6)V~NAHl9|$7MG&c0%MeZN4Ow5vR65-&IX>HV$UZ`7cC*jDc^99ep(Hx1- z$uS9}K$v}$WrxN5L~BPhJk_Ce15vT5{8OW7#*Ii6yQC`TeQG%Kq~Tb-EKErnM67`; zI?Tx|>N;smg?N`m>+)M}Aa6Wt*?IFGDFcW$g4Cvt=wk&>IK?pO4x;5TPs-3&$a36H z@*HL&rT^+_B19t?23{!7m6-@r-nuIkCa^`E`AJ|+zBJ~>ZmULC<(1}TjtO?(304Wd zforbDlqds+uJbsuYMoh1GAuGlp~Ztd8rgU5hVl~Ro8uKIGM39H1$@n2FH+IHFOY+W zS$t6ba2jDSY*;O`X%|hTJb+MNmdT#2c<^f7M@K_?BFXX&@gc2;RLTQj>H?8)ys;-X zL5(f}FS|Zb&C8RjxIS22T$xrD4|qR^ggNNS@qOiP+LA@In@zlO3V6*#wm_QcQVhHV zgCGucjYEx$iZTL&HsAVLni^!KXD_vKMww+khnw=-ECc77Hg5%?>JxUE;CmYz4TRL5 z&u#p=n%R6(!MY{l!T&|uizq9q(t*fe<9fp1M6y6E$)Mevq@cqRc{!=C5m z?k^~~IrK^e1tO)D#F<$ZHvW}N?O(fzi4*2O$0m? z;IvJswgboXkjj{rJ@TOUocO3&ikR!FmBvaqzL~+ zoB2hw$Q21Z;AyyaJtM2RB|jWo=6Yd$Fv?U>p??_Tt{-n8zOqT~4#MbQaA0n1p;S!> zG*{im*A@u#@b#qu}7!*wi7BTXM%QMhUTtikwpsQo#o3$txQOKtygV_dg>`? z!uj0wpT=n9-j~?r!yhHXA02xQH(Hl-x3IeNVrj~NATBhXx@EKEl6He9`|O1R2?0jq ziybLf!nP?4_c>X-V&iHhJA|$-T)|n_$6nV5hwY%_XHBtYdW1B7x}0~XwgKUjirB!F zBE28TQr}G6Wqu$`sin*q+f6fmLbX)WAC04RX}%49-Pz<$vahLb+gDXr@BSoo`!VN& zfTV$-_RZMb7ALEinnA;NnluY8IQJjd#65$GQ%#5r85vVg1RDw$Jv2xF2blSfZG^sQ z@oQdr*0W+z5)p1I0Y^jRm&N&zrGe0Dea)10rZHx!qwN}IMnHW7p&VoF{lbz4 zB76!_yrac4sO-ucJQciLB7&1$vfj3}j8oW@Gd%AZU+i{Wh-6Tc|I^FhcO)(~>_W+4 zUA*z9ZyvoI*>iP`k+&Wb9v>w#>VM)=%l3X;YEk)i_kbOh+44<$i4-QNM1f_3=%84c ztHuR3W1Ld0?;)DkIT!AR*rH%MGb!b?SCV&@l*XHxvH9yiNf+Tr4@BkbE6{Y0Q=NS4 zdcWP%G-dni(*vkqsWL~au%ORkE}~*_tkj5^F0t64C#hFK*n9;}nID{l)zi&Kx8At8 zXzMHs(TZwl81N@RpiVsV;9{&~UrVAk)__N$|4wd!S z5=|4m-!;W&aU~S?X!y{i5w(Y;YZxSkax}4)5VaSBG%Vm0rM5=$;IckUSO#CZiw=kN z%2vaA?)o+gExqpjDZ?jT#gKiY{wTyHAK?TQeWpwEmwcHvMb)TYT-IzbZZwE5^s^NV z&%)!8AVCQ!b@+_b7V;5^%Z^|@ZSf7y^`aAu>$%&rN0P9?vgQP zWGnu5_b#nY|Bguig#puVku__qB@%2n12=-)DaG|ZwzhRb%5tM;^x2h}hOFYp^Kwhw z*>XIinRbewNhdmM=;#QDs1mKg7d|%AA;nX+il8g#GQt^h?4(J0gsfSK+Itb+s+6g? zqC`}O7VO$Ya7*F{-7jmcZ^$y*rX zZj~jxCFz%H;!HHRl=Llvmq8!8(6O%hCwEvOjnmTX7{AOs{#ySsC)LB0s&aN-k&;CmMl!p8hia+kawH|9 zR-<=4TzDpmhZdbaIk$tgmp+SoPu;*+y20c9$bYYcge_3}5*gd{7lSv;#&0It?~nPW z_Db&8U^bI%U5-a2boe1=0tycC5c@!p$4)L0Ty$l*DUJAPe8w!Nh|=dCq)_VSIBWJN ziN%^#8`-iU+Uz2CfTsb(_8iyr3U+OIcQkHSY$)hBVQ%N&4RIvO!mf=cnWpY*kSQR? zMR~k8_ZajD8~SLn7?bTiv5m5Eei{>QPe&Sa&^JkaoLqlB92eodZ!6C<$Tr*@IzO7_ z_P=UWFCA7x>>QI&!w<@Dxyeqn1G>;8EX$t!^p$`Nt6Nye4}SAdf}2y$ zLFKPyS=|s!h+ahW=rz;Lp_dRtuNmy&s1reFwC1p^*(aNf!>l+a8+4m?iMKE!ML{Zz zo-f3*)h_5YUWDpVz5s$besIg`w_Fl&!4@5^R>aX=>cC$ud!;9%>92N2srca!IZi2g zZ%Ju*R$&&@bbcv9$p=d>1$OKgz@q#5V5PT~g4Arh@Cyp+@6c8a?kqTrCeM{vw${n- z>ahzKBTd_Wb`rQ>w6%EA3e_iCrK)7b>xaIh z1W_p3^Ugkzr~;|VbgSE@(zic~Xp7>!dw~B@V$>mBuJY^d>#fA({T5Bjc~X!jxC1299&70{p?2I!MibDh-AsFQSaR)WqpDFj==AK(q0 z715wuGi1)0m=x8y4=#MgSH|34A+H_|*qSk5#t3SpG;~%)3xHJD;=Xs5Z9=T(o)twP z-gHAM4%xN9#{@|AVNo?tlJmgdHr408{#cyIV; zK7do$T|w((m3X_ERk##A;#P*6xr$7bvN0QiN&hz91mOb@QA*^h8FJ$UUnQr5be82< zK1TM_XuMEAS*u%P1fNtHW!S#aAdB<)Q!$ta6R!3!aY)U+c4jEi4*e`e?0VfWPAf~B zElNpr#Wf+#bwG=@PEEI;v2MbA!vZJcmAGR*CEiqay!K!ci}Ie8gjlF!uCZz!*|WD_ z6GJFi)UF^|jS%$W+>t06BMzaVzQ}CiZ&d?sXG~O)eYV(N$zWHSi@ZxXwvK&C!-qe5 z=5b+prLp<`Hfcnt{|y5*$K;}X7LIt!glEL+R1zk}@;I@Ig5+^Of*61d)2v*>1(aS= z>JGQm^P{C=nxr<7l5Zrivk6!7raFG$;T~J%%=^k}=|N^bj-mG@j;TH56a2L`QO;n4nysed-qRYb_8LguQ=O$SnzW7xd|fUEwKyQueHjg{ zC^-6oIZd%rOpm$%-uHv>`#sDx zL=*LLN{C~3wJb5Ai$wTX*e3aO&!M7l`i45(@!q7Kb3xF58yiP?IY}$!VbhM^`={vI zWtNkDgdWDD)1{Fn5 zEWoE!BQq5-DNh1n>g_8dckMbS8*j&VJv;?ncqH4zL?XOFfA=#A5|VzZ!7@o%*~JDj6484f zkcx74hzaMh#)5pV%+VSl7a0=cfT`8kgGkvXFdI?9Y zUytG$ii+atJ4I(IQXDdMcuSZciFY5PKPgiPe*QUU%Nq5IDG~>VwfYLz zp03D*mn|i$ul*gX$qMb@!l4X>kJ@u_tY&RK3?t)fGacXZY}E?YRPQXHtoLDmc%WHr zL#yw({ozZd=)n9n!R`E_s0AZ!$|YSnD)yw*i>Tj%rKmDT6KGaUfFPr_!>liFcN8Rd zj6@@fCHqC5zz>hZsYcKE7n= zd3Rk+-k;Bjuc+AQ?GXOW)ghS{JQV%xf}#K#MzwI$%eHnmGu$#_0<*F6shccy1k%Sc zZ%%I52FH{DcIr%Dzgu6^rY_xUK&`4uFiuc(1Mg|eM%0g4YTJhy6+BNF$tUID zhf;qqk#=qFw?ap%siJ~31`-}c=lkZoOP@&YLo!y8t6M6r;3dU42p{IESr>B_L+y4{ z53tZG=6USJ*2n%q@bNn%oJ~CEcxn2TC2t|Up%ryJ#RnD7O6?X1UR_QREN^^|jLfK$ zy0 zWy!CT7=M!)p!3AE^ubN_;+e|Z9OA6j(YBYVh^*9Dx14EtCm(!|{?1U~K@4dq+g-Ba z@F{N-ly1GrjTjyH3egUECWd83NtU3#fPaRh8F?y%(fwX%n&ta-{M{DooaNS>$8AAA zPd4NcWoNl5L*vB;zJ9pHKlW*ys*AYs^X3lwLZayQ4IK)D@;P=o*J6q+DyYY$1MCig zF&gy#*Wzy-v-3TWm2B)Mt%WAa-m8l&j5MG*Qq?b5?2hqIPx;t&mai8vBkG%l*QD^rX#o1aqUtMDFuxXcZcVg6* z+QMGlMU0HqhtjXSl!#wgGAtMs#W{0VXvxmE%}Q7Fu|51G0ky&9csw~H@hXngw@<@R zMY@Z%G{B16iK5F0zndZfFTg-3;QJRA_L!@ovQS~v$Vyx%n;*n6!xqSIlP)eX?YMCP znVxsZ+pgTgL2UK7Kj5~EwSny;aiP|i!dAr`Th%``?&W%66dNYTckCJ241U58PriA? zR3+xm@9vYavyjZ^1(rEbKAb2~d;orZJ&}8yb#r89nwG`~Yl;duYLoVU5ViDb3{pq% zN>)y4Y^F4PDO(^szoWl$@=0HoP>38Y_WVn4P2x}Jl`)})QY#_5*P~OlJHqRhQIc=q zFU^jR+T&6Sce64*uiU|AAd9i{TX+>-afNLKM7MJF@;n7eidG-}NHxRr&vynzH(afv z+?w{j*zVy^k_RwEb|*PLPN}hRQK}1fh(Mcj8t=k*)y7oAp_Id2)mYQl{#h=1J!Cmz zg<0aAXSm}i0Uz^?H^l127K}yt`sy49NS`cn`!ve>1eyiFopa@p;nb4TJpS+2jlW-N z%sD7q@D=YX3TE!&6TD=cv3Z4tD&XS~Wt^{M5n(`3I|XNbbCbCjM%5QGS&d${7&f!7 z&&814Hgpq_3x~Py5-5GL?qf}I=G9?-`aphk2rn~&d(rd(Z?3OtA_+d%rE@PaP-VF zi=GX8bt2tKelOi-G1eeE=?mUNwIuEzt2M{XO%YjndvTL43|d%Iv-Q)dG{{XP*aRLv zKF2+LcMI+UE(jNdgoFe-%-3XStjo>^T#8NvE=A*lfL9Y>ik!HrFr$>b1hbs5yp)8v ziYk+w#D3eKD2J5*ke>x0I#RrWpZ`TUN*)i82fhv)odf<@7Kmzqb)*sqRC%L)o~r+~7`8Gzkkjhl%2o#VAlA&M zRi=Ys7WuO>7;432Y+w&WU2wLtWHL7ZTL8DmnZQsx$f>woFt~~TC)|HX7*8YtPU;DL z0PrZ_BMw6XkN8K=PiZ_1i4D+68#|~C#LmGCVt-U#hvTd@mr%+KDA+U(kjWQ@^85cE zB_PqGT*n6%pgU5c(2sNvxTA8<3=FY{8H2;Ng6)WkX@OdYpTj#Zzsul>_5Us*ro%7+ z5(Z!(Mu5v{t%Nl?LyTYX2TrR2{K=6L^G}U`l?V_ft?u;*X7rq z_Nb5!v5~?Pv2FwMIY9Vd0pTB}vi@Bto}9^|;$R0cuo8s=v9O%~vXoHXXw`WD zcwLd`fI|KT2fi64pNX#uwSfF(MqnIaYcK=UJ_2Yv?2L9R{d~AmMkmWXz+${Y88D_< z;4UvLGJNK#$O?w$5U_(N)CdAT8MzJKzd{gb^H-qFurthyoKulccs=>Jf|n6W)>{JD zkpMQVl}hEEimd_x905x+*Te8`zxU z06wrn5CDEUWgYzo6>@^k9rrA+!nF2E<*B%afHMc2=_G*$X^x&0{n*~C9LHf&HZ_`{qN{@OPo}Ez(TwPSRd^6jcVz< z=>NRee=^B&i32@3Qr;e%N@8qg3G6}tkhy9D1js`R0(Ak)yT}nV5C|UxcbaDWgD3G5 z7O=j5#Sa@0?YO<~_vDU8V!)ybtGrco=i&OfW}HSqG3z|1i~<4`5P?94 zS44i71*ZQa!CzOt(={xW=X9Q*`Cta8!P(;e7+&;#3X*mkd-3r`FP;rVL|B?fT- z7AojJX}ymR_JL{MMFLaxzPrHBf$Qd{Q8>+w1G$sr8egkN5fT4h; zQI$9kjg+;Gqk}N`(8~cldliQhX4b>G(9*@KZVhO=EwIEKriJ@m3T6J!G$(5;aYc@Y zKd|hg0xlFR1%ljpD1M6R(3P?_aWMUp;YK=+{u@DC@@U(VUjlZ3z76zl#j%i%V87cgDeb@{d3Srl>*I};$O z)=!WA5QS?IrT&ludQTpUF(Fq?V)F`M~Co<*PnF|j(#L3t>A zzyVOVGXt#PbXfQ2$au{b3DEA@*#VUylC&cur;rP58`Z1$06aV1OOuh?KJ! z)Kn$dSd}3L|E5qszO=~sIuM5g>-uwGkYP7K+BxR{=l+{$j!%(SVa!*e>{M)Xz_$LF zBoVLnm>xb$QMd*I-GV`jIR}~ukWgL)>Szas92%|&6zX8_U}s;;DQ@TH{RVD^D^sK2zG4S(2$f1Oe(E1Q4bgE~I8 z`#2uRq%Ds`A7~m=hPY6ce9ms6c7;&pqsDv6O)c6BtIo6j<7MC9xdbpi0i-Dj!-$9d-x<%4=cW=%5-S-9qyq?30EYAt?tdmdS)yG=eR=l) zCq)&b(L?Y2|18lYU-U$s%Yc4T9q$|-$A4x#xpOxhzaoAH=GG)& z0AY{%#&4fVb*LvN!}eQazOevgmIcU+4rX|+$eat7v;_Bq-s|0nM8>F_Fy zeEZc;#dUD8`SWlRg}!Gt2vnVyrMpK5^LoM$?jQ;+l=U$ZHH9}y-oPZeu z*40PTJ{$iKR~cdq0XE~{6V&Z=aro(-O7Ju1!Ev{VbUMc+7#Or*V9N&U(GQ*j?N<~7 zWeC^>Z233ma(RB3Jpw=n0Y(n%HPwU9ZtvkNEo^6J;3DE^X8Bjg{%F2uSm*DR)!7_k z5Mu*JO9$8#md6EkG?A|yj27zIpPK^aK?>F1(nuetKAP256o&ev3yWJRzCoAd7fjq}fW?9eSbn*0aW z)F%DU<~b=5((#@gO^pJ(kJ}754+F68KblhLIQ-EF!?1oGFR*(&Wr9B|+sbjGqfzQ$ zA3ZC_osZ}|PZf?vae`%W0-Vb8bmtcfZ2Y_9eK{I723EUjGS6oDdwi(lJV&n_!JfUn v%srducu1P#=tti@h1IOdnzPaWxWuF=g8(d#Admy_uNLqX*jj)U6ZHQ88@*)} diff --git a/DepFiles/unittest/junit-4.12.jar b/DepFiles/unittest/junit-4.12.jar deleted file mode 100644 index 3a7fc266c3e32283a2b21fe12166ebdcc33a1da1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 314932 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

&R7;REBZd0NaNVcN6Eoy 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

+ * This estimate doesn't include the size of the {@link SpatialReference} object + * because instances of {@link SpatialReference} are expected to be shared among + * geometry objects. + * + * @return Returns an estimate of this object size in bytes. + */ + public long estimateMemorySize() { + long sz = SIZE_OF_MAPGEOMETRY; + if (m_geometry != null) + sz += m_geometry.estimateMemorySize(); + return sz; + } + @Override public int hashCode() { SpatialReference sr = getSpatialReference(); diff --git a/src/main/java/com/esri/core/geometry/OperatorDensifyByLength.java b/src/main/java/com/esri/core/geometry/OperatorDensifyByLength.java index 085dd397..d9d9d692 100644 --- a/src/main/java/com/esri/core/geometry/OperatorDensifyByLength.java +++ b/src/main/java/com/esri/core/geometry/OperatorDensifyByLength.java @@ -49,7 +49,7 @@ public Type getType() { * After that the curves are replaced with straight segments. * @param progressTracker * @return Returns the densified geometries (It does nothing to geometries - * with dim < 1, but simply passes them along). + * with dim < 1, but simply passes them along). */ public abstract GeometryCursor execute(GeometryCursor inputGeometries, double maxLength, ProgressTracker progressTracker); @@ -67,7 +67,7 @@ public abstract GeometryCursor execute(GeometryCursor inputGeometries, * After that the curves are replaced with straight segments. * @param progressTracker * @return Returns the densified geometry. (It does nothing to geometries - * with dim < 1, but simply passes them along). + * with dim < 1, but simply passes them along). */ public abstract Geometry execute(Geometry inputGeometry, double maxLength, ProgressTracker progressTracker); diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java index 87de2d4a..2a25215d 100644 --- a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java +++ b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java @@ -34,7 +34,7 @@ public Type getType() { * Performs the ImportFromGeoJson operation. * * @param type Use the {@link Geometry.Type} enum. - * @param jsonObject The JSONObject holding the geometry and spatial reference. + * @param jsonReader The JSONReader. * @return Returns the imported MapGeometry. * @throws JsonGeometryException */ @@ -49,7 +49,6 @@ public Type getType() { * @param type Use the {@link Geometry.Type} enum. * @param geoJsonString The string holding the Geometry in geoJson format. * @return Returns the imported MapGeometry. - * @throws JSONException * */ public abstract MapGeometry execute(int import_flags, Geometry.Type type, String geoJsonString, ProgressTracker progress_tracker); @@ -61,7 +60,6 @@ public Type getType() { * @param import_flags Use the {@link GeoJsonImportFlags} interface. * @param geoJsonString The string holding the Geometry in geoJson format. * @return Returns the imported MapOGCStructure. - * @throws JSONException */ public abstract MapOGCStructure executeOGC(int import_flags, String geoJsonString, ProgressTracker progress_tracker); diff --git a/src/main/java/com/esri/core/geometry/OperatorIntersection.java b/src/main/java/com/esri/core/geometry/OperatorIntersection.java index ee3b4833..5afc6e37 100644 --- a/src/main/java/com/esri/core/geometry/OperatorIntersection.java +++ b/src/main/java/com/esri/core/geometry/OperatorIntersection.java @@ -53,12 +53,12 @@ public abstract GeometryCursor execute(GeometryCursor inputGeometries, *@param sr The spatial reference is used to get tolerance value. Can be null, then the tolerance is not used and the operation is performed with *a small tolerance value just enough to make the operation robust. *@param progress_tracker Allows to cancel the operation. Can be null. - *@param dimensionMask The dimension of the intersection. The value is either -1, or a bitmask mask of values (1 << dim). + *@param dimensionMask The dimension of the intersection. The value is either -1, or a bitmask mask of values (1 << dim). *The value of -1 means the lower dimension in the intersecting pair. *This is a fastest option when intersecting polygons with polygons or polylines. - *The bitmask of values (1 << dim), where dim is the desired dimension value, is used to indicate + *The bitmask of values (1 << dim), where dim is the desired dimension value, is used to indicate *what dimensions of geometry one wants to be returned. For example, to return - *multipoints and lines only, pass (1 << 0) | (1 << 1), which is equivalen to 1 | 2, or 3. + *multipoints and lines only, pass (1 << 0) | (1 << 1), which is equivalen to 1 | 2, or 3. *@return Returns the cursor of the intersection result. The cursors' getGeometryID method returns the current ID of the input geometry *being processed. When dimensionMask is a bitmask, there will be n result geometries per one input geometry returned, where n is the number *of bits set in the bitmask. For example, if the dimensionMask is 5, there will be two geometries per one input geometry. @@ -81,7 +81,7 @@ public abstract GeometryCursor execute(GeometryCursor input_geometries, *points, but the overlaps only). *The call is equivalent to calling the overloaded method using cursors: *execute(new SimpleGeometryCursor(input_geometry), new SimpleGeometryCursor(intersector), sr, progress_tracker, mask).next(); - *where mask can be either -1 or min(1 << input_geometry.getDimension(), 1 << intersector.getDimension()); + *where mask can be either -1 or min(1 << input_geometry.getDimension(), 1 << intersector.getDimension()); *@param inputGeometry is the Geometry instance to be intersected by the intersector. *@param intersector is the intersector Geometry. *@param sr The spatial reference to get the tolerance value from. Can be null, then the tolerance is calculated from the input geometries. diff --git a/src/main/java/com/esri/core/geometry/OperatorOffset.java b/src/main/java/com/esri/core/geometry/OperatorOffset.java index 7b4f3673..bdcf5005 100644 --- a/src/main/java/com/esri/core/geometry/OperatorOffset.java +++ b/src/main/java/com/esri/core/geometry/OperatorOffset.java @@ -43,7 +43,7 @@ public enum JoinType { * * The offset operation creates a geometry that is a constant distance from * an input polyline or polygon. It is similar to buffering, but produces a - * one sided result. If offsetDistance > 0, then the offset geometry is + * one sided result. If offsetDistance greater than 0, then the offset geometry is * constructed to the right of the oriented input geometry, otherwise it is * constructed to the left. For a simple polygon, the orientation of outer * rings is clockwise and for inner rings it is counter clockwise. So the @@ -82,7 +82,7 @@ public abstract GeometryCursor execute(GeometryCursor inputGeometries, * * The offset operation creates a geometry that is a constant distance from * an input polyline or polygon. It is similar to buffering, but produces a - * one sided result. If offsetDistance > 0, then the offset geometry is + * one sided result. If offsetDistance greater than 0, then the offset geometry is * constructed to the right of the oriented input geometry, otherwise it is * constructed to the left. For a simple polygon, the orientation of outer * rings is clockwise and for inner rings it is counter clockwise. So the diff --git a/src/main/java/com/esri/core/geometry/Point.java b/src/main/java/com/esri/core/geometry/Point.java index d96589ae..a421400f 100644 --- a/src/main/java/com/esri/core/geometry/Point.java +++ b/src/main/java/com/esri/core/geometry/Point.java @@ -39,7 +39,7 @@ public class Point extends Geometry implements Serializable { //We are using writeReplace instead. //private static final long serialVersionUID = 2L; - double[] m_attributes; // use doubles to store everything (long are bitcast) + double[] m_attributes; // use doubles to store everything (long are bitcast) /** * Creates an empty 2D point. @@ -626,22 +626,22 @@ public int hashCode() { return hashCode; } - @Override - public Geometry getBoundary() { - return null; - } - - @Override - public void replaceNaNs(int semantics, double value) { - addAttribute(semantics); - if (isEmpty()) - return; - - int ncomps = VertexDescription.getComponentCount(semantics); - for (int i = 0; i < ncomps; i++) { - double v = getAttributeAsDbl(semantics, i); - if (Double.isNaN(v)) - setAttribute(semantics, i, value); - } - } + @Override + public Geometry getBoundary() { + return null; + } + + @Override + public void replaceNaNs(int semantics, double value) { + addAttribute(semantics); + if (isEmpty()) + return; + + int ncomps = VertexDescription.getComponentCount(semantics); + for (int i = 0; i < ncomps; i++) { + double v = getAttributeAsDbl(semantics, i); + if (Double.isNaN(v)) + setAttribute(semantics, i, value); + } + } } diff --git a/src/main/java/com/esri/core/geometry/Point2D.java b/src/main/java/com/esri/core/geometry/Point2D.java index 245b8156..90cc1e46 100644 --- a/src/main/java/com/esri/core/geometry/Point2D.java +++ b/src/main/java/com/esri/core/geometry/Point2D.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -435,7 +435,7 @@ public boolean isNaN() { } /** - * Calculates the orientation of the triangle formed by p->q->r. Returns 1 + * Calculates the orientation of the triangle formed by p, q, r. Returns 1 * for counter-clockwise, -1 for clockwise, and 0 for collinear. May use * high precision arithmetics for some special degenerate cases. */ diff --git a/src/main/java/com/esri/core/geometry/Polygon.java b/src/main/java/com/esri/core/geometry/Polygon.java index a8298077..949a3797 100644 --- a/src/main/java/com/esri/core/geometry/Polygon.java +++ b/src/main/java/com/esri/core/geometry/Polygon.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -145,39 +145,41 @@ public int getExteriorRingCount() { return m_impl.getOGCPolygonCount(); } - public interface FillRule { - /** - * odd-even fill rule. This is the default value. A point is in the polygon interior if a ray - * from this point to infinity crosses odd number of segments of the polygon. - */ - public final static int enumFillRuleOddEven = 0; - /** - * winding fill rule (aka non-zero winding rule). A point is in the polygon interior if a winding number is not zero. - * To compute a winding number for a point, draw a ray from this point to infinity. If N is the number of times the ray - * crosses segments directed up and the M is the number of times it crosses segments directed down, - * then the winding number is equal to N-M. - */ - public final static int enumFillRuleWinding = 1; - }; - - /** - *Fill rule for the polygon that defines the interior of the self intersecting polygon. It affects the Simplify operation. - *Can be use by drawing code to pass around the fill rule of graphic path. - *This property is not persisted in any format yet. - *See also Polygon.FillRule. - */ - public void setFillRule(int rule) { - m_impl.setFillRule(rule); - } - - /** - *Fill rule for the polygon that defines the interior of the self intersecting polygon. It affects the Simplify operation. - *Changing the fill rule on the polygon that has no self intersections has no physical effect. - *Can be use by drawing code to pass around the fill rule of graphic path. - *This property is not persisted in any format yet. - *See also Polygon.FillRule. - */ - public int getFillRule() { - return m_impl.getFillRule(); - } + public interface FillRule { + /** + * odd-even fill rule. This is the default value. A point is in the polygon + * interior if a ray from this point to infinity crosses odd number of segments + * of the polygon. + */ + public final static int enumFillRuleOddEven = 0; + /** + * winding fill rule (aka non-zero winding rule). A point is in the polygon + * interior if a winding number is not zero. To compute a winding number for a + * point, draw a ray from this point to infinity. If N is the number of times + * the ray crosses segments directed up and the M is the number of times it + * crosses segments directed down, then the winding number is equal to N-M. + */ + public final static int enumFillRuleWinding = 1; + }; + + /** + * Fill rule for the polygon that defines the interior of the self intersecting + * polygon. It affects the Simplify operation. Can be use by drawing code to + * pass around the fill rule of graphic path. This property is not persisted in + * any format yet. See also Polygon.FillRule. + */ + public void setFillRule(int rule) { + m_impl.setFillRule(rule); + } + + /** + * Fill rule for the polygon that defines the interior of the self intersecting + * polygon. It affects the Simplify operation. Changing the fill rule on the + * polygon that has no self intersections has no physical effect. Can be use by + * drawing code to pass around the fill rule of graphic path. This property is + * not persisted in any format yet. See also Polygon.FillRule. + */ + public int getFillRule() { + return m_impl.getFillRule(); + } } diff --git a/src/main/java/com/esri/core/geometry/Polyline.java b/src/main/java/com/esri/core/geometry/Polyline.java index 0d842806..9f45d7ea 100644 --- a/src/main/java/com/esri/core/geometry/Polyline.java +++ b/src/main/java/com/esri/core/geometry/Polyline.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/main/java/com/esri/core/geometry/SizeOf.java b/src/main/java/com/esri/core/geometry/SizeOf.java index 86683a93..31460366 100644 --- a/src/main/java/com/esri/core/geometry/SizeOf.java +++ b/src/main/java/com/esri/core/geometry/SizeOf.java @@ -21,6 +21,7 @@ email: contracts@esri.com */ + package com.esri.core.geometry; import static sun.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; @@ -38,90 +39,83 @@ import static sun.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET; import static sun.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE; -public final class SizeOf -{ - public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT = 24; +public final class SizeOf { + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT = 24; - public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_DBL = 24; + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_DBL = 24; - public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT8 = 24; + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT8 = 24; - public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT16 = 24; + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT16 = 24; - public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT32 = 24; + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT32 = 24; - public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT64 = 24; + public static final int SIZE_OF_ATTRIBUTE_STREAM_OF_INT64 = 24; - public static final int SIZE_OF_ENVELOPE = 32; + public static final int SIZE_OF_ENVELOPE = 32; - public static final int SIZE_OF_ENVELOPE2D = 48; + public static final int SIZE_OF_ENVELOPE2D = 48; - public static final int SIZE_OF_LINE = 56; + public static final int SIZE_OF_LINE = 56; - public static final int SIZE_OF_MULTI_PATH = 24; + public static final int SIZE_OF_MULTI_PATH = 24; - public static final int SIZE_OF_MULTI_PATH_IMPL = 112; + public static final int SIZE_OF_MULTI_PATH_IMPL = 112; - public static final int SIZE_OF_MULTI_POINT = 24; + public static final int SIZE_OF_MULTI_POINT = 24; - public static final int SIZE_OF_MULTI_POINT_IMPL = 56; + public static final int SIZE_OF_MULTI_POINT_IMPL = 56; - public static final int SIZE_OF_POINT = 24; + public static final int SIZE_OF_POINT = 24; - public static final int SIZE_OF_POLYGON = 24; + public static final int SIZE_OF_POLYGON = 24; - public static final int SIZE_OF_POLYLINE = 24; + public static final int SIZE_OF_POLYLINE = 24; - public static final int SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION = 24; + public static final int SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION = 24; - public static final int SIZE_OF_OGC_LINE_STRING = 24; + public static final int SIZE_OF_OGC_LINE_STRING = 24; - public static final int SIZE_OF_OGC_MULTI_LINE_STRING = 24; + public static final int SIZE_OF_OGC_MULTI_LINE_STRING = 24; - public static final int SIZE_OF_OGC_MULTI_POINT = 24; + public static final int SIZE_OF_OGC_MULTI_POINT = 24; - public static final int SIZE_OF_OGC_MULTI_POLYGON = 24; + public static final int SIZE_OF_OGC_MULTI_POLYGON = 24; - public static final int SIZE_OF_OGC_POINT = 24; + public static final int SIZE_OF_OGC_POINT = 24; - public static final int SIZE_OF_OGC_POLYGON = 24; + public static final int SIZE_OF_OGC_POLYGON = 24; + + public static final int SIZE_OF_MAPGEOMETRY = 24; - public static long sizeOfByteArray(int length) - { - return ARRAY_BYTE_BASE_OFFSET + (((long) ARRAY_BYTE_INDEX_SCALE) * length); - } + public static long sizeOfByteArray(int length) { + return ARRAY_BYTE_BASE_OFFSET + (((long) ARRAY_BYTE_INDEX_SCALE) * length); + } - public static long sizeOfShortArray(int length) - { - return ARRAY_SHORT_BASE_OFFSET + (((long) ARRAY_SHORT_INDEX_SCALE) * length); - } + public static long sizeOfShortArray(int length) { + return ARRAY_SHORT_BASE_OFFSET + (((long) ARRAY_SHORT_INDEX_SCALE) * length); + } - public static long sizeOfCharArray(int length) - { - return ARRAY_CHAR_BASE_OFFSET + (((long) ARRAY_CHAR_INDEX_SCALE) * length); - } + public static long sizeOfCharArray(int length) { + return ARRAY_CHAR_BASE_OFFSET + (((long) ARRAY_CHAR_INDEX_SCALE) * length); + } - public static long sizeOfIntArray(int length) - { - return ARRAY_INT_BASE_OFFSET + (((long) ARRAY_INT_INDEX_SCALE) * length); - } + public static long sizeOfIntArray(int length) { + return ARRAY_INT_BASE_OFFSET + (((long) ARRAY_INT_INDEX_SCALE) * length); + } - public static long sizeOfLongArray(int length) - { - return ARRAY_LONG_BASE_OFFSET + (((long) ARRAY_LONG_INDEX_SCALE) * length); - } + public static long sizeOfLongArray(int length) { + return ARRAY_LONG_BASE_OFFSET + (((long) ARRAY_LONG_INDEX_SCALE) * length); + } - public static long sizeOfFloatArray(int length) - { - return ARRAY_FLOAT_BASE_OFFSET + (((long) ARRAY_FLOAT_INDEX_SCALE) * length); - } + public static long sizeOfFloatArray(int length) { + return ARRAY_FLOAT_BASE_OFFSET + (((long) ARRAY_FLOAT_INDEX_SCALE) * length); + } - public static long sizeOfDoubleArray(int length) - { - return ARRAY_DOUBLE_BASE_OFFSET + (((long) ARRAY_DOUBLE_INDEX_SCALE) * length); - } + public static long sizeOfDoubleArray(int length) { + return ARRAY_DOUBLE_BASE_OFFSET + (((long) ARRAY_DOUBLE_INDEX_SCALE) * length); + } - private SizeOf() - { - } + private SizeOf() { + } } diff --git a/src/main/java/com/esri/core/geometry/SpatialReference.java b/src/main/java/com/esri/core/geometry/SpatialReference.java index 22b0c74f..4c337e27 100644 --- a/src/main/java/com/esri/core/geometry/SpatialReference.java +++ b/src/main/java/com/esri/core/geometry/SpatialReference.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 4ad748be..a3f60a6d 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java index ba516b5f..64d2bfc2 100644 --- a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java +++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java @@ -15,92 +15,81 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -public class TestEstimateMemorySize -{ - @Test - public void testInstanceSizes() - { - assertEquals(getInstanceSize(AttributeStreamOfFloat.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT); - assertEquals(getInstanceSize(AttributeStreamOfDbl.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_DBL); - assertEquals(getInstanceSize(AttributeStreamOfInt8.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT8); - assertEquals(getInstanceSize(AttributeStreamOfInt16.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT16); - assertEquals(getInstanceSize(AttributeStreamOfInt32.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32); - assertEquals(getInstanceSize(AttributeStreamOfInt64.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT64); - assertEquals(getInstanceSize(Envelope.class), SizeOf.SIZE_OF_ENVELOPE); - assertEquals(getInstanceSize(Envelope2D.class), SizeOf.SIZE_OF_ENVELOPE2D); - assertEquals(getInstanceSize(Line.class), SizeOf.SIZE_OF_LINE); - assertEquals(getInstanceSize(MultiPath.class), SizeOf.SIZE_OF_MULTI_PATH); - assertEquals(getInstanceSize(MultiPathImpl.class), SizeOf.SIZE_OF_MULTI_PATH_IMPL); - assertEquals(getInstanceSize(MultiPoint.class), SizeOf.SIZE_OF_MULTI_POINT); - assertEquals(getInstanceSize(MultiPointImpl.class), SizeOf.SIZE_OF_MULTI_POINT_IMPL); - assertEquals(getInstanceSize(Point.class), SizeOf.SIZE_OF_POINT); - assertEquals(getInstanceSize(Polygon.class), SizeOf.SIZE_OF_POLYGON); - assertEquals(getInstanceSize(Polyline.class), SizeOf.SIZE_OF_POLYLINE); - assertEquals(getInstanceSize(OGCConcreteGeometryCollection.class), SizeOf.SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION); - assertEquals(getInstanceSize(OGCLineString.class), SizeOf.SIZE_OF_OGC_LINE_STRING); - assertEquals(getInstanceSize(OGCMultiLineString.class), SizeOf.SIZE_OF_OGC_MULTI_LINE_STRING); - assertEquals(getInstanceSize(OGCMultiPoint.class), SizeOf.SIZE_OF_OGC_MULTI_POINT); - assertEquals(getInstanceSize(OGCMultiPolygon.class), SizeOf.SIZE_OF_OGC_MULTI_POLYGON); - assertEquals(getInstanceSize(OGCPoint.class), SizeOf.SIZE_OF_OGC_POINT); - assertEquals(getInstanceSize(OGCPolygon.class), SizeOf.SIZE_OF_OGC_POLYGON); - } +public class TestEstimateMemorySize { + @Test + public void testInstanceSizes() { + assertEquals(getInstanceSize(AttributeStreamOfFloat.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_FLOAT); + assertEquals(getInstanceSize(AttributeStreamOfDbl.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_DBL); + assertEquals(getInstanceSize(AttributeStreamOfInt8.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT8); + assertEquals(getInstanceSize(AttributeStreamOfInt16.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT16); + assertEquals(getInstanceSize(AttributeStreamOfInt32.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32); + assertEquals(getInstanceSize(AttributeStreamOfInt64.class), SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT64); + assertEquals(getInstanceSize(Envelope.class), SizeOf.SIZE_OF_ENVELOPE); + assertEquals(getInstanceSize(Envelope2D.class), SizeOf.SIZE_OF_ENVELOPE2D); + assertEquals(getInstanceSize(Line.class), SizeOf.SIZE_OF_LINE); + assertEquals(getInstanceSize(MultiPath.class), SizeOf.SIZE_OF_MULTI_PATH); + assertEquals(getInstanceSize(MultiPathImpl.class), SizeOf.SIZE_OF_MULTI_PATH_IMPL); + assertEquals(getInstanceSize(MultiPoint.class), SizeOf.SIZE_OF_MULTI_POINT); + assertEquals(getInstanceSize(MultiPointImpl.class), SizeOf.SIZE_OF_MULTI_POINT_IMPL); + assertEquals(getInstanceSize(Point.class), SizeOf.SIZE_OF_POINT); + assertEquals(getInstanceSize(Polygon.class), SizeOf.SIZE_OF_POLYGON); + assertEquals(getInstanceSize(Polyline.class), SizeOf.SIZE_OF_POLYLINE); + assertEquals(getInstanceSize(OGCConcreteGeometryCollection.class), + SizeOf.SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION); + assertEquals(getInstanceSize(OGCLineString.class), SizeOf.SIZE_OF_OGC_LINE_STRING); + assertEquals(getInstanceSize(OGCMultiLineString.class), SizeOf.SIZE_OF_OGC_MULTI_LINE_STRING); + assertEquals(getInstanceSize(OGCMultiPoint.class), SizeOf.SIZE_OF_OGC_MULTI_POINT); + assertEquals(getInstanceSize(OGCMultiPolygon.class), SizeOf.SIZE_OF_OGC_MULTI_POLYGON); + assertEquals(getInstanceSize(OGCPoint.class), SizeOf.SIZE_OF_OGC_POINT); + assertEquals(getInstanceSize(OGCPolygon.class), SizeOf.SIZE_OF_OGC_POLYGON); + } - private static int getInstanceSize(Class clazz) - { - return ClassLayout.parseClass(clazz).instanceSize(); - } + private static long getInstanceSize(Class clazz) { + return ClassLayout.parseClass(clazz).instanceSize(); + } - @Test - public void testPoint() - { - testGeometry(parseWkt("POINT (1 2)")); - } + @Test + public void testPoint() { + testGeometry(parseWkt("POINT (1 2)")); + } - @Test - public void testMultiPoint() - { - testGeometry(parseWkt("MULTIPOINT (0 0, 1 1, 2 3)")); - } + @Test + public void testMultiPoint() { + testGeometry(parseWkt("MULTIPOINT (0 0, 1 1, 2 3)")); + } - @Test - public void testLineString() - { - testGeometry(parseWkt("LINESTRING (0 1, 2 3, 4 5)")); - } + @Test + public void testLineString() { + testGeometry(parseWkt("LINESTRING (0 1, 2 3, 4 5)")); + } - @Test - public void testMultiLineString() - { - testGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); - } + @Test + public void testMultiLineString() { + testGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); + } - @Test - public void testPolygon() - { - testGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); - } + @Test + public void testPolygon() { + testGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); + } - @Test - public void testMultiPolygon() - { - testGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))")); - } + @Test + public void testMultiPolygon() { + testGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))")); + } - @Test - public void testGeometryCollection() - { - testGeometry(parseWkt("GEOMETRYCOLLECTION (POINT(4 6), LINESTRING(4 6,7 10))")); - } + @Test + public void testGeometryCollection() { + testGeometry(parseWkt("GEOMETRYCOLLECTION (POINT(4 6), LINESTRING(4 6,7 10))")); + } - private void testGeometry(OGCGeometry geometry) - { - assertTrue(geometry.estimateMemorySize() > 0); - } + private void testGeometry(OGCGeometry geometry) { + assertTrue(geometry.estimateMemorySize() > 0); + } - private static OGCGeometry parseWkt(String wkt) - { - OGCGeometry geometry = OGCGeometry.fromText(wkt); - geometry.setSpatialReference(null); - return geometry; - } + private static OGCGeometry parseWkt(String wkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + geometry.setSpatialReference(null); + return geometry; + } } From b3d9cc30cb68c883d3155eaa3271eaa468c4a195 Mon Sep 17 00:00:00 2001 From: Annette Locke Date: Fri, 16 Mar 2018 14:53:43 -0700 Subject: [PATCH 10/75] Add license header. --- .../core/geometry/TestEstimateMemorySize.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java index 64d2bfc2..e4195c58 100644 --- a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java +++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java @@ -1,4 +1,28 @@ -package com.esri.core.geometry; +/* + Copyright 1995-2018 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ + + package com.esri.core.geometry; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; import com.esri.core.geometry.ogc.OGCGeometry; From c733591b114d2d55fdd4646331f10ba0d8ca47d2 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Mon, 19 Mar 2018 11:40:45 -0700 Subject: [PATCH 11/75] Geometry release v2.1.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d55f9fcf..2c6e2580 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.0.0 + 2.1.0 jar Esri Geometry API for Java From 517039c635cd07acbb61aa99d260855da23f531e Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Tue, 20 Mar 2018 09:50:15 -0700 Subject: [PATCH 12/75] README: v2.1.0 ; POM: v2.2 development (#161) --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 34589c2f..bcc099fe 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 2.0.0 + 2.1.0 ``` diff --git a/pom.xml b/pom.xml index 2c6e2580..0255ec18 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.1.0 + 2.2.0-SNAPSHOT jar Esri Geometry API for Java From 5602a2a5d5266fc7cae7548b456a2d16cd1c9af9 Mon Sep 17 00:00:00 2001 From: danio Date: Thu, 29 Mar 2018 21:22:59 +0100 Subject: [PATCH 13/75] Test union operator with some geometry (#165) @danio Looks good. Thank you for the tests! --- .../com/esri/core/geometry/TestUnion.java | 129 +++++++++++++++++- 1 file changed, 124 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/esri/core/geometry/TestUnion.java b/src/test/java/com/esri/core/geometry/TestUnion.java index 55392e39..77032413 100644 --- a/src/test/java/com/esri/core/geometry/TestUnion.java +++ b/src/test/java/com/esri/core/geometry/TestUnion.java @@ -40,11 +40,6 @@ protected void tearDown() throws Exception { @Test public static void testUnion() { - Point pt = new Point(10, 20); - - Point pt2 = new Point(); - pt2.setXY(10, 10); - Envelope env1 = new Envelope(10, 10, 30, 50); Envelope env2 = new Envelope(30, 10, 60, 50); Geometry[] geomArray = new Geometry[] { env1, env2 }; @@ -57,5 +52,129 @@ public static void testUnion() { GeometryCursor outputCursor = union.execute(inputGeometries, sr, null); Geometry result = outputCursor.next(); + + MultiPath path = (MultiPath)result; + assertEquals(1, path.getPathCount()); + assertEquals(6, path.getPathEnd(0)); + assertEquals(new Point2D(10, 10), path.getXY(0)); + assertEquals(new Point2D(10, 50), path.getXY(1)); + assertEquals(new Point2D(30, 50), path.getXY(2)); + assertEquals(new Point2D(60, 50), path.getXY(3)); + assertEquals(new Point2D(60, 10), path.getXY(4)); + assertEquals(new Point2D(30, 10), path.getXY(5)); + } + + @Test + public static void testUnionDistinctGeometries() { + Envelope env = new Envelope(1, 5, 3, 10); + + Polygon polygon = new Polygon(); + polygon.startPath(new Point(4, 3)); + polygon.lineTo(new Point(7, 6)); + polygon.lineTo(new Point(6, 8)); + polygon.lineTo(new Point(4, 3)); + + Geometry[] geomArray = new Geometry[] { env, polygon }; + SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor( + geomArray); + OperatorUnion union = (OperatorUnion) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.Union); + SpatialReference sr = SpatialReference.create(4326); + + GeometryCursor outputCursor = union.execute(inputGeometries, sr, null); + Geometry result = outputCursor.next(); + + MultiPath path = (MultiPath)result; + assertEquals(2, path.getPathCount()); + + assertEquals(3, path.getPathEnd(0)); + assertEquals(7, path.getPathEnd(1)); + // from polygon + assertEquals(new Point2D(4, 3), path.getXY(0)); + assertEquals(new Point2D(6, 8), path.getXY(1)); + assertEquals(new Point2D(7, 6), path.getXY(2)); + // from envelope + assertEquals(new Point2D(1, 5), path.getXY(3)); + assertEquals(new Point2D(1, 10), path.getXY(4)); + assertEquals(new Point2D(3, 10), path.getXY(5)); + assertEquals(new Point2D(3, 5), path.getXY(6)); + } + + @Test + public static void testUnionCoincidentPolygons() { + Polygon polygon1 = new Polygon(); + polygon1.startPath(new Point(3, 2)); + polygon1.lineTo(new Point(1, 2)); + polygon1.lineTo(new Point(1, 4)); + polygon1.lineTo(new Point(3, 4)); + polygon1.lineTo(new Point(3, 2)); + + Polygon polygon2 = new Polygon(); + polygon2.startPath(new Point(1, 2)); + polygon2.lineTo(new Point(1, 4)); + polygon2.lineTo(new Point(3, 4)); + polygon2.lineTo(new Point(3, 2)); + polygon2.lineTo(new Point(1, 2)); + + Geometry[] geomArray = new Geometry[] { polygon1, polygon2 }; + SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor( + geomArray); + OperatorUnion union = (OperatorUnion) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.Union); + SpatialReference sr = SpatialReference.create(4326); + + GeometryCursor outputCursor = union.execute(inputGeometries, sr, null); + Geometry result = outputCursor.next(); + + MultiPath path = (MultiPath)result; + assertEquals(1, path.getPathCount()); + assertEquals(4, path.getPathEnd(0)); + assertEquals(new Point2D(1, 2), path.getXY(0)); + assertEquals(new Point2D(1, 4), path.getXY(1)); + assertEquals(new Point2D(3, 4), path.getXY(2)); + assertEquals(new Point2D(3, 2), path.getXY(3)); + } + + @Test + public static void testUnionCoincidentPolygonsWithReverseWinding() { + // Input polygons have CCW winding, result is always CW + Polygon polygon1 = new Polygon(); + polygon1.startPath(new Point(3, 2)); + polygon1.lineTo(new Point(3, 4)); + polygon1.lineTo(new Point(1, 4)); + polygon1.lineTo(new Point(1, 2)); + polygon1.lineTo(new Point(3, 2)); + + Polygon polygon2 = new Polygon(); + polygon2.startPath(new Point(1, 2)); + polygon2.lineTo(new Point(3, 2)); + polygon2.lineTo(new Point(3, 4)); + polygon2.lineTo(new Point(1, 4)); + polygon2.lineTo(new Point(1, 2)); + + Polygon expectedPolygon = new Polygon(); + expectedPolygon.startPath(new Point(1, 2)); + expectedPolygon.lineTo(new Point(1, 4)); + expectedPolygon.lineTo(new Point(3, 4)); + expectedPolygon.lineTo(new Point(3, 2)); + expectedPolygon.lineTo(new Point(1, 2)); + + Geometry[] geomArray = new Geometry[] { polygon1, polygon2 }; + SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor( + geomArray); + OperatorUnion union = (OperatorUnion) OperatorFactoryLocal + .getInstance().getOperator(Operator.Type.Union); + SpatialReference sr = SpatialReference.create(4326); + + GeometryCursor outputCursor = union.execute(inputGeometries, sr, null); + Geometry result = outputCursor.next(); + + MultiPath path = (MultiPath)result; + assertEquals(1, path.getPathCount()); + assertEquals(4, path.getPathEnd(0)); + assertEquals(new Point2D(1, 2), path.getXY(0)); + assertEquals(new Point2D(1, 4), path.getXY(1)); + assertEquals(new Point2D(3, 4), path.getXY(2)); + assertEquals(new Point2D(3, 2), path.getXY(3)); } } From e631c8aadcc23d6dfdcfc6ec38668d7079bda522 Mon Sep 17 00:00:00 2001 From: danio Date: Thu, 29 Mar 2018 23:04:10 +0100 Subject: [PATCH 14/75] Ant doesn't work for building (#163) --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index bcc099fe..46b42a05 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,9 @@ The Esri Geometry API for Java can be used to enable spatial data processing in Building the source: 1. Download and unzip the .zip file, or clone the repository. -2. Deploy the esri-geometry-api.jar to the target system, add a reference to it in a Java project. -3. To build the jar, Javadoc, and run the unit-tests, run the “ant” command-line command from within the cloned directory. The ant tool runs the “build.xml” script which creates the jar, runs the unit tests, then creates the Javadoc documentation files. +1. To build the jar, run the `mvn compile` command-line command from within the cloned directory. +1. Deploy the esri-geometry-api.jar to the target system, add a reference to it in a Java project. +1. To run the unit-tests, run the `mvn test` command-line command from within the cloned directory. The project is also available as a [Maven](http://maven.apache.org/) dependency: @@ -30,7 +31,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: ## Requirements * Java JDK 1.6 or greater. -* [Apache Ant](http://ant.apache.org/) build system. +* [Apache Maven](https://maven.apache.org/) build system. * Experience developing MapReduce applications for [Apache Hadoop](http://hadoop.apache.org/). * Familiarity with text-based spatial data formats such as JSON or WKT would be useful. From 27adbbbb8e5bd54d8248dcb681347cfaec285994 Mon Sep 17 00:00:00 2001 From: Maria Basmanova Date: Mon, 9 Apr 2018 19:26:20 -0400 Subject: [PATCH 15/75] Add OGCGeometry#centroid operation (#169) @mbasmanova Thank you! --- .../java/com/esri/core/geometry/Operator.java | 2 +- .../core/geometry/OperatorCentroid2D.java | 40 +++++ .../geometry/OperatorCentroid2DLocal.java | 164 ++++++++++++++++++ .../core/geometry/OperatorFactoryLocal.java | 3 +- .../esri/core/geometry/ogc/OGCGeometry.java | 13 ++ .../core/geometry/ogc/OGCMultiSurface.java | 5 - .../esri/core/geometry/ogc/OGCSurface.java | 5 - .../com/esri/core/geometry/TestCentroid.java | 115 ++++++++++++ .../esri/core/geometry/TestOGCCentroid.java | 90 ++++++++++ 9 files changed, 425 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/esri/core/geometry/OperatorCentroid2D.java create mode 100644 src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java create mode 100644 src/test/java/com/esri/core/geometry/TestCentroid.java create mode 100644 src/test/java/com/esri/core/geometry/TestOGCCentroid.java diff --git a/src/main/java/com/esri/core/geometry/Operator.java b/src/main/java/com/esri/core/geometry/Operator.java index 9dcd804d..6866fb16 100644 --- a/src/main/java/com/esri/core/geometry/Operator.java +++ b/src/main/java/com/esri/core/geometry/Operator.java @@ -40,7 +40,7 @@ public enum Type { Union, Difference, - Proximity2D, + Proximity2D, Centroid2D, Relate, Equals, Disjoint, Intersects, Within, Contains, Crosses, Touches, Overlaps, diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java new file mode 100644 index 00000000..f44a21f8 --- /dev/null +++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java @@ -0,0 +1,40 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ +package com.esri.core.geometry; + +public abstract class OperatorCentroid2D extends Operator +{ + @Override + public Type getType() + { + return Type.Centroid2D; + } + + public abstract Point2D execute(Geometry geometry, ProgressTracker progressTracker); + + public static OperatorCentroid2D local() + { + return (OperatorCentroid2D) OperatorFactoryLocal.getInstance().getOperator(Type.Centroid2D); + } +} diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java new file mode 100644 index 00000000..91b7c948 --- /dev/null +++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java @@ -0,0 +1,164 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ +package com.esri.core.geometry; + +import static java.lang.Math.sqrt; + +public class OperatorCentroid2DLocal extends OperatorCentroid2D +{ + @Override + public Point2D execute(Geometry geometry, ProgressTracker progressTracker) + { + if (geometry.isEmpty()) { + return null; + } + + Geometry.Type geometryType = geometry.getType(); + switch (geometryType) { + case Point: + return ((Point) geometry).getXY(); + case Line: + return computeLineCentroid((Line) geometry); + case Envelope: + return ((Envelope) geometry).getCenterXY(); + case MultiPoint: + return computePointsCentroid((MultiPoint) geometry); + case Polyline: + return computePolylineCentroid(((Polyline) geometry)); + case Polygon: + return computePolygonCentroid((Polygon) geometry); + default: + throw new UnsupportedOperationException("Unexpected geometry type: " + geometryType); + } + } + + private static Point2D computeLineCentroid(Line line) + { + return new Point2D((line.getEndX() - line.getStartX()) / 2, (line.getEndY() - line.getStartY()) / 2); + } + + // Points centroid is arithmetic mean of the input points + private static Point2D computePointsCentroid(MultiPoint multiPoint) + { + double xSum = 0; + double ySum = 0; + int pointCount = multiPoint.getPointCount(); + Point2D point2D = new Point2D(); + for (int i = 0; i < pointCount; i++) { + multiPoint.getXY(i, point2D); + xSum += point2D.x; + ySum += point2D.y; + } + return new Point2D(xSum / pointCount, ySum / pointCount); + } + + // Lines centroid is weighted mean of each line segment, weight in terms of line length + private static Point2D computePolylineCentroid(Polyline polyline) + { + double xSum = 0; + double ySum = 0; + double weightSum = 0; + + Point2D startPoint = new Point2D(); + Point2D endPoint = new Point2D(); + for (int i = 0; i < polyline.getPathCount(); i++) { + polyline.getXY(polyline.getPathStart(i), startPoint); + polyline.getXY(polyline.getPathEnd(i) - 1, endPoint); + double dx = endPoint.x - startPoint.x; + double dy = endPoint.y - startPoint.y; + double length = sqrt(dx * dx + dy * dy); + weightSum += length; + xSum += (startPoint.x + endPoint.x) * length / 2; + ySum += (startPoint.y + endPoint.y) * length / 2; + } + return new Point2D(xSum / weightSum, ySum / weightSum); + } + + // Polygon centroid: area weighted average of centroids in case of holes + private static Point2D computePolygonCentroid(Polygon polygon) + { + int pathCount = polygon.getPathCount(); + + if (pathCount == 1) { + return getPolygonSansHolesCentroid(polygon); + } + + double xSum = 0; + double ySum = 0; + double areaSum = 0; + + for (int i = 0; i < pathCount; i++) { + int startIndex = polygon.getPathStart(i); + int endIndex = polygon.getPathEnd(i); + + Polygon sansHoles = getSubPolygon(polygon, startIndex, endIndex); + + Point2D centroid = getPolygonSansHolesCentroid(sansHoles); + double area = sansHoles.calculateArea2D(); + + xSum += centroid.x * area; + ySum += centroid.y * area; + areaSum += area; + } + + return new Point2D(xSum / areaSum, ySum / areaSum); + } + + private static Polygon getSubPolygon(Polygon polygon, int startIndex, int endIndex) + { + Polyline boundary = new Polyline(); + boundary.startPath(polygon.getPoint(startIndex)); + for (int i = startIndex + 1; i < endIndex; i++) { + Point current = polygon.getPoint(i); + boundary.lineTo(current); + } + + final Polygon newPolygon = new Polygon(); + newPolygon.add(boundary, false); + return newPolygon; + } + + // Polygon sans holes centroid: + // c[x] = (Sigma(x[i] + x[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = 0 to N - 1) / (6 * signedArea) + // c[y] = (Sigma(y[i] + y[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = 0 to N - 1) / (6 * signedArea) + private static Point2D getPolygonSansHolesCentroid(Polygon polygon) + { + int pointCount = polygon.getPointCount(); + double xSum = 0; + double ySum = 0; + double signedArea = 0; + + Point2D current = new Point2D(); + Point2D next = new Point2D(); + for (int i = 0; i < pointCount; i++) { + polygon.getXY(i, current); + polygon.getXY((i + 1) % pointCount, next); + double ladder = current.x * next.y - next.x * current.y; + xSum += (current.x + next.x) * ladder; + ySum += (current.y + next.y) * ladder; + signedArea += ladder / 2; + } + return new Point2D(xSum / (signedArea * 6), ySum / (signedArea * 6)); + } +} diff --git a/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java b/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java index 727b4a69..153b4728 100644 --- a/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java @@ -29,7 +29,6 @@ import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.Reader; @@ -61,6 +60,8 @@ public class OperatorFactoryLocal extends OperatorFactory { st_supportedOperators.put(Type.Proximity2D, new OperatorProximity2DLocal()); + st_supportedOperators.put(Type.Centroid2D, + new OperatorCentroid2DLocal()); st_supportedOperators.put(Type.DensifyByLength, new OperatorDensifyByLengthLocal()); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index a3f60a6d..30d11f67 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -38,6 +38,7 @@ import com.esri.core.geometry.OGCStructure; import com.esri.core.geometry.Operator; import com.esri.core.geometry.OperatorBuffer; +import com.esri.core.geometry.OperatorCentroid2D; import com.esri.core.geometry.OperatorConvexHull; import com.esri.core.geometry.OperatorExportToGeoJson; import com.esri.core.geometry.OperatorExportToWkb; @@ -51,6 +52,7 @@ import com.esri.core.geometry.OperatorSimplifyOGC; import com.esri.core.geometry.OperatorUnion; import com.esri.core.geometry.Point; +import com.esri.core.geometry.Point2D; import com.esri.core.geometry.Polygon; import com.esri.core.geometry.Polyline; import com.esri.core.geometry.SimpleGeometryCursor; @@ -427,6 +429,17 @@ public OGCGeometry buffer(double distance) { return OGCGeometry.createFromEsriGeometry(cursor.next(), esriSR); } + public OGCGeometry centroid() { + OperatorCentroid2D op = (OperatorCentroid2D) OperatorFactoryLocal.getInstance() + .getOperator(Operator.Type.Centroid2D); + + Point2D centroid = op.execute(getEsriGeometry(), null); + if (centroid == null) { + return OGCGeometry.createFromEsriGeometry(new Point(), esriSR); + } + return OGCGeometry.createFromEsriGeometry(new Point(centroid), esriSR); + } + public OGCGeometry convexHull() { com.esri.core.geometry.OperatorConvexHull op = (OperatorConvexHull) OperatorFactoryLocal .getInstance().getOperator(Operator.Type.ConvexHull); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java index 1c98be92..5a36dd0e 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java @@ -29,11 +29,6 @@ public double area() { return getEsriGeometry().calculateArea2D(); } - public OGCPoint centroid() { - // TODO - throw new UnsupportedOperationException(); - } - public OGCPoint pointOnSurface() { // TODO throw new UnsupportedOperationException(); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java b/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java index 43d192e6..989dfec8 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java @@ -29,11 +29,6 @@ public double area() { return getEsriGeometry().calculateArea2D(); } - public OGCPoint centroid() { - // TODO: implement me; - throw new UnsupportedOperationException(); - } - public OGCPoint pointOnSurface() { // TODO: support this (need to port OperatorLabelPoint) throw new UnsupportedOperationException(); diff --git a/src/test/java/com/esri/core/geometry/TestCentroid.java b/src/test/java/com/esri/core/geometry/TestCentroid.java new file mode 100644 index 00000000..58c430fb --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestCentroid.java @@ -0,0 +1,115 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ +package com.esri.core.geometry; + +import org.junit.Assert; +import org.junit.Test; + +public class TestCentroid +{ + @Test + public void testPoint() + { + assertCentroid(new Point(1, 2), new Point2D(1, 2)); + } + + @Test + public void testLine() + { + assertCentroid(new Line(0, 0, 10, 20), new Point2D(5, 10)); + } + + @Test + public void testEnvelope() + { + assertCentroid(new Envelope(1, 2, 3,4), new Point2D(2, 3)); + assertCentroid(new Envelope(), null); + } + + @Test + public void testMultiPoint() + { + MultiPoint multiPoint = new MultiPoint(); + multiPoint.add(0, 0); + multiPoint.add(1, 2); + multiPoint.add(3, 1); + multiPoint.add(0, 1); + + assertCentroid(multiPoint, new Point2D(1, 1)); + assertCentroid(new MultiPoint(), null); + } + + @Test + public void testPolyline() + { + Polyline polyline = new Polyline(); + polyline.startPath(0, 0); + polyline.lineTo(1, 2); + polyline.lineTo(3, 4); + assertCentroid(polyline, new Point2D(1.5, 2)); + + polyline.startPath(1, -1); + polyline.lineTo(2, 0); + polyline.lineTo(10, 1); + assertCentroid(polyline, new Point2D(4.093485180902371 , 0.7032574095488145)); + + assertCentroid(new Polyline(), null); + } + + @Test + public void testPolygon() + { + Polygon polygon = new Polygon(); + polygon.startPath(0, 0); + polygon.lineTo(1, 2); + polygon.lineTo(3, 4); + polygon.lineTo(5, 2); + polygon.lineTo(0, 0); + assertCentroid(polygon, new Point2D(2.5, 2)); + + // add a hole + polygon.startPath(2, 2); + polygon.lineTo(2.3, 2); + polygon.lineTo(2.3, 2.4); + polygon.lineTo(2, 2); + assertCentroid(polygon, new Point2D(2.5022670025188916 , 1.9989924433249369)); + + // add another polygon + polygon.startPath(-1, -1); + polygon.lineTo(3, -1); + polygon.lineTo(0.5, -2); + polygon.lineTo(-1, -1); + assertCentroid(polygon, new Point2D(2.166465459423206 , 1.3285043594902748)); + + assertCentroid(new Polygon(), null); + } + + private static void assertCentroid(Geometry geometry, Point2D expectedCentroid) + { + OperatorCentroid2D operator = (OperatorCentroid2D) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.Centroid2D); + + Point2D actualCentroid = operator.execute(geometry, null); + Assert.assertEquals(expectedCentroid, actualCentroid); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestOGCCentroid.java b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java new file mode 100644 index 00000000..bf183bb9 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java @@ -0,0 +1,90 @@ +/* + Copyright 1995-2017 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ +package com.esri.core.geometry; + +import com.esri.core.geometry.ogc.OGCGeometry; +import com.esri.core.geometry.ogc.OGCPoint; +import org.junit.Assert; +import org.junit.Test; + +public class TestOGCCentroid +{ + @Test + public void testPoint() + { + assertCentroid("POINT (1 2)", new Point(1, 2)); + assertEmptyCentroid("POINT EMPTY"); + } + + @Test + public void testLineString() + { + assertCentroid("LINESTRING (1 1, 2 2, 3 3)", new Point(2, 2)); + assertEmptyCentroid("LINESTRING EMPTY"); + } + + @Test + public void testPolygon() + { + assertCentroid("POLYGON ((1 1, 1 4, 4 4, 4 1))'", new Point(2.5, 2.5)); + assertCentroid("POLYGON ((1 1, 5 1, 3 4))", new Point(3, 2)); + assertCentroid("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))", new Point(2.5416666666666665, 2.5416666666666665)); + assertEmptyCentroid("POLYGON EMPTY"); + } + + @Test + public void testMultiPoint() + { + assertCentroid("MULTIPOINT (1 2, 2 4, 3 6, 4 8)", new Point(2.5, 5)); + assertEmptyCentroid("MULTIPOINT EMPTY"); + } + + @Test + public void testMultiLineString() + { + assertCentroid("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", new Point(3, 2)); + assertEmptyCentroid("MULTILINESTRING EMPTY"); + } + + @Test + public void testMultiPolygon() + { + assertCentroid("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1)), ((2 4, 2 6, 6 6, 6 4)))", new Point (3.3333333333333335,4)); + assertEmptyCentroid("MULTIPOLYGON EMPTY"); + } + + private static void assertCentroid(String wkt, Point expectedCentroid) + { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry centroid = geometry.centroid(); + Assert.assertEquals(centroid, new OGCPoint(expectedCentroid, geometry.getEsriSpatialReference())); + } + + private static void assertEmptyCentroid(String wkt) + { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry centroid = geometry.centroid(); + Assert.assertEquals(centroid, new OGCPoint(new Point(), geometry.getEsriSpatialReference())); + } +} From 2407d0b1e3149445f7cee7abe9761fe0109c51d4 Mon Sep 17 00:00:00 2001 From: Maria Basmanova Date: Mon, 9 Apr 2018 20:12:38 -0400 Subject: [PATCH 16/75] Fix Envelope#intersect when other is empty (#168) Thanks! --- .../com/esri/core/geometry/Envelope2D.java | 4 +- .../com/esri/core/geometry/TestEnvelope.java | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/esri/core/geometry/TestEnvelope.java diff --git a/src/main/java/com/esri/core/geometry/Envelope2D.java b/src/main/java/com/esri/core/geometry/Envelope2D.java index 8e44dd33..79433dd7 100644 --- a/src/main/java/com/esri/core/geometry/Envelope2D.java +++ b/src/main/java/com/esri/core/geometry/Envelope2D.java @@ -321,8 +321,10 @@ public boolean isIntersecting(double xmin_, double ymin_, double xmax_, double y * envelope to empty state and returns False. */ public boolean intersect(Envelope2D other) { - if (isEmpty() || other.isEmpty()) + if (isEmpty() || other.isEmpty()) { + setEmpty(); return false; + } if (other.xmin > xmin) xmin = other.xmin; diff --git a/src/test/java/com/esri/core/geometry/TestEnvelope.java b/src/test/java/com/esri/core/geometry/TestEnvelope.java new file mode 100644 index 00000000..56edd466 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestEnvelope.java @@ -0,0 +1,49 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TestEnvelope +{ + @Test + public void testIntersect() + { + assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5)); + assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(1, 1, 6, 6), new Envelope(1, 1, 5, 5)); + assertIntersection(new Envelope(1, 2, 3, 4), new Envelope(0, 0, 2, 3), new Envelope(1, 2, 2, 3)); + + assertNoIntersection(new Envelope(), new Envelope()); + assertNoIntersection(new Envelope(0, 0, 5, 5), new Envelope()); + assertNoIntersection(new Envelope(), new Envelope(0, 0, 5, 5)); + } + + private static void assertIntersection(Envelope envelope, Envelope other, Envelope intersection) + { + boolean intersects = envelope.intersect(other); + assertTrue(intersects); + assertEquals(envelope, intersection); + } + + private static void assertNoIntersection(Envelope envelope, Envelope other) + { + boolean intersects = envelope.intersect(other); + assertFalse(intersects); + assertTrue(envelope.isEmpty()); + } +} From f68c2413d6a1849238a71d59741f9667e98a1924 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Fri, 20 Apr 2018 09:55:34 -0700 Subject: [PATCH 17/75] Fix a typo in usage of Export flags (#171) WktExportFlags.wktExportPolygon is used instead of WkbExportFlags.wkbExportPolygon. They have same value, so there is no bug yet, but it's better to fix that. --- .../java/com/esri/core/geometry/OperatorExportToWkbLocal.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java b/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java index b87b6a8f..bb3abaad 100644 --- a/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java @@ -170,7 +170,7 @@ else if (wkbBuffer.capacity() < size) if (!bExportZs && !bExportMs) { type = WkbGeometryType.wkbPolygon; - if ((exportFlags & WktExportFlags.wktExportPolygon) == 0) { + if ((exportFlags & WkbExportFlags.wkbExportPolygon) == 0) { wkbBuffer.put(offset, byteOrder); offset += 1; wkbBuffer.putInt(offset, WkbGeometryType.wkbMultiPolygon); From bbfe1d32f9faece46677c651d6965ba1f24e1e46 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Mon, 14 May 2018 14:14:19 -0700 Subject: [PATCH 18/75] Stolstov/issue 172 (#174) --- .../com/esri/core/geometry/ConvexHull.java | 8 ++- .../ogc/OGCConcreteGeometryCollection.java | 61 +++++++++++++++++ .../com/esri/core/geometry/ogc/OGCCurve.java | 3 + .../esri/core/geometry/ogc/OGCGeometry.java | 16 ++--- .../esri/core/geometry/ogc/OGCLineString.java | 3 + .../esri/core/geometry/TestConvexHull.java | 66 +++++++++++++++++++ .../java/com/esri/core/geometry/TestOGC.java | 30 +++++++++ 7 files changed, 177 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ConvexHull.java b/src/main/java/com/esri/core/geometry/ConvexHull.java index ab4b89c9..8e47bb86 100644 --- a/src/main/java/com/esri/core/geometry/ConvexHull.java +++ b/src/main/java/com/esri/core/geometry/ConvexHull.java @@ -52,10 +52,13 @@ private ConvexHull(Point2D[] points, int n) { /** * Adds a geometry to the current bounding geometry using an incremental algorithm for dynamic insertion. - * \param geometry The geometry to add to the bounding geometry. + * @param geometry The geometry to add to the bounding geometry. */ void addGeometry(Geometry geometry) { + if (geometry.isEmpty()) + return; + int type = geometry.getType().value(); if (MultiVertexGeometry.isMultiVertex(type)) @@ -80,6 +83,9 @@ Geometry getBoundingGeometry() { Point point = new Point(); int first = m_tree_hull.getFirst(-1); Polygon hull = new Polygon(m_shape.getVertexDescription()); + if (m_tree_hull.size(-1) == 0) + return hull; + m_shape.queryPoint(m_tree_hull.getElement(first), point); hull.startPath(point); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 51e171e7..ce48b82a 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -27,11 +27,19 @@ import com.esri.core.geometry.Envelope; import com.esri.core.geometry.Geometry; import com.esri.core.geometry.GeometryCursor; +import com.esri.core.geometry.GeometryException; +import com.esri.core.geometry.MultiPath; +import com.esri.core.geometry.MultiPoint; +import com.esri.core.geometry.MultiVertexGeometry; import com.esri.core.geometry.NumberUtils; +import com.esri.core.geometry.OperatorConvexHull; import com.esri.core.geometry.Polygon; +import com.esri.core.geometry.SimpleGeometryCursor; import com.esri.core.geometry.SpatialReference; +import com.esri.core.geometry.VertexDescription; import com.esri.core.geometry.GeoJsonExportFlags; import com.esri.core.geometry.OperatorExportToGeoJson; +import com.esri.core.geometry.Point; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -377,6 +385,59 @@ public int getGeometryID() { } } + + @Override + public OGCGeometry convexHull() { + GeometryCursor cursor = OperatorConvexHull.local().execute( + getEsriGeometryCursor(), false, null); + MultiPoint mp = new MultiPoint(); + Polygon polygon = new Polygon(); + VertexDescription vd = null; + for (Geometry geom = cursor.next(); geom != null; geom = cursor.next()) { + vd = geom.getDescription(); + if (geom.isEmpty()) + continue; + + if (geom.getType() == Geometry.Type.Polygon) { + polygon.add((MultiPath) geom, false); + } + else if (geom.getType() == Geometry.Type.Polyline) { + mp.add((MultiVertexGeometry) geom, 0, -1); + } + else if (geom.getType() == Geometry.Type.Point) { + mp.add((Point) geom); + } + else { + throw new GeometryException("internal error"); + } + } + + Geometry resultGeom = null; + if (!mp.isEmpty()) { + resultGeom = OperatorConvexHull.local().execute(mp, null); + } + + if (!polygon.isEmpty()) { + if (!resultGeom.isEmpty()) { + Geometry[] geoms = { resultGeom, polygon }; + resultGeom = OperatorConvexHull.local().execute( + new SimpleGeometryCursor(geoms), true, null).next(); + } + else { + resultGeom = polygon; + } + } + + if (resultGeom == null) { + Point pt = new Point(); + if (vd != null) + pt.assignVertexDescription(vd); + + return new OGCPoint(pt, getEsriSpatialReference()); + } + + return OGCGeometry.createFromEsriGeometry(resultGeom, getEsriSpatialReference(), false); + } List geometries; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java index 0755dc2e..dd229e5e 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java @@ -41,6 +41,9 @@ public boolean isRing() { @Override public OGCGeometry boundary() { + if (isEmpty()) + return new OGCMultiPoint(this.getEsriSpatialReference()); + if (isClosed()) return new OGCMultiPoint(new MultiPoint(getEsriGeometry() .getDescription()), esriSR);// return empty multipoint; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 30d11f67..058a47b0 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -433,18 +433,16 @@ public OGCGeometry centroid() { OperatorCentroid2D op = (OperatorCentroid2D) OperatorFactoryLocal.getInstance() .getOperator(Operator.Type.Centroid2D); - Point2D centroid = op.execute(getEsriGeometry(), null); - if (centroid == null) { - return OGCGeometry.createFromEsriGeometry(new Point(), esriSR); - } - return OGCGeometry.createFromEsriGeometry(new Point(centroid), esriSR); + Point2D centroid = op.execute(getEsriGeometry(), null); + if (centroid == null) { + return OGCGeometry.createFromEsriGeometry(new Point(), esriSR); + } + return OGCGeometry.createFromEsriGeometry(new Point(centroid), esriSR); } public OGCGeometry convexHull() { - com.esri.core.geometry.OperatorConvexHull op = (OperatorConvexHull) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ConvexHull); - com.esri.core.geometry.GeometryCursor cursor = op.execute( - getEsriGeometryCursor(), true, null); + com.esri.core.geometry.GeometryCursor cursor = OperatorConvexHull.local().execute( + getEsriGeometryCursor(), false, null); return OGCGeometry.createFromEsriCursor(cursor, esriSR); } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java index 464b9a7c..8d086c3b 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java @@ -82,6 +82,9 @@ public OGCPoint pointN(int n) { @Override public boolean isClosed() { + if (isEmpty()) + return false; + return multiPath.isClosedPathInXYPlane(0); } diff --git a/src/test/java/com/esri/core/geometry/TestConvexHull.java b/src/test/java/com/esri/core/geometry/TestConvexHull.java index b2e2d59e..b29d3aaf 100644 --- a/src/test/java/com/esri/core/geometry/TestConvexHull.java +++ b/src/test/java/com/esri/core/geometry/TestConvexHull.java @@ -27,6 +27,8 @@ import junit.framework.TestCase; import org.junit.Test; +import com.esri.core.geometry.ogc.OGCGeometry; + public class TestConvexHull extends TestCase { @Override protected void setUp() throws Exception { @@ -992,5 +994,69 @@ public void testHullTickTock() { assertTrue(p5.x == -5.0 && p5.y == 1.25); assertTrue(p6.x == 0.0 && p6.y == 10.0); } + + @Test + public void testHullIssueGithub172() { + { + //empty + OGCGeometry geom = OGCGeometry.fromText("MULTIPOINT EMPTY"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POINT EMPTY") == 0); + } + { + //Point + OGCGeometry geom = OGCGeometry.fromText("POINT (1 2)"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POINT (1 2)") == 0); + } + { + //line + OGCGeometry geom = OGCGeometry.fromText("MULTIPOINT (1 1, 2 2)"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("LINESTRING (1 1, 2 2)") == 0); + } + { + //empty + OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION EMPTY"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POINT EMPTY") == 0); + } + + { + //empty + OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 2))"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POINT (1 2)") == 0); + } + + { + //empty + OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION(POLYGON EMPTY, POINT(1 1), LINESTRING EMPTY, MULTIPOLYGON EMPTY, MULTILINESTRING EMPTY)"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POINT (1 1)") == 0); + } + + { + //empty + OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION(POLYGON EMPTY, LINESTRING (1 1, 2 2), POINT(3 3), LINESTRING EMPTY, MULTIPOLYGON EMPTY, MULTILINESTRING EMPTY)"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("LINESTRING (1 1, 3 3)") == 0); + } + + { + //empty + OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION(POLYGON EMPTY, LINESTRING (1 1, 2 2), POINT(3 3), LINESTRING EMPTY, POLYGON((-10 -10, 10 -10, 10 10, -10 10, -10 -10), (-5 -5, -5 5, 5 5, 5 -5, -5 -5)))"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POLYGON ((-10 -10, 10 -10, 10 10, -10 10, -10 -10))") == 0); + } + } } diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index ca2bcf6d..31263705 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -926,4 +926,34 @@ public void testPolylineSimplifyIssueGithub52() throws Exception { } } + @Test + public void testEmptyBoundary() throws Exception { + { + OGCGeometry g = OGCGeometry.fromText("POINT EMPTY"); + OGCGeometry b = g.boundary(); + assertTrue(b.asText().compareTo("MULTIPOINT EMPTY") == 0); + } + { + OGCGeometry g = OGCGeometry.fromText("MULTIPOINT EMPTY"); + OGCGeometry b = g.boundary(); + assertTrue(b.asText().compareTo("MULTIPOINT EMPTY") == 0); + } + { + OGCGeometry g = OGCGeometry.fromText("LINESTRING EMPTY"); + OGCGeometry b = g.boundary(); + assertTrue(b.asText().compareTo("MULTIPOINT EMPTY") == 0); + } + { + OGCGeometry g = OGCGeometry.fromText("POLYGON EMPTY"); + OGCGeometry b = g.boundary(); + assertTrue(b.asText().compareTo("MULTILINESTRING EMPTY") == 0); + } + { + OGCGeometry g = OGCGeometry.fromText("MULTIPOLYGON EMPTY"); + OGCGeometry b = g.boundary(); + assertTrue(b.asText().compareTo("MULTILINESTRING EMPTY") == 0); + } + } + + } From e3e0d6ee3d3c5837e29c2acdb35ede34c0857353 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sun, 27 May 2018 22:50:07 -0700 Subject: [PATCH 19/75] Adding collection handling methods --- .../java/com/esri/core/geometry/Geometry.java | 2 +- .../com/esri/core/geometry/OGCStructure.java | 5 + .../ogc/OGCConcreteGeometryCollection.java | 308 +++++++++++++++++- .../esri/core/geometry/ogc/OGCGeometry.java | 17 +- .../esri/core/geometry/ogc/OGCLineString.java | 5 +- .../core/geometry/ogc/OGCMultiLineString.java | 21 +- .../esri/core/geometry/ogc/OGCMultiPoint.java | 4 +- .../core/geometry/ogc/OGCMultiPolygon.java | 10 +- .../com/esri/core/geometry/ogc/OGCPoint.java | 4 +- .../esri/core/geometry/ogc/OGCPolygon.java | 4 +- .../java/com/esri/core/geometry/TestOGC.java | 31 ++ 11 files changed, 390 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/Geometry.java b/src/main/java/com/esri/core/geometry/Geometry.java index 8a71a236..d108d328 100644 --- a/src/main/java/com/esri/core/geometry/Geometry.java +++ b/src/main/java/com/esri/core/geometry/Geometry.java @@ -456,7 +456,7 @@ public static int getDimensionFromType(int type) { * @param type * The integer value from geometry enumeration. You can use the * method {@link Type#value()} to get at the integer value. - * @return TRUE if the geometry is a point. + * @return TRUE if the geometry is a point (a Point or a Multipoint). */ public static boolean isPoint(int type) { return (type & 0x20) != 0; diff --git a/src/main/java/com/esri/core/geometry/OGCStructure.java b/src/main/java/com/esri/core/geometry/OGCStructure.java index 9f0875b9..1a9891d9 100644 --- a/src/main/java/com/esri/core/geometry/OGCStructure.java +++ b/src/main/java/com/esri/core/geometry/OGCStructure.java @@ -23,8 +23,13 @@ */ package com.esri.core.geometry; +import java.util.ArrayList; import java.util.List; +import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; +import com.esri.core.geometry.ogc.OGCGeometry; +import com.esri.core.geometry.ogc.OGCGeometryCollection; + public class OGCStructure { public int m_type; public List m_structures; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index ce48b82a..aa4805f3 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -32,13 +32,17 @@ import com.esri.core.geometry.MultiPoint; import com.esri.core.geometry.MultiVertexGeometry; import com.esri.core.geometry.NumberUtils; +import com.esri.core.geometry.OGCStructureInternal; import com.esri.core.geometry.OperatorConvexHull; +import com.esri.core.geometry.OperatorDifference; import com.esri.core.geometry.Polygon; +import com.esri.core.geometry.Polyline; import com.esri.core.geometry.SimpleGeometryCursor; import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.VertexDescription; import com.esri.core.geometry.GeoJsonExportFlags; import com.esri.core.geometry.OperatorExportToGeoJson; +import com.esri.core.geometry.OperatorUnion; import com.esri.core.geometry.Point; import java.nio.ByteBuffer; @@ -49,11 +53,26 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION; public class OGCConcreteGeometryCollection extends OGCGeometryCollection { + static public String TYPE = "GeometryCollection"; + + List geometries; + public OGCConcreteGeometryCollection(List geoms, SpatialReference sr) { geometries = geoms; esriSR = sr; } + + public OGCConcreteGeometryCollection(GeometryCursor geoms, + SpatialReference sr) { + List ogcGeoms = new ArrayList(10); + for (Geometry g = geoms.next(); g != null; g = geoms.next()) { + ogcGeoms.add(createFromEsriGeometry(g, sr)); + } + + geometries = ogcGeoms; + esriSR = sr; + } public OGCConcreteGeometryCollection(OGCGeometry geom, SpatialReference sr) { geometries = new ArrayList(1); @@ -112,7 +131,7 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "GeometryCollection"; + return TYPE; } @Override @@ -275,6 +294,7 @@ public boolean isSimple() { for (int i = 0, n = numGeometries(); i < n; i++) if (!geometryN(i).isSimple()) return false; + return true; } @@ -439,8 +459,6 @@ else if (geom.getType() == Geometry.Type.Point) { return OGCGeometry.createFromEsriGeometry(resultGeom, getEsriSpatialReference(), false); } - List geometries; - @Override public void setSpatialReference(SpatialReference esriSR_) { esriSR = esriSR_; @@ -501,4 +519,288 @@ public int hashCode() { return hash; } + + //Relational operations + @Override + public boolean disjoint(OGCGeometry another) { + if (isEmpty() || another.isEmpty()) + return true; + + if (this == another) + return false; + + //TODO: a simple envelope test + + OGCConcreteGeometryCollection flattened1 = flatten(); + if (flattened1.isEmpty()) + return true; + OGCConcreteGeometryCollection otherCol = new OGCConcreteGeometryCollection(another, esriSR); + OGCConcreteGeometryCollection flattened2 = otherCol.flatten(); + if (flattened2.isEmpty()) + return true; + + for (int i = 0, n1 = flattened1.numGeometries(); i < n1; ++i) { + OGCGeometry g1 = flattened1.geometryN(i); + for (int j = 0, n2 = flattened2.numGeometries(); j < n2; ++j) { + OGCGeometry g2 = flattened2.geometryN(i); + if (!g1.disjoint(g2)) + return false; + } + } + + return true; + } + + @Override + public boolean contains(OGCGeometry another) { + if (isEmpty() || another.isEmpty()) + return true; + if (this == another) + return false; + + //TODO: a simple envelope test + + OGCConcreteGeometryCollection flattened1 = flatten(); + if (flattened1.isEmpty()) + return true; + OGCConcreteGeometryCollection otherCol = new OGCConcreteGeometryCollection(another, esriSR); + OGCConcreteGeometryCollection flattened2 = otherCol.flatten(); + if (flattened2.isEmpty()) + return true; + + for (int i = 0, n2 = flattened2.numGeometries(); i < n2; ++i) { + OGCGeometry g2 = flattened2.geometryN(i); + boolean good = false; + for (int j = 0, n1 = flattened1.numGeometries(); j < n1; ++j) { + OGCGeometry g1 = flattened1.geometryN(i); + if (g1.contains(g2)) { + good = true; + break; + } + } + + if (!good) + return false; + } + + //each geometry of another is contained in a geometry from this. + return true; + } + + /** + * Checks if collection is flattened. + * @return True for the flattened collection. A flattened collection contains up to three non-empty geometries: + * an OGCMultiPoint, an OGCMultiPolygon, and an OGCMultiLineString. + */ + public boolean isFlattened() { + int n = numGeometries(); + if (n > 3) + return false; + + for (int i = 0; i < n; ++i) { + OGCGeometry g = geometryN(i); + if (g.isEmpty()) + return false;//no empty allowed + + String t = g.geometryType(); + if (t != OGCMultiPoint.TYPE && t != OGCMultiPolygon.TYPE && t != OGCMultiLineString.TYPE) + return false; + } + + return true; + } + + /** + * Flattens Geometry Collection. + * The result collection contains up to three geometries: + * an OGCMultiPoint, an OGCMultiPolygon, and an OGCMultilineString. + * @return A flattened Geometry Collection, or self if already flattened. + */ + public OGCConcreteGeometryCollection flatten() { + if (isFlattened()) { + return this; + } + + OGCMultiPoint multiPoint = null; + ArrayList polygons = null; + OGCMultiLineString polyline = null; + GeometryCursor gc = getEsriGeometryCursor(); + for (Geometry g = gc.next(); g != null; g = gc.next()) { + if (g.isEmpty()) + continue; + + Geometry.Type t = g.getType(); + + if (t == Geometry.Type.Point) { + if (multiPoint == null) { + multiPoint = new OGCMultiPoint(esriSR); + } + + ((MultiPoint)multiPoint.getEsriGeometry()).add((Point)g); + continue; + } + + if (t == Geometry.Type.MultiPoint) { + if (multiPoint == null) + multiPoint = new OGCMultiPoint(esriSR); + + ((MultiPoint)multiPoint.getEsriGeometry()).add((MultiPoint)g, 0, -1); + continue; + } + + if (t == Geometry.Type.Polyline) { + if (polyline == null) + polyline = new OGCMultiLineString(esriSR); + + ((MultiPath)polyline.getEsriGeometry()).add((Polyline)g, false); + continue; + } + + if (t == Geometry.Type.Polygon) { + if (polygons == null) + polygons = new ArrayList(); + + polygons.add(g); + continue; + } + + throw new GeometryException("internal error");//what else? + } + + List list = new ArrayList(); + + if (multiPoint != null) + list.add(multiPoint); + + if (polyline != null) + list.add(polyline); + + if (polygons != null) { + GeometryCursor unionedPolygons = OperatorUnion.local().execute(new SimpleGeometryCursor(polygons), esriSR, null); + Geometry g = unionedPolygons.next(); + if (!g.isEmpty()) { + list.add(new OGCMultiPolygon((Polygon)g, esriSR)); + } + + } + + return new OGCConcreteGeometryCollection(list, esriSR); + } + + /** + * Fixes topological overlaps in the GeometryCollecion. + * This is equivalent to union of the geometry collection elements. + * + * @return A geometry collection that is flattened and has no overlapping elements. + */ + public OGCConcreteGeometryCollection flattenAndRemoveOverlaps() { + ArrayList geoms = new ArrayList(); + + //flatten and crack/cluster + GeometryCursor cursor = OGCStructureInternal.prepare_for_ops_(flatten().getEsriGeometryCursor(), esriSR); + for (Geometry g = cursor.next(); g != null; g = cursor.next()) { + geoms.add(g); + } + + //make sure geometries don't overlap + return removeOverlapsHelper_(geoms); + } + + private OGCConcreteGeometryCollection removeOverlapsHelper_(List geoms) { + ArrayList result = new ArrayList(); + for (int i = 0; i < geoms.size() - 1; ++i) { + Geometry current = geoms.get(i); + if (current.isEmpty()) + continue; + + for (int j = 1; j < geoms.size(); ++j) { + Geometry subG = geoms.get(j); + current = OperatorDifference.local().execute(current, subG, esriSR, null); + if (current.isEmpty()) + break; + } + + if (current.isEmpty()) + continue; + + result.add(current); + } + + return new OGCConcreteGeometryCollection(new SimpleGeometryCursor(geoms), esriSR); + } + + private static class FlatteningCollectionCursor extends GeometryCursor { + private List m_collections; + private GeometryCursor m_current; + private int m_index; + FlatteningCollectionCursor(List collections) { + m_collections = collections; + m_index = -1; + m_current = null; + } + + @Override + public Geometry next() { + while (m_collections != null) { + if (m_current != null) { + Geometry g = m_current.next(); + if (g == null) { + m_current = null; + continue; + } + + return g; + } + else { + m_index++; + if (m_index < m_collections.size()) { + m_current = m_collections.get(m_index).flatten().getEsriGeometryCursor(); + continue; + } + else { + m_collections = null; + m_index = -1; + } + } + } + + return null; + } + + @Override + public int getGeometryID() { + return m_index; + } + + }; + + //Collectively processes group of geometry collections (intersects all segments and clusters points). + //Flattens collections, removes overlaps. + //Once done, the result collections would work well for topological and relational operations. + private List prepare_for_ops_(List geoms) { + assert(geoms != null && !geoms.isEmpty()); + GeometryCursor prepared = OGCStructureInternal.prepare_for_ops_(new FlatteningCollectionCursor(geoms), esriSR); + + ArrayList result = new ArrayList(); + int prevCollectionIndex = -1; + ArrayList list = null; + for (Geometry g = prepared.next(); g != null; g = prepared.next()) { + int c = prepared.getGeometryID(); + if (c != prevCollectionIndex) { + if (list != null) { + result.add(removeOverlapsHelper_(list)); + } + + list = new ArrayList(); + } + + list.add(g); + } + + if (list != null) { + result.add(removeOverlapsHelper_(list)); + } + + return result; + } } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 058a47b0..a34d7af1 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -295,10 +295,7 @@ public boolean crosses(OGCGeometry another) { } public boolean within(OGCGeometry another) { - com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); - com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); - return com.esri.core.geometry.GeometryEngine.within(geom1, geom2, - getEsriSpatialReference()); + return another.contains(this); } public boolean contains(OGCGeometry another) { @@ -456,6 +453,18 @@ public OGCGeometry intersection(OGCGeometry another) { } public OGCGeometry union(OGCGeometry another) { + String thisType = geometryType(); + String anotherType = another.geometryType(); + if (thisType != anotherType || thisType == OGCConcreteGeometryCollection.TYPE) { + //heterogeneous union. + //We make a geometry collection, then process to union parts and remove overlaps. + ArrayList geoms = new ArrayList(); + geoms.add(this); + geoms.add(another); + OGCConcreteGeometryCollection geomCol = new OGCConcreteGeometryCollection(geoms, esriSR); + return geomCol.flattenAndRemoveOverlaps(); + } + OperatorUnion op = (OperatorUnion) OperatorFactoryLocal.getInstance() .getOperator(Operator.Type.Union); GeometryCursorAppend ap = new GeometryCursorAppend( diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java index 8d086c3b..4df18c15 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java @@ -40,7 +40,8 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_LINE_STRING; public class OGCLineString extends OGCCurve { - + static public String TYPE = "LineString"; + /** * The number of Points in this LineString. */ @@ -120,7 +121,7 @@ public OGCPoint endPoint() { @Override public String geometryType() { - return "LineString"; + return TYPE; } @Override diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java index 8fa020c8..91a6580e 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java @@ -42,22 +42,31 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_LINE_STRING; public class OGCMultiLineString extends OGCMultiCurve { + static public String TYPE = "MultiLineString"; + public OGCMultiLineString(Polyline poly, SpatialReference sr) { polyline = poly; esriSR = sr; } + public OGCMultiLineString(SpatialReference sr) { + polyline = new Polyline(); + esriSR = sr; + } + @Override public String asText() { return GeometryEngine.geometryToWkt(getEsriGeometry(), WktExportFlags.wktExportMultiLineString); } + @Override - public String asGeoJson() { - OperatorExportToGeoJson op = (OperatorExportToGeoJson) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ExportToGeoJson); - return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, null, getEsriGeometry()); - } + public String asGeoJson() { + OperatorExportToGeoJson op = (OperatorExportToGeoJson) OperatorFactoryLocal.getInstance() + .getOperator(Operator.Type.ExportToGeoJson); + return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, null, getEsriGeometry()); + } + @Override public ByteBuffer asBinary() { OperatorExportToWkb op = (OperatorExportToWkb) OperatorFactoryLocal @@ -74,7 +83,7 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "MultiLineString"; + return TYPE; } @Override diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java index b25a948a..4f300ea3 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java @@ -40,6 +40,8 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_POINT; public class OGCMultiPoint extends OGCGeometryCollection { + public static String TYPE = "MultiPoint"; + public int numGeometries() { return multiPoint.getPointCount(); } @@ -65,7 +67,7 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "MultiPoint"; + return TYPE; } @Override diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java index bed0e114..520cc3f7 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java @@ -42,12 +42,18 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_POLYGON; public class OGCMultiPolygon extends OGCMultiSurface { - + static public String TYPE = "MultiPolygon"; + public OGCMultiPolygon(Polygon src, SpatialReference sr) { polygon = src; esriSR = sr; } + public OGCMultiPolygon(SpatialReference sr) { + polygon = new Polygon(); + esriSR = sr; + } + @Override public String asText() { return GeometryEngine.geometryToWkt(getEsriGeometry(), @@ -89,7 +95,7 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "MultiPolygon"; + return TYPE; } @Override diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java index 9db01268..608e809f 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java @@ -39,6 +39,8 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_POINT; public final class OGCPoint extends OGCGeometry { + public static String TYPE = "Point"; + public OGCPoint(Point pt, SpatialReference sr) { point = pt; esriSR = sr; @@ -76,7 +78,7 @@ public double M() { @Override public String geometryType() { - return "Point"; + return TYPE; } @Override diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java index 6f7a74f2..2bc65935 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java @@ -40,6 +40,8 @@ import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_POLYGON; public class OGCPolygon extends OGCSurface { + public static String TYPE = "Polygon"; + public OGCPolygon(Polygon src, int exteriorRing, SpatialReference sr) { polygon = new Polygon(); for (int i = exteriorRing, n = src.getPathCount(); i < n; i++) { @@ -109,7 +111,7 @@ public OGCMultiCurve boundary() { @Override public String geometryType() { - return "Polygon"; + return TYPE; } @Override diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index 31263705..fd7151ec 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -955,5 +955,36 @@ public void testEmptyBoundary() throws Exception { } } + @Test + public void testUnionPointWithEmptyLineString() { + assertUnion("POINT (1 2)", "LINESTRING EMPTY", "GEOMETRYCOLLECTION (POINT (1 2))"); + } + + @Test + public void testUnionPointWithLinestring() { + assertUnion("POINT (1 2)", "LINESTRING (3 4, 5 6)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); + } + + @Test + public void testUnionLinestringWithEmptyPolygon() { + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "GEOMETRYCOLLECTION (LINESTRING ((1 2, 3 4)))"); + } + + @Test + public void testUnionLinestringWithPolygon() { + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((0 0, 1 1, 0 1, 0 0))", + "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((0 0, 1 1, 0 1, 0 0)))"); + } + @Test + public void testUnionGeometryCollectionWithGeometryCollection() { + assertUnion("GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((0 0, 1 1, 0 1, 0 0)))", + "GEOMETRYCOLLECTION (POINT (1 2), POINT (2 3), POINT (0.5 0.5), POINT (3 5), LINESTRING (3 4, 5 6), POLYGON ((0 0, 1 0, 1 1, 0 0)))", + "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((0 0, 1 1, 0 1, 0 0)))"); + } + + private void assertUnion(String leftWkt, String rightWkt, String expectedWkt) { + OGCGeometry union = OGCGeometry.fromText(leftWkt).union(OGCGeometry.fromText(rightWkt)); + assertEquals(expectedWkt, union.asText()); + } } From 91a0bdaa7eef5b87f1c9a7215d6484ced6d517b1 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sun, 27 May 2018 23:19:44 -0700 Subject: [PATCH 20/75] Fixed distance --- .../ogc/OGCConcreteGeometryCollection.java | 21 ++++++++++++-- .../esri/core/geometry/ogc/OGCGeometry.java | 4 +++ .../java/com/esri/core/geometry/TestOGC.java | 28 +++++++++++++++++-- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index aa4805f3..2e931696 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -520,6 +520,21 @@ public int hashCode() { return hash; } + @Override + public double distance(OGCGeometry another) { + double minD = 0; + for (int i = 0, n = numGeometries(); i < n; ++i) { + double d = geometryN(i).distance(another); + if (d < minD) { + minD = d; + if (minD == 0) { + break; + } + } + } + + return minD; + } //Relational operations @Override public boolean disjoint(OGCGeometry another) { @@ -708,12 +723,12 @@ public OGCConcreteGeometryCollection flattenAndRemoveOverlaps() { private OGCConcreteGeometryCollection removeOverlapsHelper_(List geoms) { ArrayList result = new ArrayList(); - for (int i = 0; i < geoms.size() - 1; ++i) { + for (int i = 0; i < geoms.size(); ++i) { Geometry current = geoms.get(i); if (current.isEmpty()) continue; - for (int j = 1; j < geoms.size(); ++j) { + for (int j = i + 1; j < geoms.size(); ++j) { Geometry subG = geoms.get(j); current = OperatorDifference.local().execute(current, subG, esriSR, null); if (current.isEmpty()) @@ -726,7 +741,7 @@ private OGCConcreteGeometryCollection removeOverlapsHelper_(List geoms result.add(current); } - return new OGCConcreteGeometryCollection(new SimpleGeometryCursor(geoms), esriSR); + return new OGCConcreteGeometryCollection(new SimpleGeometryCursor(result), esriSR); } private static class FlatteningCollectionCursor extends GeometryCursor { diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index a34d7af1..158d79ef 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -325,6 +325,10 @@ public boolean relate(OGCGeometry another, String matrix) { // analysis public double distance(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return another.distance(this); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.distance(geom1, geom2, diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index fd7151ec..c0a744cc 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -967,7 +967,7 @@ public void testUnionPointWithLinestring() { @Test public void testUnionLinestringWithEmptyPolygon() { - assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "GEOMETRYCOLLECTION (LINESTRING ((1 2, 3 4)))"); + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))"); } @Test @@ -980,11 +980,35 @@ public void testUnionLinestringWithPolygon() { public void testUnionGeometryCollectionWithGeometryCollection() { assertUnion("GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((0 0, 1 1, 0 1, 0 0)))", "GEOMETRYCOLLECTION (POINT (1 2), POINT (2 3), POINT (0.5 0.5), POINT (3 5), LINESTRING (3 4, 5 6), POLYGON ((0 0, 1 0, 1 1, 0 0)))", - "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((0 0, 1 1, 0 1, 0 0)))"); + "GEOMETRYCOLLECTION (POINT (3 5), LINESTRING (1 2, 2 3, 3 4, 5 6), POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)))"); } private void assertUnion(String leftWkt, String rightWkt, String expectedWkt) { OGCGeometry union = OGCGeometry.fromText(leftWkt).union(OGCGeometry.fromText(rightWkt)); assertEquals(expectedWkt, union.asText()); } + + @Test + public void testDisjointOnGeometryCollection() { + OGCGeometry ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); + assertFalse(ogcGeometry.disjoint(OGCGeometry.fromText("POINT (1 1)"))); + } + + @Test + public void testContainsOnGeometryCollection() { + OGCGeometry ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); + assertTrue(ogcGeometry.contains(OGCGeometry.fromText("POINT (1 1)"))); + } + + @Test + public void testIntersectsOnGeometryCollection() { + OGCGeometry ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); + assertTrue(ogcGeometry.intersects(OGCGeometry.fromText("POINT (1 1)"))); + } + + @Test + public void testDistanceOnGeometryCollection() { + OGCGeometry ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); + assertTrue(ogcGeometry.distance(OGCGeometry.fromText("POINT (1 1)")) == 0); + } } From 13c1fa322441f8a24d89899a5a6d54454a2b467a Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sun, 27 May 2018 23:33:48 -0700 Subject: [PATCH 21/75] added missing file --- .../core/geometry/OGCStructureInternal.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/com/esri/core/geometry/OGCStructureInternal.java diff --git a/src/main/java/com/esri/core/geometry/OGCStructureInternal.java b/src/main/java/com/esri/core/geometry/OGCStructureInternal.java new file mode 100644 index 00000000..dcf4aeef --- /dev/null +++ b/src/main/java/com/esri/core/geometry/OGCStructureInternal.java @@ -0,0 +1,89 @@ +/* + Copyright 1995-2018 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + For additional information, contact: + Environmental Systems Research Institute, Inc. + Attn: Contracts Dept + 380 New York Street + Redlands, California, USA 92373 + + email: contracts@esri.com + */ +package com.esri.core.geometry; + +import java.util.ArrayList; +import java.util.List; + +import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; +import com.esri.core.geometry.ogc.OGCGeometry; +import com.esri.core.geometry.ogc.OGCGeometryCollection; + +//An internal helper class. Do not use. +public class OGCStructureInternal { + private static class EditShapeCursor extends GeometryCursor { + EditShape m_shape; + int m_geom; + int m_index; + + EditShapeCursor(EditShape shape, int index) { + m_shape = shape; + m_geom = -1; + m_index = index; + } + @Override + public Geometry next() { + if (m_shape != null) { + if (m_geom == -1) + m_geom = m_shape.getFirstGeometry(); + else + m_geom = m_shape.getNextGeometry(m_geom); + + if (m_geom == -1) { + m_shape = null; + } + else { + return m_shape.getGeometry(m_geom); + } + + } + + return null; + } + + @Override + public int getGeometryID() { + return m_shape.getGeometryUserIndex(m_geom, m_index); + } + + }; + + public static GeometryCursor prepare_for_ops_(GeometryCursor geoms, SpatialReference sr) { + assert(geoms != null); + EditShape editShape = new EditShape(); + int geomIndex = editShape.createGeometryUserIndex(); + for (Geometry g = geoms.next(); g != null; g = geoms.next()) { + int egeom = editShape.addGeometry(g); + editShape.setGeometryUserIndex(egeom, geomIndex, geoms.getGeometryID()); + } + + Envelope2D env = editShape.getEnvelope2D(); + double tolerance = InternalUtils.calculateToleranceFromGeometry(sr, + env, true); + + CrackAndCluster.execute(editShape, tolerance, null, true); + return OperatorSimplifyOGC.local().execute(new EditShapeCursor(editShape, geomIndex), sr, false, null); + } +} + From 559fe2f61c9c81ee741985d3a034f646bf8fedc8 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 29 May 2018 18:38:33 -0700 Subject: [PATCH 22/75] Fixed a couple of review comments --- .../ogc/OGCConcreteGeometryCollection.java | 12 ++++++++++-- .../com/esri/core/geometry/ogc/OGCGeometry.java | 8 ++++++++ src/test/java/com/esri/core/geometry/TestOGC.java | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 2e931696..35807cd2 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -522,10 +522,10 @@ public int hashCode() { @Override public double distance(OGCGeometry another) { - double minD = 0; + double minD = Double.NaN; for (int i = 0, n = numGeometries(); i < n; ++i) { double d = geometryN(i).distance(another); - if (d < minD) { + if (d < minD || Double.isNaN(minD)) { minD = d; if (minD == 0) { break; @@ -612,6 +612,7 @@ public boolean isFlattened() { if (n > 3) return false; + int dimension = -1; for (int i = 0; i < n; ++i) { OGCGeometry g = geometryN(i); if (g.isEmpty()) @@ -620,6 +621,13 @@ public boolean isFlattened() { String t = g.geometryType(); if (t != OGCMultiPoint.TYPE && t != OGCMultiPolygon.TYPE && t != OGCMultiLineString.TYPE) return false; + + //check strict order of geometry dimensions + int d = g.dimension(); + if (d <= dimension) + return false; + + dimension = d; } return true; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 158d79ef..72093351 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -270,6 +270,10 @@ public boolean equals(OGCGeometry another) { } public boolean disjoint(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return another.disjoint(this); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.disjoint(geom1, geom2, @@ -299,6 +303,10 @@ public boolean within(OGCGeometry another) { } public boolean contains(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return another.contains(this); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.contains(geom1, geom2, diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index c0a744cc..a8afb7da 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -1004,11 +1004,25 @@ public void testContainsOnGeometryCollection() { public void testIntersectsOnGeometryCollection() { OGCGeometry ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); assertTrue(ogcGeometry.intersects(OGCGeometry.fromText("POINT (1 1)"))); + ogcGeometry = OGCGeometry.fromText("POINT (1 1)"); + assertTrue(ogcGeometry.intersects(OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"))); } @Test public void testDistanceOnGeometryCollection() { OGCGeometry ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); assertTrue(ogcGeometry.distance(OGCGeometry.fromText("POINT (1 1)")) == 0); + + //distance to empty is NAN + ogcGeometry = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 1))"); + assertTrue(Double.isNaN(ogcGeometry.distance(OGCGeometry.fromText("POINT EMPTY")))); + } + + @Test + public void testFlattened() { + OGCConcreteGeometryCollection ogcGeometry = (OGCConcreteGeometryCollection)OGCGeometry.fromText("GEOMETRYCOLLECTION (MULTILINESTRING ((1 2, 3 4)), MULTIPOLYGON (((1 2, 3 4, 5 6, 1 2))), MULTIPOINT (1 1))"); + assertFalse(ogcGeometry.isFlattened()); + ogcGeometry = (OGCConcreteGeometryCollection)OGCGeometry.fromText("GEOMETRYCOLLECTION (MULTIPOINT (1 1), MULTILINESTRING ((1 2, 3 4)), MULTIPOLYGON (((1 2, 3 4, 5 6, 1 2))))"); + assertTrue(ogcGeometry.isFlattened()); } } From 0618e303c9e3958c3dac68eb38706d6b664a2f9a Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 29 May 2018 19:36:58 -0700 Subject: [PATCH 23/75] a few fixes, added intersection and difference for collections --- .../com/esri/core/geometry/OGCStructure.java | 5 - .../core/geometry/OGCStructureInternal.java | 7 -- .../ogc/OGCConcreteGeometryCollection.java | 101 ++++++++++++++++-- .../esri/core/geometry/ogc/OGCGeometry.java | 13 ++- .../java/com/esri/core/geometry/TestOGC.java | 12 +++ 5 files changed, 119 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/OGCStructure.java b/src/main/java/com/esri/core/geometry/OGCStructure.java index 1a9891d9..9f0875b9 100644 --- a/src/main/java/com/esri/core/geometry/OGCStructure.java +++ b/src/main/java/com/esri/core/geometry/OGCStructure.java @@ -23,13 +23,8 @@ */ package com.esri.core.geometry; -import java.util.ArrayList; import java.util.List; -import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; -import com.esri.core.geometry.ogc.OGCGeometry; -import com.esri.core.geometry.ogc.OGCGeometryCollection; - public class OGCStructure { public int m_type; public List m_structures; diff --git a/src/main/java/com/esri/core/geometry/OGCStructureInternal.java b/src/main/java/com/esri/core/geometry/OGCStructureInternal.java index dcf4aeef..59cf1e61 100644 --- a/src/main/java/com/esri/core/geometry/OGCStructureInternal.java +++ b/src/main/java/com/esri/core/geometry/OGCStructureInternal.java @@ -23,13 +23,6 @@ */ package com.esri.core.geometry; -import java.util.ArrayList; -import java.util.List; - -import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; -import com.esri.core.geometry.ogc.OGCGeometry; -import com.esri.core.geometry.ogc.OGCGeometryCollection; - //An internal helper class. Do not use. public class OGCStructureInternal { private static class EditShapeCursor extends GeometryCursor { diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 35807cd2..c7737ab0 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -80,6 +80,11 @@ public OGCConcreteGeometryCollection(OGCGeometry geom, SpatialReference sr) { esriSR = sr; } + public OGCConcreteGeometryCollection(SpatialReference sr) { + geometries = new ArrayList(); + esriSR = sr; + } + @Override public int dimension() { int maxD = 0; @@ -356,7 +361,7 @@ protected boolean isConcreteGeometryCollection() { return true; } - static class GeometryCursorOGC extends GeometryCursor { + private static class GeometryCursorOGC extends GeometryCursor { private int m_index; private int m_ind; private List m_geoms; @@ -522,6 +527,9 @@ public int hashCode() { @Override public double distance(OGCGeometry another) { + if (this == another) + return isEmpty() ? Double.NaN : 0; + double minD = Double.NaN; for (int i = 0, n = numGeometries(); i < n; ++i) { double d = geometryN(i).distance(another); @@ -535,6 +543,8 @@ public double distance(OGCGeometry another) { return minD; } + + // //Relational operations @Override public boolean disjoint(OGCGeometry another) { @@ -569,7 +579,8 @@ public boolean disjoint(OGCGeometry another) { @Override public boolean contains(OGCGeometry another) { if (isEmpty() || another.isEmpty()) - return true; + return false; + if (this == another) return false; @@ -601,7 +612,79 @@ public boolean contains(OGCGeometry another) { //each geometry of another is contained in a geometry from this. return true; } - + //Topological + @Override + public OGCGeometry difference(OGCGeometry another) { + List list = wrapGeomsIntoList_(this, another); + list = prepare_for_ops_(list); + if (list.size() != 2) // this should not happen + throw new GeometryException("internal error"); + + List result = new ArrayList(); + OGCConcreteGeometryCollection coll1 = list.get(0); + OGCConcreteGeometryCollection coll2 = list.get(1); + for (int i = 0, n = coll1.numGeometries(); i < n; ++i) { + OGCGeometry cur = coll1.geometryN(i); + for (int j = 0, n2 = coll2.numGeometries(); j < n2; ++j) { + OGCGeometry geom2 = coll2.geometryN(j); + if (cur.dimension() > geom2.dimension()) + continue; //subtracting lower dimension has no effect. + + cur = cur.difference(geom2); + if (cur.isEmpty()) + break; + } + + if (cur.isEmpty()) + continue; + + result.add(cur); + } + + return new OGCConcreteGeometryCollection(result, esriSR); + } + + @Override + public OGCGeometry intersection(OGCGeometry another) { + List list = wrapGeomsIntoList_(this, another); + list = prepare_for_ops_(list); + if (list.size() != 2) // this should not happen + throw new GeometryException("internal error"); + + List result = new ArrayList(); + OGCConcreteGeometryCollection coll1 = list.get(0); + OGCConcreteGeometryCollection coll2 = list.get(1); + for (int i = 0, n = coll1.numGeometries(); i < n; ++i) { + OGCGeometry cur = coll1.geometryN(i); + for (int j = 0, n2 = coll2.numGeometries(); j < n2; ++j) { + OGCGeometry geom2 = coll2.geometryN(j); + + OGCGeometry partialIntersection = cur.intersection(geom2); + if (partialIntersection.isEmpty()) + continue; + + result.add(partialIntersection); + } + } + + return (new OGCConcreteGeometryCollection(result, esriSR)).flattenAndRemoveOverlaps(); + } + + //make a list of collections out of two geometries + private static List wrapGeomsIntoList_(OGCGeometry g1, OGCGeometry g2) { + List list = new ArrayList(); + if (g1.geometryType() != OGCConcreteGeometryCollection.TYPE) { + g1 = new OGCConcreteGeometryCollection(g1, g1.getEsriSpatialReference()); + } + if (g2.geometryType() != OGCConcreteGeometryCollection.TYPE) { + g2 = new OGCConcreteGeometryCollection(g2, g2.getEsriSpatialReference()); + } + + list.add((OGCConcreteGeometryCollection)g1); + list.add((OGCConcreteGeometryCollection)g2); + + return list; + } /** * Checks if collection is flattened. * @return True for the flattened collection. A flattened collection contains up to three non-empty geometries: @@ -636,7 +719,7 @@ public boolean isFlattened() { /** * Flattens Geometry Collection. * The result collection contains up to three geometries: - * an OGCMultiPoint, an OGCMultiPolygon, and an OGCMultilineString. + * an OGCMultiPoint, an OGCMultilineString, and an OGCMultiPolygon (in that order). * @return A flattened Geometry Collection, or self if already flattened. */ public OGCConcreteGeometryCollection flatten() { @@ -804,17 +887,23 @@ private List prepare_for_ops_(List result = new ArrayList(); + List result = new ArrayList(); int prevCollectionIndex = -1; - ArrayList list = null; + List list = null; for (Geometry g = prepared.next(); g != null; g = prepared.next()) { int c = prepared.getGeometryID(); if (c != prevCollectionIndex) { + //add empty collections for all skipped indices + for (int i = prevCollectionIndex; i < c - 1; i++) { + result.add(new OGCConcreteGeometryCollection(esriSR)); + } + if (list != null) { result.add(removeOverlapsHelper_(list)); } list = new ArrayList(); + prevCollectionIndex = c; } list.add(g); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 72093351..8fda3edb 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -253,7 +253,7 @@ public boolean isMeasured() { */ public boolean Equals(OGCGeometry another) { if (this == another) - return true; + return true; //should return false for empty if (another == null) return false; @@ -333,6 +333,9 @@ public boolean relate(OGCGeometry another, String matrix) { // analysis public double distance(OGCGeometry another) { + if (this == another) + return isEmpty() ? Double.NaN : 0; + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { return another.distance(this); } @@ -456,6 +459,10 @@ public OGCGeometry convexHull() { } public OGCGeometry intersection(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return (new OGCConcreteGeometryCollection(this, esriSR)).intersection(another); + } + com.esri.core.geometry.OperatorIntersection op = (OperatorIntersection) OperatorFactoryLocal .getInstance().getOperator(Operator.Type.Intersection); com.esri.core.geometry.GeometryCursor cursor = op.execute( @@ -487,6 +494,10 @@ public OGCGeometry union(OGCGeometry another) { } public OGCGeometry difference(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return (new OGCConcreteGeometryCollection(this, esriSR)).difference(another); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return createFromEsriGeometry( diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index a8afb7da..b4dadf38 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -983,6 +983,18 @@ public void testUnionGeometryCollectionWithGeometryCollection() { "GEOMETRYCOLLECTION (POINT (3 5), LINESTRING (1 2, 2 3, 3 4, 5 6), POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)))"); } + @Test + public void testIntersectionGeometryCollectionWithGeometryCollection() { + assertIntersection("GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((0 0, 1 1, 0 1, 0 0)))", + "GEOMETRYCOLLECTION (POINT (1 2), POINT (2 3), POINT (0.5 0.5), POINT (3 5), LINESTRING (3 4, 5 6), POLYGON ((0 0, 1 0, 1 1, 0 0)))", + "GEOMETRYCOLLECTION (MULTIPOINT ((1 2), (2 3), (3 4)), LINESTRING (0 0, 0.5 0.5, 1 1))"); + } + + private void assertIntersection(String leftWkt, String rightWkt, String expectedWkt) { + OGCGeometry intersection = OGCGeometry.fromText(leftWkt).intersection(OGCGeometry.fromText(rightWkt)); + assertEquals(expectedWkt, intersection.asText()); + } + private void assertUnion(String leftWkt, String rightWkt, String expectedWkt) { OGCGeometry union = OGCGeometry.fromText(leftWkt).union(OGCGeometry.fromText(rightWkt)); assertEquals(expectedWkt, union.asText()); From af34eaf7e156346a588dca57b9118f6e790079c3 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Wed, 30 May 2018 21:40:45 -0700 Subject: [PATCH 24/75] Equals for collection, reducFromMulti --- .../ogc/OGCConcreteGeometryCollection.java | 70 ++++++++++++++++++- .../esri/core/geometry/ogc/OGCGeometry.java | 21 +++++- .../esri/core/geometry/ogc/OGCLineString.java | 7 +- .../core/geometry/ogc/OGCMultiLineString.java | 16 ++++- .../esri/core/geometry/ogc/OGCMultiPoint.java | 14 ++++ .../core/geometry/ogc/OGCMultiPolygon.java | 16 ++++- .../com/esri/core/geometry/ogc/OGCPoint.java | 7 +- .../esri/core/geometry/ogc/OGCPolygon.java | 7 +- .../java/com/esri/core/geometry/TestOGC.java | 4 +- 9 files changed, 149 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index c7737ab0..74e5876b 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -477,6 +477,20 @@ public void setSpatialReference(SpatialReference esriSR_) { public OGCGeometry convertToMulti() { return this; } + + @Override + public OGCGeometry reduceFromMulti() { + int n = numGeometries(); + if (n == 0) { + return this; + } + + if (n == 1) { + return geometryN(0).reduceFromMulti(); + } + + return this; + } @Override public String asJson() { @@ -582,7 +596,7 @@ public boolean contains(OGCGeometry another) { return false; if (this == another) - return false; + return true; //TODO: a simple envelope test @@ -612,6 +626,48 @@ public boolean contains(OGCGeometry another) { //each geometry of another is contained in a geometry from this. return true; } + + @Override + public boolean Equals(OGCGeometry another) { + if (this == another) + return !isEmpty(); + + if (another == null) + return false; + + + OGCGeometry g1 = reduceFromMulti(); + String t1 = g1.geometryType(); + OGCGeometry g2 = reduceFromMulti(); + if (t1 != g2.geometryType()) { + return false; + } + + if (t1 != OGCConcreteGeometryCollection.TYPE) { + return g1.Equals(g2); + } + + OGCConcreteGeometryCollection gc1 = (OGCConcreteGeometryCollection)g1; + OGCConcreteGeometryCollection gc2 = (OGCConcreteGeometryCollection)g2; + gc1 = gc1.flattenAndRemoveOverlaps(); + gc2 = gc2.flattenAndRemoveOverlaps(); + int n = gc1.numGeometries(); + if (n != gc2.numGeometries()) { + return false; + } + + boolean res = false; + for (int i = 0; i < n; ++i) { + if (!gc1.geometryN(i).Equals(gc2.geometryN(i))) { + return false; + } + + res = true; + } + + return res; + } + //Topological @Override public OGCGeometry difference(OGCGeometry another) { @@ -641,9 +697,13 @@ public OGCGeometry difference(OGCGeometry another) { result.add(cur); } + if (result.size() == 1) { + result.get(0).reduceFromMulti(); + } + return new OGCConcreteGeometryCollection(result, esriSR); } - + @Override public OGCGeometry intersection(OGCGeometry another) { List list = wrapGeomsIntoList_(this, another); @@ -666,6 +726,10 @@ public OGCGeometry intersection(OGCGeometry another) { result.add(partialIntersection); } } + + if (result.size() == 1) { + result.get(0).reduceFromMulti(); + } return (new OGCConcreteGeometryCollection(result, esriSR)).flattenAndRemoveOverlaps(); } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 8fda3edb..5014e207 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -253,17 +253,21 @@ public boolean isMeasured() { */ public boolean Equals(OGCGeometry another) { if (this == another) - return true; //should return false for empty + return !isEmpty(); if (another == null) return false; + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return another.Equals(this); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.equals(geom1, geom2, getEsriSpatialReference()); } - + @Deprecated public boolean equals(OGCGeometry another) { return Equals(another); @@ -481,7 +485,7 @@ public OGCGeometry union(OGCGeometry another) { geoms.add(this); geoms.add(another); OGCConcreteGeometryCollection geomCol = new OGCConcreteGeometryCollection(geoms, esriSR); - return geomCol.flattenAndRemoveOverlaps(); + return geomCol.flattenAndRemoveOverlaps().reduceFromMulti(); } OperatorUnion op = (OperatorUnion) OperatorFactoryLocal.getInstance() @@ -755,6 +759,17 @@ public void setSpatialReference(SpatialReference esriSR_) { */ public abstract OGCGeometry convertToMulti(); + /** + * For the geometry collection types, when it has 1 or 0 elements, converts a MultiPolygon to Polygon, + * MultiPoint to Point, MultiLineString to a LineString, and + * OGCConcretGeometryCollection to the reduced element it contains. + * + * If OGCConcretGeometryCollection is empty, returns self. + * + * @return A reduced geometry or this. + */ + public abstract OGCGeometry reduceFromMulti(); + @Override public String toString() { String snippet = asText(); diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java index 4df18c15..f044128d 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -151,5 +151,10 @@ public OGCGeometry convertToMulti() return new OGCMultiLineString((Polyline)multiPath, esriSR); } + @Override + public OGCGeometry reduceFromMulti() { + return this; + } + MultiPath multiPath; } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java index 91a6580e..6a2381e3 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -123,5 +123,19 @@ public OGCGeometry convertToMulti() return this; } + @Override + public OGCGeometry reduceFromMulti() { + int n = numGeometries(); + if (n == 0) { + return new OGCLineString(new Polyline(polyline.getDescription()), 0, esriSR); + } + + if (n == 1) { + return geometryN(0); + } + + return this; + } + Polyline polyline; } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java index 4f300ea3..b1c70a02 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java @@ -133,5 +133,19 @@ public OGCGeometry convertToMulti() return this; } + @Override + public OGCGeometry reduceFromMulti() { + int n = numGeometries(); + if (n == 0) { + return new OGCPoint(new Point(multiPoint.getDescription()), esriSR); + } + + if (n == 1) { + return geometryN(0); + } + + return this; + } + private com.esri.core.geometry.MultiPoint multiPoint; } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java index 520cc3f7..d2e64956 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -135,5 +135,19 @@ public OGCGeometry convertToMulti() return this; } + @Override + public OGCGeometry reduceFromMulti() { + int n = numGeometries(); + if (n == 0) { + return new OGCLineString(new Polygon(polygon.getDescription()), 0, esriSR); + } + + if (n == 1) { + return geometryN(0); + } + + return this; + } + Polygon polygon; } diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java index 608e809f..d0fba6e7 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -115,6 +115,11 @@ public OGCGeometry convertToMulti() { return new OGCMultiPoint(point, esriSR); } + + @Override + public OGCGeometry reduceFromMulti() { + return this; + } com.esri.core.geometry.Point point; diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java index 2bc65935..4c95250a 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -143,5 +143,10 @@ public OGCGeometry convertToMulti() return new OGCMultiPolygon(polygon, esriSR); } + @Override + public OGCGeometry reduceFromMulti() { + return this; + } + Polygon polygon; } diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index b4dadf38..eb40a2d4 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -957,7 +957,7 @@ public void testEmptyBoundary() throws Exception { @Test public void testUnionPointWithEmptyLineString() { - assertUnion("POINT (1 2)", "LINESTRING EMPTY", "GEOMETRYCOLLECTION (POINT (1 2))"); + assertUnion("POINT (1 2)", "LINESTRING EMPTY", "POINT (1 2)"); } @Test @@ -967,7 +967,7 @@ public void testUnionPointWithLinestring() { @Test public void testUnionLinestringWithEmptyPolygon() { - assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))"); + assertUnion("MULTILINESTRING ((1 2, 3 4))", "POLYGON EMPTY", "LINESTRING (1 2, 3 4)"); } @Test From aefd7d73ed31149f9a3d1e795d0ec1c856fac690 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sun, 3 Jun 2018 17:28:56 -0700 Subject: [PATCH 25/75] update some comments --- .../geometry/OperatorDifferenceLocal.java | 4 +- .../esri/core/geometry/TestDifference.java | 12 +- .../java/com/esri/core/geometry/TestOGC.java | 3 +- .../geometry/TestOGCGeometryCollection.java | 153 ++++++++++++++++++ 4 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java diff --git a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java index 02006bfc..b68b050f 100644 --- a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java @@ -81,9 +81,9 @@ static Geometry difference(Geometry geometry_a, Geometry geometry_b, if (!env_a_inflated.isIntersecting(env_b)) return geometry_a; - if (dimension_a == 1 && dimension_b == 2) + /*if (dimension_a == 1 && dimension_b == 2) return polylineMinusArea_(geometry_a, geometry_b, type_b, - spatial_reference, progress_tracker); + spatial_reference, progress_tracker);*/ if (type_a == Geometry.GeometryType.Point) { Geometry geometry_b_; diff --git a/src/test/java/com/esri/core/geometry/TestDifference.java b/src/test/java/com/esri/core/geometry/TestDifference.java index c6f22321..2ea73ffc 100644 --- a/src/test/java/com/esri/core/geometry/TestDifference.java +++ b/src/test/java/com/esri/core/geometry/TestDifference.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -24,8 +24,6 @@ package com.esri.core.geometry; -import java.util.ArrayList; -import java.util.List; import junit.framework.TestCase; @@ -504,6 +502,14 @@ public static void testDifferenceOnPolyline() { assertEquals(5, pointCountDiffPolyline); } + + @Test + public static void testDifferencePolylineAlongPolygonBoundary() { + Polyline polyline = (Polyline)GeometryEngine.geometryFromWkt("LINESTRING(0 0, 0 5, -2 5)", 0, Geometry.Type.Unknown); + Polygon polygon = (Polygon)GeometryEngine.geometryFromWkt("POLYGON((0 0, 5 0, 5 5, 0 5, 0 0))", 0, Geometry.Type.Unknown); + Geometry result = OperatorDifference.local().execute(polyline, polygon, null, null); + assertEquals(GeometryEngine.geometryToJson(null, result), "{\"paths\":[[[0,5],[-2,5]]]}"); + } public static Polygon makePolygon1() { Polygon poly = new Polygon(); diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index eb40a2d4..34403661 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -35,7 +35,6 @@ import com.esri.core.geometry.ogc.OGCMultiPolygon; import com.esri.core.geometry.ogc.OGCPoint; import com.esri.core.geometry.ogc.OGCPolygon; -import com.fasterxml.jackson.core.JsonParseException; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; import org.junit.Test; diff --git a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java new file mode 100644 index 00000000..1d1a32d7 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java @@ -0,0 +1,153 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import com.esri.core.geometry.ogc.OGCGeometry; +import org.junit.Assert; +import org.junit.Test; + +public class TestOGCGeometryCollection +{ + @Test + public void testUnionPoint() + { + // point - point + assertUnion("POINT (1 2)", "POINT (1 2)", "POINT (1 2)"); + assertUnion("POINT (1 2)", "POINT EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "POINT (3 4)", "MULTIPOINT ((1 2), (3 4))"); + + // point - multi-point + assertUnion("POINT (1 2)", "MULTIPOINT (1 2)", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTIPOINT EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTIPOINT (3 4)", "MULTIPOINT ((1 2), (3 4))"); + assertUnion("POINT (1 2)", "MULTIPOINT (1 2, 3 4)", "MULTIPOINT ((1 2), (3 4))"); + assertUnion("POINT (1 2)", "MULTIPOINT (3 4, 5 6)", "MULTIPOINT ((1 2), (3 4), (5 6))"); + + // point - linestring + assertUnion("POINT (1 2)", "LINESTRING (3 4, 5 6)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); + assertUnion("POINT (1 2)", "LINESTRING EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)"); + assertUnion("POINT (1 2)", "LINESTRING (1 1, 1 3, 3 4)", "LINESTRING (1 1, 1 2, 1 3, 3 4)"); + + // point - multi-linestring + assertUnion("POINT (1 2)", "MULTILINESTRING ((3 4, 5 6))", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); + assertUnion("POINT (1 2)", "MULTILINESTRING EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTILINESTRING ((3 4, 5 6), (7 8, 9 10, 11 12))", "GEOMETRYCOLLECTION (POINT (1 2), MULTILINESTRING ((3 4, 5 6), (7 8, 9 10, 11 12)))"); + assertUnion("POINT (1 2)", "MULTILINESTRING ((1 2, 3 4))", "LINESTRING (1 2, 3 4)"); + assertUnion("POINT (1 2)", "MULTILINESTRING ((1 1, 1 3, 3 4), (7 8, 9 10, 11 12))", "MULTILINESTRING ((1 1, 1 2, 1 3, 3 4), (7 8, 9 10, 11 12))"); + + // point - polygon + assertUnion("POINT (1 2)", "POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 1 0, 1 1, 0 0)))"); + assertUnion("POINT (1 2)", "POLYGON EMPTY", "POINT (1 2)"); + // point inside polygon + assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); + // point inside polygon with a hole + assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))"); + // point inside polygon's hole + assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))"); + // point is a vertex of the polygon + assertUnion("POINT (1 2)", "POLYGON ((1 2, 2 2, 2 3, 1 3, 1 2))", "POLYGON ((1 2, 2 2, 2 3, 1 3, 1 2))"); + // point on the boundary of the polybon + assertUnion("POINT (1 2)", "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 1))", "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 2, 1 1))"); + + // point - multi-polygon + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 1 0, 1 1, 0 0)))"); + assertUnion("POINT (1 2)", "MULTIPOLYGON EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)), ((4 4, 5 4, 5 5, 4 4)))", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)), ((4 4, 5 4, 5 5, 4 4)))"); + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))"); + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)), ((4 4, 5 4, 5 5, 4 4)))", "GEOMETRYCOLLECTION (POINT (1 2), MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)), ((4 4, 5 4, 5 5, 4 4))))"); + + // point - geometry collection + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2))", "POINT (1 2)"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2), POINT (2 3))", "MULTIPOINT ((1 2), (2 3))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (MULTIPOINT (1 2, 2 3))", "MULTIPOINT ((1 2), (2 3))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))", "LINESTRING (1 2, 3 4)"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 2, 3 4))", "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 2, 3 4))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))", "GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))"); + } + + @Test + public void testUnionLinestring() + { + // linestring - linestring + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING EMPTY", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (3 4, 1 2)", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (3 4, 5 6)", "LINESTRING (1 2, 3 4, 5 6)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (5 6, 7 8)", "MULTILINESTRING ((1 2, 3 4), (5 6, 7 8))"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (2 1, 2 5)", "MULTILINESTRING ((2 1, 2 3), (1 2, 2 3), (2 3, 3 4), (2 3, 2 5))"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 2 3, 4 3)", "MULTILINESTRING ((1 2, 2 3), (2 3, 4 3), (2 3, 3 4))"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (2 3, 2.1 3.1)", "LINESTRING (1 2, 2 3, 2.0999999999999996 3.0999999999999996, 3 4)"); + + // linestring - polygon + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((5 5, 6 5, 6 6, 5 5))", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((5 5, 6 5, 6 6, 5 5)))"); + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "LINESTRING (1 2, 3 4)"); + // linestring inside polygon + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + assertUnion("LINESTRING (0 0, 5 0)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + // linestring crosses polygon's vertex + assertUnion("LINESTRING (0 0, 6 6)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "GEOMETRYCOLLECTION (LINESTRING (5 5, 6 6), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))"); + assertUnion("LINESTRING (4 6, 6 4)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "GEOMETRYCOLLECTION (LINESTRING (4 6, 5 5, 6 4), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))"); + // linestring crosses polygon's boundary + assertUnion("LINESTRING (1 1, 1 6)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "GEOMETRYCOLLECTION (LINESTRING (1 5, 1 6), POLYGON ((0 0, 5 0, 5 5, 1 5, 0 5, 0 0)))"); + + // linestring - geometry collection + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION EMPTY", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (3 4, 5 6))", "LINESTRING (1 2, 3 4, 5 6)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (3 4, 5 6), LINESTRING (7 8, 9 10))", "MULTILINESTRING ((1 2, 3 4, 5 6), (7 8, 9 10))"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))", "LINESTRING (1 2, 3 4, 5 6)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6), POLYGON ((3 0, 4 0, 4 1, 3 0)))", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4, 5 6), POLYGON ((3 0, 4 0, 4 1, 3 0)))"); + } + + @Test + public void testUnionPolygon() + { + // polygon - polygon + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + // one polygon contains the other + assertUnion("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((1 1, 2 1, 2 2, 1 1))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + // The following test fails because vertex order in the union geometry depends on the order of union inputs + //assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 0.5 0, 0.5 0.5, 0 0))", "POLYGON ((0 0, 0.5 0, 1 0, 1 1, 0.49999999999999994 0.49999999999999994, 0 0))"); + // polygons intersect + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0.5, 2 0.5, 2 2, 0 2, 0 0.5))", "POLYGON ((0 0, 1 0, 1 0.5, 2 0.5, 2 2, 0 2, 0 0.5, 0.5 0.5, 0 0))"); + // disjoint polygons + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((3 3, 5 3, 5 5, 3 3))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + + // polygon - multi-polygon + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((0 0.5, 2 0.5, 2 2, 0 2, 0 0.5)))", "POLYGON ((0 0, 1 0, 1 0.5, 2 0.5, 2 2, 0 2, 0 0.5, 0.5 0.5, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((3 3, 5 3, 5 5, 3 3)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + + // polygon - geometry collection + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POLYGON ((0 0, 1 0, 1 1, 0 0)))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POLYGON ((3 3, 5 3, 5 5, 3 3)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POINT (0 0), POLYGON ((3 3, 5 3, 5 5, 3 3)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POINT (10 10), POLYGON ((3 3, 5 3, 5 5, 3 3)))", "GEOMETRYCOLLECTION (POINT (10 10), MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3))))"); + } + + private void assertUnion(String wkt, String otherWkt, String expectedWkt) + { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + Assert.assertEquals(expectedWkt, geometry.union(otherGeometry).asText()); + Assert.assertEquals(expectedWkt, otherGeometry.union(geometry).asText()); + } +} From b06e5793b00a4369cae7c559606147a29d910683 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sun, 3 Jun 2018 17:32:24 -0700 Subject: [PATCH 26/75] comment out unused code --- .../com/esri/core/geometry/OperatorDifferenceLocal.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java index b68b050f..e52e670d 100644 --- a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java @@ -358,7 +358,9 @@ static Geometry multiPointMinusPoint_(MultiPoint multi_point, Point point, return new_multipoint; } - static Geometry polylineMinusArea_(Geometry geometry, Geometry area, + /* + This optimization causes a bug when polyline segments are on the boundary. + static Geometry polylineMinusArea_(Geometry geometry, Geometry area, int area_type, SpatialReference sr, ProgressTracker progress_tracker) { // construct the complement of the Polygon (or Envelope) Envelope envelope = new Envelope(); @@ -387,6 +389,6 @@ static Geometry polylineMinusArea_(Geometry geometry, Geometry area, Geometry difference = operatorIntersection.execute(geometry, complement, sr, progress_tracker); return difference; - } + }*/ } From c47a0e49ba6b258cf0025cb6c9d9d2675cb0c4c6 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Mon, 4 Jun 2018 20:36:39 -0700 Subject: [PATCH 27/75] reflect review comments. fix formatting in a test --- .../geometry/OperatorDifferenceLocal.java | 39 +-- .../ogc/OGCConcreteGeometryCollection.java | 28 +- .../geometry/TestOGCGeometryCollection.java | 319 ++++++++++-------- 3 files changed, 188 insertions(+), 198 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java index e52e670d..31db5027 100644 --- a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java @@ -81,10 +81,6 @@ static Geometry difference(Geometry geometry_a, Geometry geometry_b, if (!env_a_inflated.isIntersecting(env_b)) return geometry_a; - /*if (dimension_a == 1 && dimension_b == 2) - return polylineMinusArea_(geometry_a, geometry_b, type_b, - spatial_reference, progress_tracker);*/ - if (type_a == Geometry.GeometryType.Point) { Geometry geometry_b_; if (MultiPath.isSegment(type_b)) { @@ -357,38 +353,5 @@ static Geometry multiPointMinusPoint_(MultiPoint multi_point, Point point, return new_multipoint; } - - /* - This optimization causes a bug when polyline segments are on the boundary. - static Geometry polylineMinusArea_(Geometry geometry, Geometry area, - int area_type, SpatialReference sr, ProgressTracker progress_tracker) { - // construct the complement of the Polygon (or Envelope) - Envelope envelope = new Envelope(); - geometry.queryEnvelope(envelope); - Envelope2D env_2D = new Envelope2D(); - area.queryEnvelope2D(env_2D); - envelope.merge(env_2D); - double dw = 0.1 * envelope.getWidth(); - double dh = 0.1 * envelope.getHeight(); - envelope.inflate(dw, dh); - - Polygon complement = new Polygon(); - complement.addEnvelope(envelope, false); - - MultiPathImpl complementImpl = (MultiPathImpl) (complement._getImpl()); - - if (area_type == Geometry.GeometryType.Polygon) { - MultiPathImpl polygonImpl = (MultiPathImpl) (area._getImpl()); - complementImpl.add(polygonImpl, true); - } else - complementImpl.addEnvelope((Envelope) (area), true); - - OperatorFactoryLocal projEnv = OperatorFactoryLocal.getInstance(); - OperatorIntersection operatorIntersection = (OperatorIntersection) projEnv - .getOperator(Operator.Type.Intersection); - Geometry difference = operatorIntersection.execute(geometry, - complement, sr, progress_tracker); - return difference; - }*/ - } + diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 74e5876b..d0a82e3f 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -598,33 +598,7 @@ public boolean contains(OGCGeometry another) { if (this == another) return true; - //TODO: a simple envelope test - - OGCConcreteGeometryCollection flattened1 = flatten(); - if (flattened1.isEmpty()) - return true; - OGCConcreteGeometryCollection otherCol = new OGCConcreteGeometryCollection(another, esriSR); - OGCConcreteGeometryCollection flattened2 = otherCol.flatten(); - if (flattened2.isEmpty()) - return true; - - for (int i = 0, n2 = flattened2.numGeometries(); i < n2; ++i) { - OGCGeometry g2 = flattened2.geometryN(i); - boolean good = false; - for (int j = 0, n1 = flattened1.numGeometries(); j < n1; ++j) { - OGCGeometry g1 = flattened1.geometryN(i); - if (g1.contains(g2)) { - good = true; - break; - } - } - - if (!good) - return false; - } - - //each geometry of another is contained in a geometry from this. - return true; + return another.difference(this).isEmpty(); } @Override diff --git a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java index 1d1a32d7..deadad18 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java @@ -17,137 +17,190 @@ import org.junit.Assert; import org.junit.Test; -public class TestOGCGeometryCollection -{ - @Test - public void testUnionPoint() - { - // point - point - assertUnion("POINT (1 2)", "POINT (1 2)", "POINT (1 2)"); - assertUnion("POINT (1 2)", "POINT EMPTY", "POINT (1 2)"); - assertUnion("POINT (1 2)", "POINT (3 4)", "MULTIPOINT ((1 2), (3 4))"); - - // point - multi-point - assertUnion("POINT (1 2)", "MULTIPOINT (1 2)", "POINT (1 2)"); - assertUnion("POINT (1 2)", "MULTIPOINT EMPTY", "POINT (1 2)"); - assertUnion("POINT (1 2)", "MULTIPOINT (3 4)", "MULTIPOINT ((1 2), (3 4))"); - assertUnion("POINT (1 2)", "MULTIPOINT (1 2, 3 4)", "MULTIPOINT ((1 2), (3 4))"); - assertUnion("POINT (1 2)", "MULTIPOINT (3 4, 5 6)", "MULTIPOINT ((1 2), (3 4), (5 6))"); - - // point - linestring - assertUnion("POINT (1 2)", "LINESTRING (3 4, 5 6)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); - assertUnion("POINT (1 2)", "LINESTRING EMPTY", "POINT (1 2)"); - assertUnion("POINT (1 2)", "LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)"); - assertUnion("POINT (1 2)", "LINESTRING (1 1, 1 3, 3 4)", "LINESTRING (1 1, 1 2, 1 3, 3 4)"); - - // point - multi-linestring - assertUnion("POINT (1 2)", "MULTILINESTRING ((3 4, 5 6))", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); - assertUnion("POINT (1 2)", "MULTILINESTRING EMPTY", "POINT (1 2)"); - assertUnion("POINT (1 2)", "MULTILINESTRING ((3 4, 5 6), (7 8, 9 10, 11 12))", "GEOMETRYCOLLECTION (POINT (1 2), MULTILINESTRING ((3 4, 5 6), (7 8, 9 10, 11 12)))"); - assertUnion("POINT (1 2)", "MULTILINESTRING ((1 2, 3 4))", "LINESTRING (1 2, 3 4)"); - assertUnion("POINT (1 2)", "MULTILINESTRING ((1 1, 1 3, 3 4), (7 8, 9 10, 11 12))", "MULTILINESTRING ((1 1, 1 2, 1 3, 3 4), (7 8, 9 10, 11 12))"); - - // point - polygon - assertUnion("POINT (1 2)", "POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 1 0, 1 1, 0 0)))"); - assertUnion("POINT (1 2)", "POLYGON EMPTY", "POINT (1 2)"); - // point inside polygon - assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); - // point inside polygon with a hole - assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))"); - // point inside polygon's hole - assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))"); - // point is a vertex of the polygon - assertUnion("POINT (1 2)", "POLYGON ((1 2, 2 2, 2 3, 1 3, 1 2))", "POLYGON ((1 2, 2 2, 2 3, 1 3, 1 2))"); - // point on the boundary of the polybon - assertUnion("POINT (1 2)", "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 1))", "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 2, 1 1))"); - - // point - multi-polygon - assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 1 0, 1 1, 0 0)))"); - assertUnion("POINT (1 2)", "MULTIPOLYGON EMPTY", "POINT (1 2)"); - assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); - assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)), ((4 4, 5 4, 5 5, 4 4)))", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)), ((4 4, 5 4, 5 5, 4 4)))"); - assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))", "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))"); - assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)), ((4 4, 5 4, 5 5, 4 4)))", "GEOMETRYCOLLECTION (POINT (1 2), MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)), ((4 4, 5 4, 5 5, 4 4))))"); - - // point - geometry collection - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2))", "POINT (1 2)"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION EMPTY", "POINT (1 2)"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2), POINT (2 3))", "MULTIPOINT ((1 2), (2 3))"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (MULTIPOINT (1 2, 2 3))", "MULTIPOINT ((1 2), (2 3))"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))", "LINESTRING (1 2, 3 4)"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 2, 3 4))", "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 2, 3 4))"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); - assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))", "GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))"); - } - - @Test - public void testUnionLinestring() - { - // linestring - linestring - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING EMPTY", "LINESTRING (1 2, 3 4)"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (3 4, 1 2)", "LINESTRING (1 2, 3 4)"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (3 4, 5 6)", "LINESTRING (1 2, 3 4, 5 6)"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (5 6, 7 8)", "MULTILINESTRING ((1 2, 3 4), (5 6, 7 8))"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (2 1, 2 5)", "MULTILINESTRING ((2 1, 2 3), (1 2, 2 3), (2 3, 3 4), (2 3, 2 5))"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 2 3, 4 3)", "MULTILINESTRING ((1 2, 2 3), (2 3, 4 3), (2 3, 3 4))"); - assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (2 3, 2.1 3.1)", "LINESTRING (1 2, 2 3, 2.0999999999999996 3.0999999999999996, 3 4)"); - - // linestring - polygon - assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((5 5, 6 5, 6 6, 5 5))", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((5 5, 6 5, 6 6, 5 5)))"); - assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "LINESTRING (1 2, 3 4)"); - // linestring inside polygon - assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); - assertUnion("LINESTRING (0 0, 5 0)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); - // linestring crosses polygon's vertex - assertUnion("LINESTRING (0 0, 6 6)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "GEOMETRYCOLLECTION (LINESTRING (5 5, 6 6), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))"); - assertUnion("LINESTRING (4 6, 6 4)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "GEOMETRYCOLLECTION (LINESTRING (4 6, 5 5, 6 4), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))"); - // linestring crosses polygon's boundary - assertUnion("LINESTRING (1 1, 1 6)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "GEOMETRYCOLLECTION (LINESTRING (1 5, 1 6), POLYGON ((0 0, 5 0, 5 5, 1 5, 0 5, 0 0)))"); - - // linestring - geometry collection - assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))", "LINESTRING (1 2, 3 4)"); - assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION EMPTY", "LINESTRING (1 2, 3 4)"); - assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (3 4, 5 6))", "LINESTRING (1 2, 3 4, 5 6)"); - assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (3 4, 5 6), LINESTRING (7 8, 9 10))", "MULTILINESTRING ((1 2, 3 4, 5 6), (7 8, 9 10))"); - assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))", "LINESTRING (1 2, 3 4, 5 6)"); - assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6), POLYGON ((3 0, 4 0, 4 1, 3 0)))", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4, 5 6), POLYGON ((3 0, 4 0, 4 1, 3 0)))"); - } - - @Test - public void testUnionPolygon() - { - // polygon - polygon - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); - // one polygon contains the other - assertUnion("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((1 1, 2 1, 2 2, 1 1))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); - // The following test fails because vertex order in the union geometry depends on the order of union inputs - //assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 0.5 0, 0.5 0.5, 0 0))", "POLYGON ((0 0, 0.5 0, 1 0, 1 1, 0.49999999999999994 0.49999999999999994, 0 0))"); - // polygons intersect - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0.5, 2 0.5, 2 2, 0 2, 0 0.5))", "POLYGON ((0 0, 1 0, 1 0.5, 2 0.5, 2 2, 0 2, 0 0.5, 0.5 0.5, 0 0))"); - // disjoint polygons - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((3 3, 5 3, 5 5, 3 3))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); - - // polygon - multi-polygon - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((0 0.5, 2 0.5, 2 2, 0 2, 0 0.5)))", "POLYGON ((0 0, 1 0, 1 0.5, 2 0.5, 2 2, 0 2, 0 0.5, 0.5 0.5, 0 0))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((3 3, 5 3, 5 5, 3 3)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); - - // polygon - geometry collection - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POLYGON ((0 0, 1 0, 1 1, 0 0)))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POLYGON ((3 3, 5 3, 5 5, 3 3)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POINT (0 0), POLYGON ((3 3, 5 3, 5 5, 3 3)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POINT (10 10), POLYGON ((3 3, 5 3, 5 5, 3 3)))", "GEOMETRYCOLLECTION (POINT (10 10), MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3))))"); - } - - private void assertUnion(String wkt, String otherWkt, String expectedWkt) - { - OGCGeometry geometry = OGCGeometry.fromText(wkt); - OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); - Assert.assertEquals(expectedWkt, geometry.union(otherGeometry).asText()); - Assert.assertEquals(expectedWkt, otherGeometry.union(geometry).asText()); - } +public class TestOGCGeometryCollection { + @Test + public void testUnionPoint() { + // point - point + assertUnion("POINT (1 2)", "POINT (1 2)", "POINT (1 2)"); + assertUnion("POINT (1 2)", "POINT EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "POINT (3 4)", "MULTIPOINT ((1 2), (3 4))"); + + // point - multi-point + assertUnion("POINT (1 2)", "MULTIPOINT (1 2)", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTIPOINT EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTIPOINT (3 4)", "MULTIPOINT ((1 2), (3 4))"); + assertUnion("POINT (1 2)", "MULTIPOINT (1 2, 3 4)", "MULTIPOINT ((1 2), (3 4))"); + assertUnion("POINT (1 2)", "MULTIPOINT (3 4, 5 6)", "MULTIPOINT ((1 2), (3 4), (5 6))"); + + // point - linestring + assertUnion("POINT (1 2)", "LINESTRING (3 4, 5 6)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); + assertUnion("POINT (1 2)", "LINESTRING EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)"); + assertUnion("POINT (1 2)", "LINESTRING (1 1, 1 3, 3 4)", "LINESTRING (1 1, 1 2, 1 3, 3 4)"); + + // point - multi-linestring + assertUnion("POINT (1 2)", "MULTILINESTRING ((3 4, 5 6))", + "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))"); + assertUnion("POINT (1 2)", "MULTILINESTRING EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTILINESTRING ((3 4, 5 6), (7 8, 9 10, 11 12))", + "GEOMETRYCOLLECTION (POINT (1 2), MULTILINESTRING ((3 4, 5 6), (7 8, 9 10, 11 12)))"); + assertUnion("POINT (1 2)", "MULTILINESTRING ((1 2, 3 4))", "LINESTRING (1 2, 3 4)"); + assertUnion("POINT (1 2)", "MULTILINESTRING ((1 1, 1 3, 3 4), (7 8, 9 10, 11 12))", + "MULTILINESTRING ((1 1, 1 2, 1 3, 3 4), (7 8, 9 10, 11 12))"); + + // point - polygon + assertUnion("POINT (1 2)", "POLYGON ((0 0, 1 0, 1 1, 0 0))", + "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 1 0, 1 1, 0 0)))"); + assertUnion("POINT (1 2)", "POLYGON EMPTY", "POINT (1 2)"); + // point inside polygon + assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); + // point inside polygon with a hole + assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))", + "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))"); + // point inside polygon's hole + assertUnion("POINT (1 2)", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1))", + "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))"); + // point is a vertex of the polygon + assertUnion("POINT (1 2)", "POLYGON ((1 2, 2 2, 2 3, 1 3, 1 2))", "POLYGON ((1 2, 2 2, 2 3, 1 3, 1 2))"); + // point on the boundary of the polybon + assertUnion("POINT (1 2)", "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 1))", "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 2, 1 1))"); + + // point - multi-polygon + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", + "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 1 0, 1 1, 0 0)))"); + assertUnion("POINT (1 2)", "MULTIPOLYGON EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)))", "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); + assertUnion("POINT (1 2)", "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)), ((4 4, 5 4, 5 5, 4 4)))", + "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0)), ((4 4, 5 4, 5 5, 4 4)))"); + assertUnion("POINT (1 2)", + "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))", + "GEOMETRYCOLLECTION (POINT (1 2), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)))"); + assertUnion("POINT (1 2)", + "MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)), ((4 4, 5 4, 5 5, 4 4)))", + "GEOMETRYCOLLECTION (POINT (1 2), MULTIPOLYGON (((0 0, 3 0, 3 3, 0 3, 0 0), (0.5 1, 0.5 2.5, 2.5 2.5, 2.5 1, 0.5 1)), ((4 4, 5 4, 5 5, 4 4))))"); + + // point - geometry collection + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2))", "POINT (1 2)"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION EMPTY", "POINT (1 2)"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2), POINT (2 3))", "MULTIPOINT ((1 2), (2 3))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (MULTIPOINT (1 2, 2 3))", "MULTIPOINT ((1 2), (2 3))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))", "LINESTRING (1 2, 3 4)"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 2, 3 4))", + "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 2, 3 4))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))", + "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); + assertUnion("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))", + "GEOMETRYCOLLECTION (POINT (5 5), POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)))"); + } + + @Test + public void testUnionLinestring() { + // linestring - linestring + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING EMPTY", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (3 4, 1 2)", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (3 4, 5 6)", "LINESTRING (1 2, 3 4, 5 6)"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (5 6, 7 8)", "MULTILINESTRING ((1 2, 3 4), (5 6, 7 8))"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (2 1, 2 5)", + "MULTILINESTRING ((2 1, 2 3), (1 2, 2 3), (2 3, 3 4), (2 3, 2 5))"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (1 2, 2 3, 4 3)", + "MULTILINESTRING ((1 2, 2 3), (2 3, 4 3), (2 3, 3 4))"); + assertUnion("LINESTRING (1 2, 3 4)", "LINESTRING (2 3, 2.1 3.1)", + "LINESTRING (1 2, 2 3, 2.0999999999999996 3.0999999999999996, 3 4)"); + + // linestring - polygon + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((5 5, 6 5, 6 6, 5 5))", + "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4), POLYGON ((5 5, 6 5, 6 6, 5 5)))"); + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON EMPTY", "LINESTRING (1 2, 3 4)"); + // linestring inside polygon + assertUnion("LINESTRING (1 2, 3 4)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", + "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + assertUnion("LINESTRING (0 0, 5 0)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", + "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + // linestring crosses polygon's vertex + assertUnion("LINESTRING (0 0, 6 6)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", + "GEOMETRYCOLLECTION (LINESTRING (5 5, 6 6), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))"); + assertUnion("LINESTRING (4 6, 6 4)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", + "GEOMETRYCOLLECTION (LINESTRING (4 6, 5 5, 6 4), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))"); + // linestring crosses polygon's boundary + assertUnion("LINESTRING (1 1, 1 6)", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", + "GEOMETRYCOLLECTION (LINESTRING (1 5, 1 6), POLYGON ((0 0, 5 0, 5 5, 1 5, 0 5, 0 0)))"); + + // linestring - geometry collection + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4))", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION EMPTY", "LINESTRING (1 2, 3 4)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (3 4, 5 6))", + "LINESTRING (1 2, 3 4, 5 6)"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (LINESTRING (3 4, 5 6), LINESTRING (7 8, 9 10))", + "MULTILINESTRING ((1 2, 3 4, 5 6), (7 8, 9 10))"); + assertUnion("LINESTRING (1 2, 3 4)", "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6))", + "LINESTRING (1 2, 3 4, 5 6)"); + assertUnion("LINESTRING (1 2, 3 4)", + "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (3 4, 5 6), POLYGON ((3 0, 4 0, 4 1, 3 0)))", + "GEOMETRYCOLLECTION (LINESTRING (1 2, 3 4, 5 6), POLYGON ((3 0, 4 0, 4 1, 3 0)))"); + } + + @Test + public void testUnionPolygon() { + // polygon - polygon + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))", + "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + // one polygon contains the other + assertUnion("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((1 1, 2 1, 2 2, 1 1))", + "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + // The following test fails because vertex order in the union geometry depends + // on the order of union inputs + // assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 0.5 0, 0.5 0.5, + // 0 0))", "POLYGON ((0 0, 0.5 0, 1 0, 1 1, 0.49999999999999994 + // 0.49999999999999994, 0 0))"); + // polygons intersect + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0.5, 2 0.5, 2 2, 0 2, 0 0.5))", + "POLYGON ((0 0, 1 0, 1 0.5, 2 0.5, 2 2, 0 2, 0 0.5, 0.5 0.5, 0 0))"); + // disjoint polygons + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((3 3, 5 3, 5 5, 3 3))", + "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + + // polygon - multi-polygon + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", + "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((0 0.5, 2 0.5, 2 2, 0 2, 0 0.5)))", + "POLYGON ((0 0, 1 0, 1 0.5, 2 0.5, 2 2, 0 2, 0 0.5, 0.5 0.5, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "MULTIPOLYGON (((3 3, 5 3, 5 5, 3 3)))", + "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + + // polygon - geometry collection + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POLYGON ((0 0, 1 0, 1 1, 0 0)))", + "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION EMPTY", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", "GEOMETRYCOLLECTION (POLYGON ((3 3, 5 3, 5 5, 3 3)))", + "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", + "GEOMETRYCOLLECTION (POINT (0 0), POLYGON ((3 3, 5 3, 5 5, 3 3)))", + "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3)))"); + assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 0))", + "GEOMETRYCOLLECTION (POINT (10 10), POLYGON ((3 3, 5 3, 5 5, 3 3)))", + "GEOMETRYCOLLECTION (POINT (10 10), MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((3 3, 5 3, 5 5, 3 3))))"); + } + + private void assertUnion(String wkt, String otherWkt, String expectedWkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + Assert.assertEquals(expectedWkt, geometry.union(otherGeometry).asText()); + Assert.assertEquals(expectedWkt, otherGeometry.union(geometry).asText()); + } + + @Test + public void testGeometryCollectionOverlappingContains() { + assertContains("GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (0 1, 5 1))", + "GEOMETRYCOLLECTION (MULTIPOINT (0 0, 2 1))"); + } + + private void assertContains(String wkt, String otherWkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + Assert.assertTrue(geometry.contains(otherGeometry)); + Assert.assertTrue(otherGeometry.within(geometry)); + } } From 873d073cbc66efd4616a8db2f0717538c646ac3f Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Wed, 6 Jun 2018 20:18:22 -0700 Subject: [PATCH 28/75] fix a typo in disjoint and a test --- .../ogc/OGCConcreteGeometryCollection.java | 2 +- .../core/geometry/TestOGCGeometryCollection.java | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index d0a82e3f..004c7a8f 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -581,7 +581,7 @@ public boolean disjoint(OGCGeometry another) { for (int i = 0, n1 = flattened1.numGeometries(); i < n1; ++i) { OGCGeometry g1 = flattened1.geometryN(i); for (int j = 0, n2 = flattened2.numGeometries(); j < n2; ++j) { - OGCGeometry g2 = flattened2.geometryN(i); + OGCGeometry g2 = flattened2.geometryN(j); if (!g1.disjoint(g2)) return false; } diff --git a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java index deadad18..c74752ee 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java @@ -203,4 +203,18 @@ private void assertContains(String wkt, String otherWkt) { Assert.assertTrue(geometry.contains(otherGeometry)); Assert.assertTrue(otherGeometry.within(geometry)); } + + @Test + public void testGeometryCollectionDisjoint() { + assertDisjoint("GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (0 1, 5 1))", + "GEOMETRYCOLLECTION (MULTIPOINT (10 0, 21 1), LINESTRING (30 0, 31 1), POLYGON ((40 0, 41 1, 40 1, 40 0)))"); + } + + private void assertDisjoint(String wkt, String otherWkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + Assert.assertTrue(geometry.disjoint(otherGeometry)); + Assert.assertTrue(otherGeometry.disjoint(geometry)); + } + } From 7e19e6f09d07c749b13aa346a946aea1aff413e2 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Thu, 7 Jun 2018 08:16:36 -0700 Subject: [PATCH 29/75] Reflect review comments, throw from unsupported methods --- .../ogc/OGCConcreteGeometryCollection.java | 37 ++++++++++++++++++- .../esri/core/geometry/ogc/OGCGeometry.java | 27 +++++++++++++- .../geometry/TestOGCGeometryCollection.java | 17 +++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 004c7a8f..3868a469 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -560,6 +560,29 @@ public double distance(OGCGeometry another) { // //Relational operations + @Override + public boolean overlaps(OGCGeometry another) { + //TODO + throw new UnsupportedOperationException(); + } + + @Override + public boolean touches(OGCGeometry another) { + //TODO + throw new UnsupportedOperationException(); + } + + @Override + public boolean crosses(OGCGeometry another) { + //TODO + throw new UnsupportedOperationException(); + } + + @Override + public boolean relate(OGCGeometry another, String matrix) { + throw new UnsupportedOperationException(); + } + @Override public boolean disjoint(OGCGeometry another) { if (isEmpty() || another.isEmpty()) @@ -672,7 +695,7 @@ public OGCGeometry difference(OGCGeometry another) { } if (result.size() == 1) { - result.get(0).reduceFromMulti(); + return result.get(0).reduceFromMulti(); } return new OGCConcreteGeometryCollection(result, esriSR); @@ -680,6 +703,10 @@ public OGCGeometry difference(OGCGeometry another) { @Override public OGCGeometry intersection(OGCGeometry another) { + if (isEmpty() || another.isEmpty()) { + return new OGCConcreteGeometryCollection(esriSR); + } + List list = wrapGeomsIntoList_(this, another); list = prepare_for_ops_(list); if (list.size() != 2) // this should not happen @@ -702,11 +729,17 @@ public OGCGeometry intersection(OGCGeometry another) { } if (result.size() == 1) { - result.get(0).reduceFromMulti(); + return result.get(0).reduceFromMulti(); } return (new OGCConcreteGeometryCollection(result, esriSR)).flattenAndRemoveOverlaps(); } + + @Override + public OGCGeometry symDifference(OGCGeometry another) { + //TODO + throw new UnsupportedOperationException(); + } //make a list of collections out of two geometries private static List wrapGeomsIntoList_(OGCGeometry g1, OGCGeometry g2) { diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 5014e207..87e8c620 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -289,6 +289,11 @@ public boolean intersects(OGCGeometry another) { } public boolean touches(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + //TODO + throw new UnsupportedOperationException(); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.touches(geom1, geom2, @@ -296,6 +301,11 @@ public boolean touches(OGCGeometry another) { } public boolean crosses(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + //TODO + throw new UnsupportedOperationException(); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.crosses(geom1, geom2, @@ -308,7 +318,7 @@ public boolean within(OGCGeometry another) { public boolean contains(OGCGeometry another) { if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { - return another.contains(this); + return new OGCConcreteGeometryCollection(this, esriSR).contains(another); } com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); @@ -318,6 +328,10 @@ public boolean contains(OGCGeometry another) { } public boolean overlaps(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return another.overlaps(this); //overlaps should be symmetric + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.overlaps(geom1, geom2, @@ -325,6 +339,11 @@ public boolean overlaps(OGCGeometry another) { } public boolean relate(OGCGeometry another, String matrix) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + //TODO + throw new UnsupportedOperationException(); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.relate(geom1, geom2, @@ -337,8 +356,9 @@ public boolean relate(OGCGeometry another, String matrix) { // analysis public double distance(OGCGeometry another) { - if (this == another) + if (this == another) { return isEmpty() ? Double.NaN : 0; + } if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { return another.distance(this); @@ -510,6 +530,9 @@ public OGCGeometry difference(OGCGeometry another) { } public OGCGeometry symDifference(OGCGeometry another) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) + return another.symDifference(this); + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return createFromEsriGeometry( diff --git a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java index c74752ee..53007166 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java @@ -216,5 +216,22 @@ private void assertDisjoint(String wkt, String otherWkt) { Assert.assertTrue(geometry.disjoint(otherGeometry)); Assert.assertTrue(otherGeometry.disjoint(geometry)); } + + @Test + public void testGeometryCollectionIntersect() { + assertIntersection("GEOMETRYCOLLECTION (POINT (1 2))", "POINT EMPTY", "GEOMETRYCOLLECTION EMPTY"); + assertIntersection("GEOMETRYCOLLECTION (POINT (1 2), MULTIPOINT (3 4, 5 6))", "POINT (3 4)", + "POINT (3 4)"); + assertIntersection("GEOMETRYCOLLECTION (POINT (1 2), MULTIPOINT (3 4, 5 6))", "POINT (30 40)", + "GEOMETRYCOLLECTION EMPTY"); + assertIntersection("POINT (30 40)", "GEOMETRYCOLLECTION (POINT (1 2), MULTIPOINT (3 4, 5 6))", + "GEOMETRYCOLLECTION EMPTY"); + } + private void assertIntersection(String wkt, String otherWkt, String expectedWkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + OGCGeometry result = geometry.intersection(otherGeometry); + Assert.assertEquals(expectedWkt, result.asText()); + } } From 104c2ef50e834f48d270133464945963137dfc58 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Thu, 7 Jun 2018 08:18:41 -0700 Subject: [PATCH 30/75] Added a test from @mbasmanova --- .../esri/core/geometry/TestOGCContains.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/test/java/com/esri/core/geometry/TestOGCContains.java diff --git a/src/test/java/com/esri/core/geometry/TestOGCContains.java b/src/test/java/com/esri/core/geometry/TestOGCContains.java new file mode 100644 index 00000000..fd2c5116 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCContains.java @@ -0,0 +1,74 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import com.esri.core.geometry.ogc.OGCGeometry; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TestOGCContains { + @Test + public void testPoint() { + // point + assertContains("POINT (1 2)", "POINT (1 2)"); + assertContains("POINT (1 2)", "GEOMETRYCOLLECTION (POINT (1 2))"); + assertNotContains("POINT (1 2)", "POINT EMPTY"); + assertNotContains("POINT (1 2)", "POINT (3 4)"); + + // multi-point + assertContains("MULTIPOINT (1 2, 3 4)", "MULTIPOINT (1 2, 3 4)"); + assertContains("MULTIPOINT (1 2, 3 4)", "MULTIPOINT (1 2)"); + assertContains("MULTIPOINT (1 2, 3 4)", "POINT (3 4)"); + assertContains("MULTIPOINT (1 2, 3 4)", "GEOMETRYCOLLECTION (MULTIPOINT (1 2), POINT (3 4))"); + assertContains("MULTIPOINT (1 2, 3 4)", "GEOMETRYCOLLECTION (POINT (1 2))"); + assertNotContains("MULTIPOINT (1 2, 3 4)", "MULTIPOINT EMPTY"); + } + + @Test + public void testLineString() { + // TODO Add more tests + assertContains("LINESTRING (0 1, 5 1)", "POINT (2 1)"); + } + + @Test + public void testPolygon() { + // TODO Fill in + } + + @Test + public void testGeometryCollection() { + // TODO Add more tests + assertContains("GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (0 1, 5 1))", + "GEOMETRYCOLLECTION (MULTIPOINT (0 0, 2 1))"); + } + + private void assertContains(String wkt, String otherWkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + + assertTrue(geometry.contains(otherGeometry)); + assertTrue(otherGeometry.within(geometry)); + assertFalse(geometry.disjoint(otherGeometry)); + } + + private void assertNotContains(String wkt, String otherWkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + assertFalse(geometry.contains(otherGeometry)); + assertFalse(otherGeometry.within(geometry)); + } +} + From 7030d57367fa2587cfcdc6786c42ee49cf1d5a2d Mon Sep 17 00:00:00 2001 From: Masha Basmanova Date: Thu, 7 Jun 2018 22:40:24 -0400 Subject: [PATCH 31/75] Fix OGCCollection#reduceFromMulti and add test --- .../core/geometry/ogc/OGCMultiPolygon.java | 2 +- .../core/geometry/TestOGCReduceFromMulti.java | 80 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/esri/core/geometry/TestOGCReduceFromMulti.java diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java index d2e64956..52afbe86 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java @@ -139,7 +139,7 @@ public OGCGeometry convertToMulti() public OGCGeometry reduceFromMulti() { int n = numGeometries(); if (n == 0) { - return new OGCLineString(new Polygon(polygon.getDescription()), 0, esriSR); + return new OGCPolygon(new Polygon(polygon.getDescription()), 0, esriSR); } if (n == 1) { diff --git a/src/test/java/com/esri/core/geometry/TestOGCReduceFromMulti.java b/src/test/java/com/esri/core/geometry/TestOGCReduceFromMulti.java new file mode 100644 index 00000000..f47c817c --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCReduceFromMulti.java @@ -0,0 +1,80 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import org.junit.Test; + +import static com.esri.core.geometry.ogc.OGCGeometry.fromText; +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; + +public class TestOGCReduceFromMulti +{ + @Test + public void testPoint() + { + assertReduceFromMulti("POINT (1 2)", "POINT (1 2)"); + assertReduceFromMulti("POINT EMPTY", "POINT EMPTY"); + assertReduceFromMulti("MULTIPOINT (1 2)", "POINT (1 2)"); + assertReduceFromMulti("MULTIPOINT (1 2, 3 4)", "MULTIPOINT ((1 2), (3 4))"); + assertReduceFromMulti("MULTIPOINT EMPTY", "POINT EMPTY"); + } + + @Test + public void testLineString() + { + assertReduceFromMulti("LINESTRING (0 0, 1 1, 2 3)", "LINESTRING (0 0, 1 1, 2 3)"); + assertReduceFromMulti("LINESTRING EMPTY", "LINESTRING EMPTY"); + assertReduceFromMulti("MULTILINESTRING ((0 0, 1 1, 2 3))", "LINESTRING (0 0, 1 1, 2 3)"); + assertReduceFromMulti("MULTILINESTRING ((0 0, 1 1, 2 3), (4 4, 5 5))", "MULTILINESTRING ((0 0, 1 1, 2 3), (4 4, 5 5))"); + assertReduceFromMulti("MULTILINESTRING EMPTY", "LINESTRING EMPTY"); + } + + @Test + public void testPolygon() + { + assertReduceFromMulti("POLYGON ((0 0, 1 0, 1 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertReduceFromMulti("POLYGON EMPTY", "POLYGON EMPTY"); + assertReduceFromMulti("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))", "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + assertReduceFromMulti("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((2 2, 3 2, 3 3, 2 2)))", "MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((2 2, 3 2, 3 3, 2 2)))"); + assertReduceFromMulti("MULTIPOLYGON EMPTY", "POLYGON EMPTY"); + } + + @Test + public void testGeometryCollection() + { + assertReduceFromMulti(gc("POINT (1 2)"), "POINT (1 2)"); + assertReduceFromMulti(gc("MULTIPOINT (1 2)"), "POINT (1 2)"); + assertReduceFromMulti(gc(gc("POINT (1 2)")), "POINT (1 2)"); + assertReduceFromMulti(gc("POINT EMPTY"), "POINT EMPTY"); + + assertReduceFromMulti(gc("LINESTRING (0 0, 1 1, 2 3)"), "LINESTRING (0 0, 1 1, 2 3)"); + assertReduceFromMulti(gc("POLYGON ((0 0, 1 0, 1 1, 0 0))"), "POLYGON ((0 0, 1 0, 1 1, 0 0))"); + + assertReduceFromMulti(gc("POINT (1 2), LINESTRING (0 0, 1 1, 2 3)"), gc("POINT (1 2), LINESTRING (0 0, 1 1, 2 3)")); + + assertReduceFromMulti("GEOMETRYCOLLECTION EMPTY", "GEOMETRYCOLLECTION EMPTY"); + assertReduceFromMulti(gc("GEOMETRYCOLLECTION EMPTY"), "GEOMETRYCOLLECTION EMPTY"); + } + + private void assertReduceFromMulti(String wkt, String reducedWkt) + { + assertEquals(reducedWkt, fromText(wkt).reduceFromMulti().asText()); + } + + private String gc(String wkts) + { + return format("GEOMETRYCOLLECTION (%s)", wkts); + } +} From 40b324e8d01eec1d98eeac872fcca992bcb24c1a Mon Sep 17 00:00:00 2001 From: Masha Basmanova Date: Fri, 8 Jun 2018 00:30:02 -0400 Subject: [PATCH 32/75] Add tests for distance and flatten --- .../ogc/OGCConcreteGeometryCollection.java | 2 + .../esri/core/geometry/TestOGCDistance.java | 59 +++++++++++++++++++ .../TestOGCGeometryCollectionFlatten.java | 48 +++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 src/test/java/com/esri/core/geometry/TestOGCDistance.java create mode 100644 src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 3868a469..660f70ed 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -546,9 +546,11 @@ public double distance(OGCGeometry another) { double minD = Double.NaN; for (int i = 0, n = numGeometries(); i < n; ++i) { + // TODO Skip expensive distance computation if bounding boxes are further away than minD double d = geometryN(i).distance(another); if (d < minD || Double.isNaN(minD)) { minD = d; + // TODO Replace zero with tolerance defined by the spatial reference if (minD == 0) { break; } diff --git a/src/test/java/com/esri/core/geometry/TestOGCDistance.java b/src/test/java/com/esri/core/geometry/TestOGCDistance.java new file mode 100644 index 00000000..dea491f9 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCDistance.java @@ -0,0 +1,59 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import org.junit.Test; + +import static com.esri.core.geometry.ogc.OGCGeometry.fromText; +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; + +public class TestOGCDistance +{ + @Test + public void testPoint() + { + assertDistance("POINT (1 2)", "POINT (2 2)", 1); + assertDistance("POINT (1 2)", "POINT (1 2)", 0); + assertNanDistance("POINT (1 2)", "POINT EMPTY"); + + assertDistance(gc("POINT (1 2)"), "POINT (2 2)", 1); + assertDistance(gc("POINT (1 2)"), "POINT (1 2)", 0); + assertNanDistance(gc("POINT (1 2)"), "POINT EMPTY"); + assertDistance(gc("POINT (1 2)"), gc("POINT (2 2)"), 1); + + assertDistance("MULTIPOINT (1 0, 2 0, 3 0)", "POINT (2 1)", 1); + assertDistance(gc("MULTIPOINT (1 0, 2 0, 3 0)"), "POINT (2 1)", 1); + assertDistance(gc("POINT (1 0), POINT (2 0), POINT (3 0))"), "POINT (2 1)", 1); + + assertDistance(gc("POINT (1 0), POINT EMPTY"), "POINT (2 0)", 1); + } + + private void assertDistance(String wkt, String otherWkt, double distance) + { + assertEquals(distance, fromText(wkt).distance(fromText(otherWkt)), 0.000001); + assertEquals(distance, fromText(otherWkt).distance(fromText(wkt)), 0.000001); + } + + private void assertNanDistance(String wkt, String otherWkt) + { + assertEquals(Double.NaN, fromText(wkt).distance(fromText(otherWkt)), 0.000001); + assertEquals(Double.NaN, fromText(otherWkt).distance(fromText(wkt)), 0.000001); + } + + private String gc(String wkts) + { + return format("GEOMETRYCOLLECTION (%s)", wkts); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java new file mode 100644 index 00000000..50832f2d --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java @@ -0,0 +1,48 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; +import com.esri.core.geometry.ogc.OGCGeometry; +import org.junit.Test; + +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TestOGCGeometryCollectionFlatten +{ + @Test + public void test() + { + assertFlatten("GEOMETRYCOLLECTION EMPTY", "GEOMETRYCOLLECTION EMPTY"); + assertFlatten(gc("POINT (1 2)"), gc("MULTIPOINT ((1 2))")); + assertFlatten(gc("POINT (1 2), POINT EMPTY"), gc("MULTIPOINT ((1 2))")); + assertFlatten(gc("POINT (1 2), MULTIPOINT (3 4, 5 6)"), gc("MULTIPOINT ((1 2), (3 4), (5 6))")); + assertFlatten(gc("POINT (1 2), POINT (3 4), " + gc("POINT (5 6)")), gc("MULTIPOINT ((1 2), (3 4), (5 6))")); + } + + private void assertFlatten(String wkt, String flattenedWkt) + { + OGCConcreteGeometryCollection collection = (OGCConcreteGeometryCollection) OGCGeometry.fromText(wkt); + assertEquals(flattenedWkt, collection.flatten().asText()); + assertTrue(collection.flatten().isFlattened()); + assertEquals(flattenedWkt, collection.flatten().flatten().asText()); + } + + private String gc(String wkts) + { + return format("GEOMETRYCOLLECTION (%s)", wkts); + } +} From 8c20f1d25f206d07bff65c5664f5ab702e30293c Mon Sep 17 00:00:00 2001 From: Masha Basmanova Date: Fri, 8 Jun 2018 00:30:26 -0400 Subject: [PATCH 33/75] Simplify intersection and difference --- .../ogc/OGCConcreteGeometryCollection.java | 183 +++++++----------- .../esri/core/geometry/TestOGCDisjoint.java | 126 ++++++++++++ .../TestOGCGeometryCollectionFlatten.java | 4 +- 3 files changed, 203 insertions(+), 110 deletions(-) create mode 100644 src/test/java/com/esri/core/geometry/TestOGCDisjoint.java diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 660f70ed..155b8c41 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -25,6 +25,7 @@ package com.esri.core.geometry.ogc; import com.esri.core.geometry.Envelope; +import com.esri.core.geometry.GeoJsonExportFlags; import com.esri.core.geometry.Geometry; import com.esri.core.geometry.GeometryCursor; import com.esri.core.geometry.GeometryException; @@ -35,15 +36,15 @@ import com.esri.core.geometry.OGCStructureInternal; import com.esri.core.geometry.OperatorConvexHull; import com.esri.core.geometry.OperatorDifference; +import com.esri.core.geometry.OperatorExportToGeoJson; +import com.esri.core.geometry.OperatorIntersection; +import com.esri.core.geometry.OperatorUnion; +import com.esri.core.geometry.Point; import com.esri.core.geometry.Polygon; import com.esri.core.geometry.Polyline; import com.esri.core.geometry.SimpleGeometryCursor; import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.VertexDescription; -import com.esri.core.geometry.GeoJsonExportFlags; -import com.esri.core.geometry.OperatorExportToGeoJson; -import com.esri.core.geometry.OperatorUnion; -import com.esri.core.geometry.Point; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -648,6 +649,8 @@ public boolean Equals(OGCGeometry another) { OGCConcreteGeometryCollection gc1 = (OGCConcreteGeometryCollection)g1; OGCConcreteGeometryCollection gc2 = (OGCConcreteGeometryCollection)g2; + // TODO Assuming input geometries are simple and valid, remove-overlaps would be a no-op. + // Hence, calling flatten() should be sufficient. gc1 = gc1.flattenAndRemoveOverlaps(); gc2 = gc2.flattenAndRemoveOverlaps(); int n = gc1.numGeometries(); @@ -655,52 +658,66 @@ public boolean Equals(OGCGeometry another) { return false; } - boolean res = false; for (int i = 0; i < n; ++i) { if (!gc1.geometryN(i).Equals(gc2.geometryN(i))) { return false; } - - res = true; } - return res; + return n > 0; } - + + private static OGCConcreteGeometryCollection toGeometryCollection(OGCGeometry geometry) + { + if (geometry.geometryType() != OGCConcreteGeometryCollection.TYPE) { + return new OGCConcreteGeometryCollection(geometry, geometry.getEsriSpatialReference()); + } + + return (OGCConcreteGeometryCollection) geometry; + } + + private static List toList(GeometryCursor cursor) + { + List geometries = new ArrayList(); + for (Geometry geometry = cursor.next(); geometry != null; geometry = cursor.next()) { + geometries.add(geometry); + } + return geometries; + } + //Topological @Override public OGCGeometry difference(OGCGeometry another) { - List list = wrapGeomsIntoList_(this, another); - list = prepare_for_ops_(list); - if (list.size() != 2) // this should not happen - throw new GeometryException("internal error"); - + if (isEmpty() || another.isEmpty()) { + return this; + } + + List geometries = toList(prepare_for_ops_(toGeometryCollection(this))); + List otherGeometries = toList(prepare_for_ops_(toGeometryCollection(another))); + List result = new ArrayList(); - OGCConcreteGeometryCollection coll1 = list.get(0); - OGCConcreteGeometryCollection coll2 = list.get(1); - for (int i = 0, n = coll1.numGeometries(); i < n; ++i) { - OGCGeometry cur = coll1.geometryN(i); - for (int j = 0, n2 = coll2.numGeometries(); j < n2; ++j) { - OGCGeometry geom2 = coll2.geometryN(j); - if (cur.dimension() > geom2.dimension()) + for (Geometry geometry : geometries) { + for (Geometry otherGeometry : otherGeometries) { + if (geometry.getDimension() > otherGeometry.getDimension()) { continue; //subtracting lower dimension has no effect. - - cur = cur.difference(geom2); - if (cur.isEmpty()) + } + + geometry = OperatorDifference.local().execute(geometry, otherGeometry, esriSR, null); + if (geometry.isEmpty()) { break; + } + } + + if (!geometry.isEmpty()) { + result.add(OGCGeometry.createFromEsriGeometry(geometry, esriSR)); } - - if (cur.isEmpty()) - continue; - - result.add(cur); } - + if (result.size() == 1) { return result.get(0).reduceFromMulti(); } - return new OGCConcreteGeometryCollection(result, esriSR); + return new OGCConcreteGeometryCollection(result, esriSR).flattenAndRemoveOverlaps(); } @Override @@ -708,25 +725,18 @@ public OGCGeometry intersection(OGCGeometry another) { if (isEmpty() || another.isEmpty()) { return new OGCConcreteGeometryCollection(esriSR); } - - List list = wrapGeomsIntoList_(this, another); - list = prepare_for_ops_(list); - if (list.size() != 2) // this should not happen - throw new GeometryException("internal error"); - + + List geometries = toList(prepare_for_ops_(toGeometryCollection(this))); + List otherGeometries = toList(prepare_for_ops_(toGeometryCollection(another))); + List result = new ArrayList(); - OGCConcreteGeometryCollection coll1 = list.get(0); - OGCConcreteGeometryCollection coll2 = list.get(1); - for (int i = 0, n = coll1.numGeometries(); i < n; ++i) { - OGCGeometry cur = coll1.geometryN(i); - for (int j = 0, n2 = coll2.numGeometries(); j < n2; ++j) { - OGCGeometry geom2 = coll2.geometryN(j); - - OGCGeometry partialIntersection = cur.intersection(geom2); - if (partialIntersection.isEmpty()) - continue; - - result.add(partialIntersection); + for (Geometry geometry : geometries) { + for (Geometry otherGeometry : otherGeometries) { + GeometryCursor intersectionCursor = OperatorIntersection.local().execute(new SimpleGeometryCursor(geometry), new SimpleGeometryCursor(otherGeometry), esriSR, null, 7); + OGCGeometry intersection = OGCGeometry.createFromEsriCursor(intersectionCursor, esriSR, true); + if (!intersection.isEmpty()) { + result.add(intersection); + } } } @@ -734,7 +744,7 @@ public OGCGeometry intersection(OGCGeometry another) { return result.get(0).reduceFromMulti(); } - return (new OGCConcreteGeometryCollection(result, esriSR)).flattenAndRemoveOverlaps(); + return new OGCConcreteGeometryCollection(result, esriSR).flattenAndRemoveOverlaps(); } @Override @@ -743,21 +753,6 @@ public OGCGeometry symDifference(OGCGeometry another) { throw new UnsupportedOperationException(); } - //make a list of collections out of two geometries - private static List wrapGeomsIntoList_(OGCGeometry g1, OGCGeometry g2) { - List list = new ArrayList(); - if (g1.geometryType() != OGCConcreteGeometryCollection.TYPE) { - g1 = new OGCConcreteGeometryCollection(g1, g1.getEsriSpatialReference()); - } - if (g2.geometryType() != OGCConcreteGeometryCollection.TYPE) { - g2 = new OGCConcreteGeometryCollection(g2, g2.getEsriSpatialReference()); - } - - list.add((OGCConcreteGeometryCollection)g1); - list.add((OGCConcreteGeometryCollection)g2); - - return list; - } /** * Checks if collection is flattened. * @return True for the flattened collection. A flattened collection contains up to three non-empty geometries: @@ -869,24 +864,23 @@ public OGCConcreteGeometryCollection flatten() { /** * Fixes topological overlaps in the GeometryCollecion. * This is equivalent to union of the geometry collection elements. - * + * + * TODO "flattened" collection is supposed to contain only mutli-geometries, but this method may return single geometries + * e.g. for GEOMETRYCOLLECTION (LINESTRING (...)) it returns GEOMETRYCOLLECTION (LINESTRING (...)) + * and not GEOMETRYCOLLECTION (MULTILINESTRING (...)) * @return A geometry collection that is flattened and has no overlapping elements. */ public OGCConcreteGeometryCollection flattenAndRemoveOverlaps() { - ArrayList geoms = new ArrayList(); - + //flatten and crack/cluster GeometryCursor cursor = OGCStructureInternal.prepare_for_ops_(flatten().getEsriGeometryCursor(), esriSR); - for (Geometry g = cursor.next(); g != null; g = cursor.next()) { - geoms.add(g); - } - + //make sure geometries don't overlap - return removeOverlapsHelper_(geoms); + return new OGCConcreteGeometryCollection(removeOverlapsHelper_(toList(cursor)), esriSR); } - - private OGCConcreteGeometryCollection removeOverlapsHelper_(List geoms) { - ArrayList result = new ArrayList(); + + private GeometryCursor removeOverlapsHelper_(List geoms) { + List result = new ArrayList(); for (int i = 0; i < geoms.size(); ++i) { Geometry current = geoms.get(i); if (current.isEmpty()) @@ -905,7 +899,7 @@ private OGCConcreteGeometryCollection removeOverlapsHelper_(List geoms result.add(current); } - return new OGCConcreteGeometryCollection(new SimpleGeometryCursor(result), esriSR); + return new SimpleGeometryCursor(result); } private static class FlatteningCollectionCursor extends GeometryCursor { @@ -956,36 +950,9 @@ public int getGeometryID() { //Collectively processes group of geometry collections (intersects all segments and clusters points). //Flattens collections, removes overlaps. //Once done, the result collections would work well for topological and relational operations. - private List prepare_for_ops_(List geoms) { - assert(geoms != null && !geoms.isEmpty()); - GeometryCursor prepared = OGCStructureInternal.prepare_for_ops_(new FlatteningCollectionCursor(geoms), esriSR); - - List result = new ArrayList(); - int prevCollectionIndex = -1; - List list = null; - for (Geometry g = prepared.next(); g != null; g = prepared.next()) { - int c = prepared.getGeometryID(); - if (c != prevCollectionIndex) { - //add empty collections for all skipped indices - for (int i = prevCollectionIndex; i < c - 1; i++) { - result.add(new OGCConcreteGeometryCollection(esriSR)); - } - - if (list != null) { - result.add(removeOverlapsHelper_(list)); - } - - list = new ArrayList(); - prevCollectionIndex = c; - } - - list.add(g); - } - - if (list != null) { - result.add(removeOverlapsHelper_(list)); - } - - return result; + private GeometryCursor prepare_for_ops_(OGCConcreteGeometryCollection collection) { + assert(collection != null && !collection.isEmpty()); + GeometryCursor prepared = OGCStructureInternal.prepare_for_ops_(collection.flatten().getEsriGeometryCursor(), esriSR); + return removeOverlapsHelper_(toList(prepared)); } } diff --git a/src/test/java/com/esri/core/geometry/TestOGCDisjoint.java b/src/test/java/com/esri/core/geometry/TestOGCDisjoint.java new file mode 100644 index 00000000..45090e83 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCDisjoint.java @@ -0,0 +1,126 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.esri.core.geometry; + +import com.esri.core.geometry.ogc.OGCGeometry; +import org.junit.Test; + +import static java.lang.String.format; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TestOGCDisjoint +{ + @Test + public void testPoint() + { + // point + assertDisjoint("POINT (1 2)", "POINT (3 4)"); + assertDisjoint("POINT (1 2)", "POINT EMPTY"); + assertNotDisjoint("POINT (1 2)", "POINT (1 2)", "POINT (1 2)"); + + // multi-point + assertDisjoint("POINT (1 2)", "MULTIPOINT (3 4, 5 6)"); + assertDisjoint("POINT (1 2)", "MULTIPOINT EMPTY"); + assertNotDisjoint("POINT (1 2)", "MULTIPOINT (1 2, 3 4, 5 6)", "POINT (1 2)"); + assertNotDisjoint("POINT (1 2)", "MULTIPOINT (1 2)", "POINT (1 2)"); + } + + @Test + public void testLinestring() + { + // TODO Fill in + } + + @Test + public void testPolygon() + { + // TODO Fill in + } + + @Test + public void testGeometryCollection() + { + assertDisjoint("GEOMETRYCOLLECTION (POINT (1 2))", "POINT (3 4)"); + // GeometryException: internal error + assertDisjoint("GEOMETRYCOLLECTION (POINT (1 2))", "POINT EMPTY"); + assertNotDisjoint("GEOMETRYCOLLECTION (POINT (1 2))", "POINT (1 2)", "POINT (1 2)"); + + assertDisjoint("GEOMETRYCOLLECTION (POINT (1 2), MULTIPOINT (3 4, 5 6))", "POINT (0 0)"); + assertNotDisjoint("GEOMETRYCOLLECTION (POINT (1 2), MULTIPOINT (3 4, 5 6))", "POINT (3 4)", "POINT (3 4)"); + + String wkt = "GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 5 0), POLYGON ((2 2, 3 2, 3 3, 2 2)))"; + assertDisjoint(wkt, gc("POINT (0 2)")); + + assertNotDisjoint(wkt, gc("POINT (1 2)"), "POINT (1 2)"); + // point within the line + assertNotDisjoint(wkt, gc("POINT (0 0)"), "POINT (0 0)"); + assertNotDisjoint(wkt, gc("POINT (1 0)"), "POINT (1 0)"); + // point within the polygon + assertNotDisjoint(wkt, gc("POINT (2 2)"), "POINT (2 2)"); + assertNotDisjoint(wkt, gc("POINT (2.5 2)"), "POINT (2.5 2)"); + assertNotDisjoint(wkt, gc("POINT (2.5 2.1)"), "POINT (2.5 2.1)"); + + assertDisjoint(wkt, gc("LINESTRING (0 2, 1 3)")); + + // line intersects the point + assertNotDisjoint(wkt, gc("LINESTRING (0 1, 2 3)"), "POINT (1 2)"); + // line intersects the line + assertNotDisjoint(wkt, gc("LINESTRING (0 0, 1 0)"), "LINESTRING (0 0, 1 0)"); + assertNotDisjoint(wkt, gc("LINESTRING (5 -1, 5 1)"), "POINT (5 0)"); + // line intersects the polygon + assertNotDisjoint(wkt, gc("LINESTRING (0 0, 5 5)"), gc("POINT (0 0), LINESTRING (2 2, 3 3)")); + assertNotDisjoint(wkt, gc("LINESTRING (0 2.5, 2.6 2.5)"), "LINESTRING (2.5 2.5, 2.6 2.5)"); + + assertDisjoint(wkt, gc("POLYGON ((5 5, 6 5, 6 6, 5 5))")); + assertDisjoint(wkt, gc("POLYGON ((-1 -1, 10 -1, 10 10, -1 10, -1 -1), (-0.1 -0.1, 5.1 -0.1, 5.1 5.1, -0.1 5.1, -0.1 -0.1))")); + + assertNotDisjoint(wkt, gc("POLYGON ((-1 -1, 10 -1, 10 10, -1 10, -1 -1))"), gc("POINT (1 2), LINESTRING (0 0, 5 0), POLYGON ((2 2, 3 2, 3 3, 2 2))")); + assertNotDisjoint(wkt, gc("POLYGON ((2 -1, 4 -1, 4 1, 2 1, 2 -1))"), "LINESTRING (2 0, 4 0)"); + assertNotDisjoint(wkt, gc("POLYGON ((0 1, 1.5 1, 1.5 2.5, 0 2.5, 0 1))"), "POINT (1 2)"); + assertNotDisjoint(wkt, gc("POLYGON ((5 0, 6 0, 6 5, 5 0))"), "POINT (5 0)"); + } + + private String gc(String wkts) + { + return format("GEOMETRYCOLLECTION (%s)", wkts); + } + + private void assertDisjoint(String wkt, String otherWkt) + { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + assertTrue(geometry.disjoint(otherGeometry)); + assertFalse(geometry.intersects(otherGeometry)); + assertTrue(geometry.intersection(otherGeometry).isEmpty()); + + assertTrue(otherGeometry.disjoint(geometry)); + assertFalse(otherGeometry.intersects(geometry)); + assertTrue(otherGeometry.intersection(geometry).isEmpty()); + } + + private void assertNotDisjoint(String wkt, String otherWkt, String intersectionWkt) + { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); + assertFalse(geometry.disjoint(otherGeometry)); + assertTrue(geometry.intersects(otherGeometry)); + assertEquals(intersectionWkt, geometry.intersection(otherGeometry).asText()); + + assertFalse(otherGeometry.disjoint(geometry)); + assertTrue(otherGeometry.intersects(geometry)); + assertEquals(intersectionWkt, otherGeometry.intersection(geometry).asText()); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java index 50832f2d..8a98d5d1 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollectionFlatten.java @@ -14,9 +14,9 @@ package com.esri.core.geometry; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; -import com.esri.core.geometry.ogc.OGCGeometry; import org.junit.Test; +import static com.esri.core.geometry.ogc.OGCGeometry.fromText; import static java.lang.String.format; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -35,7 +35,7 @@ public void test() private void assertFlatten(String wkt, String flattenedWkt) { - OGCConcreteGeometryCollection collection = (OGCConcreteGeometryCollection) OGCGeometry.fromText(wkt); + OGCConcreteGeometryCollection collection = (OGCConcreteGeometryCollection) fromText(wkt); assertEquals(flattenedWkt, collection.flatten().asText()); assertTrue(collection.flatten().isFlattened()); assertEquals(flattenedWkt, collection.flatten().flatten().asText()); From 7b2bc6af4f50fea99ce9ccea252b1547f5a3cf78 Mon Sep 17 00:00:00 2001 From: Masha Basmanova Date: Fri, 8 Jun 2018 01:10:08 -0400 Subject: [PATCH 34/75] Block overlaps and symDifference for geometry collections --- .../java/com/esri/core/geometry/ogc/OGCGeometry.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 87e8c620..17ef2f8f 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -329,7 +329,8 @@ public boolean contains(OGCGeometry another) { public boolean overlaps(OGCGeometry another) { if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { - return another.overlaps(this); //overlaps should be symmetric + // TODO + throw new UnsupportedOperationException(); } com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); @@ -530,9 +531,11 @@ public OGCGeometry difference(OGCGeometry another) { } public OGCGeometry symDifference(OGCGeometry another) { - if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) - return another.symDifference(this); - + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + // TODO + throw new UnsupportedOperationException(); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return createFromEsriGeometry( From 6fcc5e68237dc2cca710ee594d8ab8e9c69fa1a3 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Tue, 26 Jun 2018 16:36:29 -0700 Subject: [PATCH 35/75] update jackson to 2.9.6 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0255ec18..3035ef99 100755 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ 1.6 - 2.9.4 + 2.9.6 4.12 0.9 From ac760efd95d14d5fb8550f1970c8a886df66b171 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Wed, 27 Jun 2018 08:19:56 -0700 Subject: [PATCH 36/75] jackson-2.9.6 --- build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.xml b/build.xml index a4bc51b1..a2e894a4 100644 --- a/build.xml +++ b/build.xml @@ -14,7 +14,7 @@ - + From c74e7a8fb604bf1831e0982f71e5ee67e692354a Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Fri, 29 Jun 2018 09:01:15 -0700 Subject: [PATCH 37/75] Geometry release v2.2.0 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 46b42a05..a4b5e0ae 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 2.1.0 + 2.2.0 ``` diff --git a/pom.xml b/pom.xml index 3035ef99..e4c2b890 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.0-SNAPSHOT + 2.2.0 jar Esri Geometry API for Java From e7fb7cae3468c14d33dad528f7dfe6b08d4048e2 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Fri, 6 Jul 2018 10:56:30 -0700 Subject: [PATCH 38/75] Add serialization for QuadTree and related classes --- .../core/geometry/AttributeStreamOfInt32.java | 58 ++++++++++- .../java/com/esri/core/geometry/QuadTree.java | 8 +- .../com/esri/core/geometry/QuadTreeImpl.java | 78 +++++++++++++-- .../geometry/StridedIndexTypeCollection.java | 8 +- .../esri/core/geometry/TestSerialization.java | 96 ++++++++++++++++++- 5 files changed, 232 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java index 1939bb0f..52d07517 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -27,14 +27,20 @@ import com.esri.core.geometry.VertexDescription.Persistence; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.Arrays; import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32; import static com.esri.core.geometry.SizeOf.sizeOfIntArray; -final class AttributeStreamOfInt32 extends AttributeStreamBase { - private int[] m_buffer = null; +final class AttributeStreamOfInt32 extends AttributeStreamBase implements Serializable { + private static final long serialVersionUID = 1L; + + transient private int[] m_buffer = null; private int m_size; public void reserve(int reserve) @@ -594,7 +600,6 @@ private void _selfWriteRangeImpl(int toElement, int count, int fromElement, // reverse what we written int j = toElement; int offset = toElement + count - stride; - int dj = stride; for (int i = 0, n = count / 2; i < n; i++) { for (int k = 0; k < stride; k++) { int v = m_buffer[j + k]; @@ -728,4 +733,49 @@ void quicksort(int leftIn, int rightIn, IntComparator compare, public void sort(int start, int end) { Arrays.sort(m_buffer, start, end); } + + private void writeObject(java.io.ObjectOutputStream stream) + throws IOException { + stream.defaultWriteObject(); + IntBuffer intBuf = null; + byte[] bytes = null; + for (int i = 0; i < m_size;) { + int n = Math.min(32, m_size - i); + if (bytes == null) { + bytes = new byte[n * 4]; //32 elements at a time + ByteBuffer buf = ByteBuffer.wrap(bytes); + intBuf = buf.asIntBuffer(); + } + intBuf.rewind(); + intBuf.put(m_buffer, i, n); + stream.write(bytes, 0, n * 4); + i += n; + } + } + + private void readObject(java.io.ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + m_buffer = new int[m_size]; + IntBuffer intBuf = null; + byte[] bytes = null; + for (int i = 0; i < m_size;) { + int n = Math.min(32, m_size - i); + if (bytes == null) { + bytes = new byte[n * 4]; //32 elements at a time + ByteBuffer buf = ByteBuffer.wrap(bytes); + intBuf = buf.asIntBuffer(); + } + stream.read(bytes, 0, n * 4); + intBuf.rewind(); + intBuf.get(m_buffer, i, n); + i += n; + } + } + + @SuppressWarnings("unused") + private void readObjectNoData() throws ObjectStreamException { + m_buffer = new int[2]; + m_size = 0; + } } diff --git a/src/main/java/com/esri/core/geometry/QuadTree.java b/src/main/java/com/esri/core/geometry/QuadTree.java index 32d81c3c..0b4a4945 100644 --- a/src/main/java/com/esri/core/geometry/QuadTree.java +++ b/src/main/java/com/esri/core/geometry/QuadTree.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,7 +25,11 @@ package com.esri.core.geometry; -public class QuadTree { +import java.io.Serializable; + +public class QuadTree implements Serializable { + private static final long serialVersionUID = 1L; + public static final class QuadTreeIterator { /** * Resets the iterator to an starting state on the QuadTree. If the diff --git a/src/main/java/com/esri/core/geometry/QuadTreeImpl.java b/src/main/java/com/esri/core/geometry/QuadTreeImpl.java index fe48999a..bedabdac 100644 --- a/src/main/java/com/esri/core/geometry/QuadTreeImpl.java +++ b/src/main/java/com/esri/core/geometry/QuadTreeImpl.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,9 +23,15 @@ */ package com.esri.core.geometry; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.Serializable; import java.util.ArrayList; -class QuadTreeImpl { +class QuadTreeImpl implements Serializable { + private static final long serialVersionUID = 1L; + static final class QuadTreeIteratorImpl { /** * Resets the iterator to an starting state on the Quad_tree_impl. If @@ -1248,19 +1254,28 @@ private void set_data_values_(int data_handle, int element, Envelope2D bounding_ private Envelope2D m_data_extent; private StridedIndexTypeCollection m_quad_tree_nodes; private StridedIndexTypeCollection m_element_nodes; - private ArrayList m_data; + transient private ArrayList m_data; private AttributeStreamOfInt32 m_free_data; private int m_root; private int m_height; private boolean m_b_store_duplicates; - private int m_quadrant_mask = 3; - private int m_height_bit_shift = 2; - private int m_flushing_count = 5; + final static private int m_quadrant_mask = 3; + final static private int m_height_bit_shift = 2; + final static private int m_flushing_count = 5; static final class Data { int element; Envelope2D box; + + Data() { + } + + Data(int element_, double x1, double y1, double x2, double y2) { + element = element_; + box = new Envelope2D(); + box.setCoords(x1, y1, x2, y2); + } Data(int element_, Envelope2D box_) { element = element_; @@ -1269,6 +1284,57 @@ static final class Data { } } + private void writeObject(java.io.ObjectOutputStream stream) + throws IOException { + stream.defaultWriteObject(); + stream.writeInt(m_data.size()); + for (int i = 0, n = m_data.size(); i < n; ++i) { + Data d = m_data.get(i); + if (d != null) { + stream.writeByte(1); + stream.writeInt(d.element); + stream.writeDouble(d.box.xmin); + stream.writeDouble(d.box.ymin); + stream.writeDouble(d.box.xmax); + stream.writeDouble(d.box.ymax); + } + else { + stream.writeByte(0); + } + + } + } + + private void readObject(java.io.ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + int dataSize = stream.readInt(); + m_data = new ArrayList(dataSize); + for (int i = 0, n = dataSize; i < n; ++i) { + int b = stream.readByte(); + if (b == 1) { + int elm = stream.readInt(); + double x1 = stream.readDouble(); + double y1 = stream.readDouble(); + double x2 = stream.readDouble(); + double y2 = stream.readDouble(); + Data d = new Data(elm, x1, y1, x2, y2); + m_data.add(d); + } + else if (b == 0) { + m_data.add(null); + } + else { + throw new IOException(); + } + } + } + + @SuppressWarnings("unused") + private void readObjectNoData() throws ObjectStreamException { + throw new InvalidObjectException("Stream data required"); + } + /* m_quad_tree_nodes * 0: m_north_east_child * 1: m_north_west_child diff --git a/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java b/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java index c54cfe9a..8bd607e5 100644 --- a/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java +++ b/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,13 +23,17 @@ */ package com.esri.core.geometry; +import java.io.Serializable; + /** * A collection of strides of Index_type elements. To be used when one needs a * collection of homogeneous elements that contain only integer fields (i.e. * structs with Index_type members) Recycles the strides. Allows for constant * time creation and deletion of an element. */ -final class StridedIndexTypeCollection { +final class StridedIndexTypeCollection implements Serializable { + private static final long serialVersionUID = 1L; + private int[][] m_buffer = null; private int m_firstFree = -1; private int m_last = 0; diff --git a/src/test/java/com/esri/core/geometry/TestSerialization.java b/src/test/java/com/esri/core/geometry/TestSerialization.java index 8cdb4ad9..5f3796a1 100644 --- a/src/test/java/com/esri/core/geometry/TestSerialization.java +++ b/src/test/java/com/esri/core/geometry/TestSerialization.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.FileOutputStream; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -401,4 +400,97 @@ public void testSerializeEnvelope2D() { } } + public void testAttributeStreamOfInt32() { + AttributeStreamOfInt32 a = new AttributeStreamOfInt32(0); + for (int i = 0; i < 100; i++) + a.add(i); + + try { + // serialize + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream os = new ObjectOutputStream(baos); + os.writeObject(a); + os.close(); + baos.close(); + + // deserialize + ByteArrayInputStream bais = new ByteArrayInputStream( + baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + AttributeStreamOfInt32 aOut = (AttributeStreamOfInt32) in.readObject(); + in.close(); + bais.close(); + + assertTrue(aOut.size() == a.size()); + for (int i = 0; i < 100; i++) + assertTrue(aOut.get(i) == a.get(i)); + + } catch (Exception e) { + fail("AttributeStreamOfInt32 serialization failure"); + } + + } + + @Test + public void testQuadTree() { + MultiPoint mp = new MultiPoint(); + int r = 124124; + for (int i = 0; i < 100; ++i) { + r = NumberUtils.nextRand(r); + int x = r; + r = NumberUtils.nextRand(r); + int y = r; + mp.add(x, y); + } + + Envelope2D extent = new Envelope2D(); + mp.queryEnvelope2D(extent); + QuadTree quadTree = new QuadTree(extent, 8); + Envelope2D boundingbox = new Envelope2D(); + Point2D pt; + + for (int i = 0; i < mp.getPointCount(); i++) { + pt = mp.getXY(i); + boundingbox.setCoords(pt.x, pt.y, pt.x, pt.y); + quadTree.insert(i, boundingbox, -1); + } + + try { + // serialize + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream os = new ObjectOutputStream(baos); + os.writeObject(quadTree); + os.close(); + baos.close(); + + // deserialize + ByteArrayInputStream bais = new ByteArrayInputStream( + baos.toByteArray()); + ObjectInputStream in = new ObjectInputStream(bais); + QuadTree qOut = (QuadTree) in.readObject(); + in.close(); + bais.close(); + + assertTrue(quadTree.getElementCount() == qOut.getElementCount()); + QuadTree.QuadTreeIterator iter1 = quadTree.getIterator(); + QuadTree.QuadTreeIterator iter2 = qOut.getIterator(); + int h1 = iter1.next(); + int h2 = iter2.next(); + for (; h1 != -1 && h2 != -1; h1 = iter1.next(), h2 = iter2.next()) { + assertTrue(quadTree.getElement(h1) == qOut.getElement(h2)); + assertTrue(quadTree.getElementExtent(h1).equals(qOut.getElementExtent(h2))); + assertTrue(quadTree.getExtent(quadTree.getQuad(h1)).equals(qOut.getExtent(qOut.getQuad(h2)))); + int c1 = quadTree.getSubTreeElementCount(quadTree.getQuad(h1)); + int c2 = qOut.getSubTreeElementCount(qOut.getQuad(h2)); + assertTrue(c1 == c2); + } + + assertTrue(h1 == -1 && h2 == -1); + + assertTrue(quadTree.getDataExtent().equals(qOut.getDataExtent())); + } catch (Exception e) { + fail("QuadTree serialization failure"); + } + + } } From acc586158532658c73a43bdfeec5a75ee8bab34d Mon Sep 17 00:00:00 2001 From: Tim Meehan Date: Wed, 1 Aug 2018 12:42:03 -0700 Subject: [PATCH 39/75] Fix NPE on estimateMemorySize against empty multipart geometries This commit fixes an NPE in the estimateMemorySize method when the following geometries are empty: - LINESTRING - MULTILINESTRING - GEOMETRY - MULTIGEOMETRY It also adds test "empty" versions the current unit test suite. --- .../com/esri/core/geometry/MultiPathImpl.java | 4 +-- .../core/geometry/TestEstimateMemorySize.java | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java index 54ec0a5d..249a2a48 100644 --- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java @@ -66,8 +66,8 @@ public long estimateMemorySize() + (m_envelope != null ? m_envelope.estimateMemorySize() : 0) + (m_moveToPoint != null ? m_moveToPoint.estimateMemorySize() : 0) + (m_cachedRingAreas2D != null ? m_cachedRingAreas2D.estimateMemorySize() : 0) - + m_paths.estimateMemorySize() - + m_pathFlags.estimateMemorySize() + + (m_paths != null ? m_paths.estimateMemorySize() : 0) + + (m_pathFlags != null ? m_pathFlags.estimateMemorySize() : 0) + (m_segmentFlags != null ? m_segmentFlags.estimateMemorySize() : 0) + (m_segmentParamIndex != null ? m_segmentParamIndex.estimateMemorySize() : 0) + (m_segmentParams != null ? m_segmentParams.estimateMemorySize() : 0); diff --git a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java index e4195c58..ae391d8c 100644 --- a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java +++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java @@ -77,36 +77,71 @@ public void testPoint() { testGeometry(parseWkt("POINT (1 2)")); } + @Test + public void testEmptyPoint() { + testGeometry(parseWkt("POINT EMPTY")); + } + @Test public void testMultiPoint() { testGeometry(parseWkt("MULTIPOINT (0 0, 1 1, 2 3)")); } + @Test + public void testEmptyMultiPoint() { + testGeometry(parseWkt("MULTIPOINT EMPTY")); + } + @Test public void testLineString() { testGeometry(parseWkt("LINESTRING (0 1, 2 3, 4 5)")); } + @Test + public void testEmptyLineString() { + testGeometry(parseWkt("LINESTRING EMPTY")); + } + @Test public void testMultiLineString() { testGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); } + @Test + public void testEmptyMultiLineString() { + testGeometry(parseWkt("MULTILINESTRING EMPTY")); + } + @Test public void testPolygon() { testGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); } + @Test + public void testEmptyPolygon() { + testGeometry(parseWkt("POLYGON EMPTY")); + } + @Test public void testMultiPolygon() { testGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))")); } + @Test + public void testEmptyMultiPolygon() { + testGeometry(parseWkt("MULTIPOLYGON EMPTY")); + } + @Test public void testGeometryCollection() { testGeometry(parseWkt("GEOMETRYCOLLECTION (POINT(4 6), LINESTRING(4 6,7 10))")); } + @Test + public void testEmptyGeometryCollection() { + testGeometry(parseWkt("GEOMETRYCOLLECTION EMPTY")); + } + private void testGeometry(OGCGeometry geometry) { assertTrue(geometry.estimateMemorySize() > 0); } From 072434b521ad1dd62ef6d9ee2214888a1868e5a3 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 14 Aug 2018 13:43:22 -0700 Subject: [PATCH 40/75] Fix convex hull crash for collection of polygons --- .gitignore | 1 + .../geometry/ogc/OGCConcreteGeometryCollection.java | 4 ++-- .../java/com/esri/core/geometry/TestConvexHull.java | 10 ++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 7328fe5d..1e2db53a 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ ehthumbs.db Thumbs.db target/* /bin/ +/target/ diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java index 155b8c41..66eb1310 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -444,13 +444,13 @@ else if (geom.getType() == Geometry.Type.Point) { } if (!polygon.isEmpty()) { - if (!resultGeom.isEmpty()) { + if (resultGeom != null && !resultGeom.isEmpty()) { Geometry[] geoms = { resultGeom, polygon }; resultGeom = OperatorConvexHull.local().execute( new SimpleGeometryCursor(geoms), true, null).next(); } else { - resultGeom = polygon; + resultGeom = OperatorConvexHull.local().execute(polygon, null); } } diff --git a/src/test/java/com/esri/core/geometry/TestConvexHull.java b/src/test/java/com/esri/core/geometry/TestConvexHull.java index b29d3aaf..ee9c764e 100644 --- a/src/test/java/com/esri/core/geometry/TestConvexHull.java +++ b/src/test/java/com/esri/core/geometry/TestConvexHull.java @@ -1059,4 +1059,14 @@ public void testHullIssueGithub172() { } } + @Test + public void testHullIssueGithub194() { + { + //empty + OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION(POLYGON EMPTY, POLYGON((0 0, 1 0, 1 1, 0 0)), POLYGON((-10 -10, 10 -10, 10 10, -10 10, -10 -10), (-5 -5, -5 5, 5 5, 5 -5, -5 -5)))"); + OGCGeometry result = geom.convexHull(); + String text = result.asText(); + assertTrue(text.compareTo("POLYGON ((-10 -10, 10 -10, 10 10, -10 10, -10 -10))") == 0); + } + } } From 28666569726a3b45184180ba3398219eab653f06 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Fri, 17 Aug 2018 13:19:11 -0700 Subject: [PATCH 41/75] Delete MgrsConversionMode.java This file is unused. --- .../core/geometry/MgrsConversionMode.java | 60 ------------------- 1 file changed, 60 deletions(-) delete mode 100644 src/main/java/com/esri/core/geometry/MgrsConversionMode.java diff --git a/src/main/java/com/esri/core/geometry/MgrsConversionMode.java b/src/main/java/com/esri/core/geometry/MgrsConversionMode.java deleted file mode 100644 index b92ef646..00000000 --- a/src/main/java/com/esri/core/geometry/MgrsConversionMode.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - Copyright 1995-2015 Esri - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - - email: contracts@esri.com - */ - -package com.esri.core.geometry; - -/** - * The modes for converting between military grid reference system (MGRS) - * notation and coordinates. - * */ -public interface MgrsConversionMode { - /** - * Uses the spheroid to determine the military grid string. - */ - public static final int mgrsAutomatic = 0;// PE_MGRS_STYLE_AUTO - /** - * Treats all spheroids as new, like WGS 1984, when creating or reading a - * military grid string. The 180 longitude falls into zone 60. - */ - public static final int mgrsNewStyle = 0x100; // PE_MGRS_STYLE_NEW - /** - * Treats all spheroids as old, like Bessel 1841, when creating or reading a - * military grid string. The 180 longitude falls into zone 60. - */ - public static final int mgrsOldStyle = 0x200; // PE_MGRS_STYLE_OLD - /** - * Treats all spheroids as new, like WGS 1984, when creating or reading a - * military grid string. The 180 longitude falls into zone 01. - */ - public static final int mgrsNewWith180InZone01 = 0x1000 + 0x100; // PE_MGRS_180_ZONE_1_PLUS - // | - // PE_MGRS_STYLE_NEW - /** - * Treats all spheroids as old, like Bessel 1841, when creating or reading a - * military grid string. The 180 longitude falls into zone 01. - */ - public static final int mgrsOldWith180InZone01 = 0x1000 + 0x200; // PE_MGRS_180_ZONE_1_PLUS - // | - // PE_MGRS_STYLE_OLD -} From bc4769aa254e82a33b0959abc15ff146886ce932 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Fri, 31 Aug 2018 09:36:43 -0700 Subject: [PATCH 42/75] Geometry release v2.2.1 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a4b5e0ae..171fa4c6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 2.2.0 + 2.2.1 ``` diff --git a/pom.xml b/pom.xml index e4c2b890..2815d47f 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.0 + 2.2.1 jar Esri Geometry API for Java From 17fdf4e57264fdd778e3d87e59566d51e6ce923a Mon Sep 17 00:00:00 2001 From: Masha Basmanova Date: Wed, 21 Nov 2018 14:46:25 -0500 Subject: [PATCH 43/75] Add accelerator size to OGCGeometry#estimateMemorySize --- .../core/geometry/GeometryAccelerators.java | 9 ++- .../com/esri/core/geometry/MultiPathImpl.java | 5 ++ .../com/esri/core/geometry/QuadTreeImpl.java | 23 +++++++- .../core/geometry/RasterizedGeometry2D.java | 6 ++ .../geometry/RasterizedGeometry2DImpl.java | 31 +++++++--- .../esri/core/geometry/SimpleRasterizer.java | 59 ++++++++++++++++--- .../java/com/esri/core/geometry/SizeOf.java | 23 ++++++++ .../geometry/StridedIndexTypeCollection.java | 18 ++++++ .../esri/core/geometry/Transformation2D.java | 6 ++ .../core/geometry/TestEstimateMemorySize.java | 47 +++++++++++++-- 10 files changed, 201 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/GeometryAccelerators.java b/src/main/java/com/esri/core/geometry/GeometryAccelerators.java index 2ccc84cc..90d699d0 100644 --- a/src/main/java/com/esri/core/geometry/GeometryAccelerators.java +++ b/src/main/java/com/esri/core/geometry/GeometryAccelerators.java @@ -23,8 +23,6 @@ */ package com.esri.core.geometry; -import java.util.ArrayList; - class GeometryAccelerators { private RasterizedGeometry2D m_rasterizedGeometry; @@ -84,4 +82,11 @@ static boolean canUseQuadTreeForPaths(Geometry geom) { return true; } + + public long estimateMemorySize() + { + return (m_rasterizedGeometry != null ? m_rasterizedGeometry.estimateMemorySize() : 0) + + (m_quad_tree != null ? m_quad_tree.estimateMemorySize() : 0) + + (m_quad_tree_for_paths != null ? m_quad_tree_for_paths.estimateMemorySize() : 0); + } } diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java index 249a2a48..c9400ee0 100644 --- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java @@ -77,6 +77,11 @@ public long estimateMemorySize() size += m_vertexAttributes[i].estimateMemorySize(); } } + + if (m_accelerators != null) { + size += m_accelerators.estimateMemorySize(); + } + return size; } diff --git a/src/main/java/com/esri/core/geometry/QuadTreeImpl.java b/src/main/java/com/esri/core/geometry/QuadTreeImpl.java index bedabdac..e9234bb5 100644 --- a/src/main/java/com/esri/core/geometry/QuadTreeImpl.java +++ b/src/main/java/com/esri/core/geometry/QuadTreeImpl.java @@ -29,6 +29,10 @@ import java.io.Serializable; import java.util.ArrayList; +import static com.esri.core.geometry.SizeOf.SIZE_OF_DATA; +import static com.esri.core.geometry.SizeOf.SIZE_OF_QUAD_TREE_IMPL; +import static com.esri.core.geometry.SizeOf.sizeOfObjectArray; + class QuadTreeImpl implements Serializable { private static final long serialVersionUID = 1L; @@ -777,6 +781,22 @@ QuadTreeSortedIteratorImpl getSortedIterator() { return new QuadTreeSortedIteratorImpl(getIterator()); } + public long estimateMemorySize() + { + long size = SIZE_OF_QUAD_TREE_IMPL + + (m_extent != null ? m_extent.estimateMemorySize() : 0) + + (m_data_extent != null ? m_data_extent.estimateMemorySize() : 0) + + (m_quad_tree_nodes != null ? m_quad_tree_nodes.estimateMemorySize() : 0) + + (m_element_nodes != null ? m_element_nodes.estimateMemorySize() : 0) + + (m_free_data != null ? m_free_data.estimateMemorySize() : 0); + + if (m_data != null) { + size += sizeOfObjectArray(m_data.size()) + m_data.size() * SIZE_OF_DATA; + } + + return size; + } + private void reset_(Envelope2D extent, int height) { if (height < 0 || height > 127) throw new IllegalArgumentException("invalid height"); @@ -1268,9 +1288,6 @@ static final class Data { int element; Envelope2D box; - Data() { - } - Data(int element_, double x1, double y1, double x2, double y2) { element = element_; box = new Envelope2D(); diff --git a/src/main/java/com/esri/core/geometry/RasterizedGeometry2D.java b/src/main/java/com/esri/core/geometry/RasterizedGeometry2D.java index 46ccd5c6..ff1b8257 100644 --- a/src/main/java/com/esri/core/geometry/RasterizedGeometry2D.java +++ b/src/main/java/com/esri/core/geometry/RasterizedGeometry2D.java @@ -136,4 +136,10 @@ static boolean canUseAccelerator(Geometry geom) { */ public abstract boolean dbgSaveToBitmap(String fileName); + /** + * Returns an estimate of this object size in bytes. + * + * @return Returns an estimate of this object size in bytes. + */ + public abstract long estimateMemorySize(); } diff --git a/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java b/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java index ff21c8ec..6b9a2e4d 100644 --- a/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java +++ b/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java @@ -24,18 +24,14 @@ package com.esri.core.geometry; -import java.io.*; +import java.io.FileOutputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import com.esri.core.geometry.Envelope2D; -import com.esri.core.geometry.Geometry; -import com.esri.core.geometry.GeometryException; -import com.esri.core.geometry.NumberUtils; -import com.esri.core.geometry.Point2D; -import com.esri.core.geometry.Segment; -import com.esri.core.geometry.SegmentIteratorImpl; -import com.esri.core.geometry.SimpleRasterizer; +import static com.esri.core.geometry.SizeOf.SIZE_OF_RASTERIZED_GEOMETRY_2D_IMPL; +import static com.esri.core.geometry.SizeOf.SIZE_OF_SCAN_CALLBACK_IMPL; +import static com.esri.core.geometry.SizeOf.sizeOfIntArray; final class RasterizedGeometry2DImpl extends RasterizedGeometry2D { int[] m_bitmap; @@ -89,6 +85,13 @@ public void drawScan(int[] scans, int scanCount3) { } } } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_SCAN_CALLBACK_IMPL + + (m_bitmap != null ? sizeOfIntArray(m_bitmap.length) : 0); + } } void fillMultiPath(SimpleRasterizer rasterizer, Transformation2D trans, MultiPathImpl polygon, boolean isWinding) { @@ -559,4 +562,14 @@ public boolean dbgSaveToBitmap(String fileName) { } } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_RASTERIZED_GEOMETRY_2D_IMPL + + (m_geomEnv != null ? m_geomEnv.estimateMemorySize() : 0) + + (m_transform != null ? m_transform.estimateMemorySize(): 0) + + (m_rasterizer != null ? m_rasterizer.estimateMemorySize(): 0) + + (m_callback != null ? m_callback.estimateMemorySize(): 0); + } } diff --git a/src/main/java/com/esri/core/geometry/SimpleRasterizer.java b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java index de817443..d91f734f 100644 --- a/src/main/java/com/esri/core/geometry/SimpleRasterizer.java +++ b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java @@ -24,11 +24,14 @@ package com.esri.core.geometry; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; +import static com.esri.core.geometry.SizeOf.SIZE_OF_EDGE; +import static com.esri.core.geometry.SizeOf.SIZE_OF_SIMPLE_RASTERIZER; +import static com.esri.core.geometry.SizeOf.sizeOfIntArray; +import static com.esri.core.geometry.SizeOf.sizeOfObjectArray; + /** * Simple scanline rasterizer. Caller provides a callback to draw pixels to actual surface. * @@ -44,15 +47,22 @@ public class SimpleRasterizer { * Winding fill rule */ public final static int WINDING = 1; - - public static interface ScanCallback { + + public interface ScanCallback { /** * Rasterizer calls this method for each scan it produced * @param scans array of scans. Scans are triplets of numbers. The start X coordinate for the scan (inclusive), * the end X coordinate of the scan (exclusive), the Y coordinate for the scan. * @param scanCount3 The number of initialized elements in the scans array. The scan count is scanCount3 / 3. */ - public abstract void drawScan(int[] scans, int scanCount3); + void drawScan(int[] scans, int scanCount3); + + /** + * Returns an estimate of this object size in bytes. + * + * @return Returns an estimate of this object size in bytes. + */ + long estimateMemorySize(); } public SimpleRasterizer() { @@ -340,17 +350,50 @@ final boolean addSegmentStroke(double x1, double y1, double x2, double y2, doubl } public final ScanCallback getScanCallback() { return callback_; } - - + + public long estimateMemorySize() + { + // callback_ is only a pointer, the actual size is accounted for in the caller of setup() + long size = SIZE_OF_SIMPLE_RASTERIZER + + (activeEdgesTable_ != null ? activeEdgesTable_.estimateMemorySize() : 0) + + (scanBuffer_ != null ? sizeOfIntArray(scanBuffer_.length) : 0); + + if (ySortedEdges_ != null) { + size += sizeOfObjectArray(ySortedEdges_.length); + for (int i = 0; i < ySortedEdges_.length; i++) { + if (ySortedEdges_[i] != null) { + size += ySortedEdges_[i].estimateMemorySize(); + } + } + } + + if (sortBuffer_ != null) { + size += sizeOfObjectArray(sortBuffer_.length); + for (int i = 0; i < sortBuffer_.length; i++) { + if (sortBuffer_[i] != null) { + size += sortBuffer_[i].estimateMemorySize(); + } + } + } + + return size; + } + //PRIVATE - private static class Edge { + static class Edge { long x; long dxdy; int y; int ymax; int dir; Edge next; + + long estimateMemorySize() + { + // next is only a pointer, the actual size is accounted for in SimpleRasterizer#estimateMemorySize + return SIZE_OF_EDGE; + } } private final void advanceAET_() { diff --git a/src/main/java/com/esri/core/geometry/SizeOf.java b/src/main/java/com/esri/core/geometry/SizeOf.java index 31460366..6b097dad 100644 --- a/src/main/java/com/esri/core/geometry/SizeOf.java +++ b/src/main/java/com/esri/core/geometry/SizeOf.java @@ -36,6 +36,8 @@ import static sun.misc.Unsafe.ARRAY_INT_INDEX_SCALE; import static sun.misc.Unsafe.ARRAY_LONG_BASE_OFFSET; import static sun.misc.Unsafe.ARRAY_LONG_INDEX_SCALE; +import static sun.misc.Unsafe.ARRAY_OBJECT_BASE_OFFSET; +import static sun.misc.Unsafe.ARRAY_OBJECT_INDEX_SCALE; import static sun.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET; import static sun.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE; @@ -88,6 +90,22 @@ public final class SizeOf { public static final int SIZE_OF_MAPGEOMETRY = 24; + public static final int SIZE_OF_RASTERIZED_GEOMETRY_2D_IMPL = 112; + + public static final int SIZE_OF_SCAN_CALLBACK_IMPL = 32; + + public static final int SIZE_OF_TRANSFORMATION_2D = 64; + + public static final int SIZE_OF_SIMPLE_RASTERIZER = 64; + + public static final int SIZE_OF_EDGE = 48; + + public static final int SIZE_OF_QUAD_TREE_IMPL = 48; + + public static final int SIZE_OF_DATA = 24; + + public static final int SIZE_OF_STRIDED_INDEX_TYPE_COLLECTION = 48; + public static long sizeOfByteArray(int length) { return ARRAY_BYTE_BASE_OFFSET + (((long) ARRAY_BYTE_INDEX_SCALE) * length); } @@ -116,6 +134,11 @@ public static long sizeOfDoubleArray(int length) { return ARRAY_DOUBLE_BASE_OFFSET + (((long) ARRAY_DOUBLE_INDEX_SCALE) * length); } + public static long sizeOfObjectArray(int length) + { + return ARRAY_OBJECT_BASE_OFFSET + (((long) ARRAY_OBJECT_INDEX_SCALE) * length); + } + private SizeOf() { } } diff --git a/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java b/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java index 8bd607e5..ae1f4dca 100644 --- a/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java +++ b/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java @@ -25,6 +25,10 @@ import java.io.Serializable; +import static com.esri.core.geometry.SizeOf.SIZE_OF_STRIDED_INDEX_TYPE_COLLECTION; +import static com.esri.core.geometry.SizeOf.sizeOfIntArray; +import static com.esri.core.geometry.SizeOf.sizeOfObjectArray; + /** * A collection of strides of Index_type elements. To be used when one needs a * collection of homogeneous elements that contain only integer fields (i.e. @@ -277,4 +281,18 @@ private void grow_(long newsize) { } } } + + public long estimateMemorySize() + { + long size = SIZE_OF_STRIDED_INDEX_TYPE_COLLECTION; + if (m_buffer != null) { + size += sizeOfObjectArray(m_buffer.length); + for (int i = 0; i< m_buffer.length; i++) { + if (m_buffer[i] != null) { + size += sizeOfIntArray(m_buffer[i].length); + } + } + } + return size; + } } diff --git a/src/main/java/com/esri/core/geometry/Transformation2D.java b/src/main/java/com/esri/core/geometry/Transformation2D.java index 99ea7cde..1704628a 100644 --- a/src/main/java/com/esri/core/geometry/Transformation2D.java +++ b/src/main/java/com/esri/core/geometry/Transformation2D.java @@ -24,6 +24,8 @@ package com.esri.core.geometry; +import static com.esri.core.geometry.SizeOf.SIZE_OF_TRANSFORMATION_2D; + /** * The affine transformation class for 2D. * @@ -921,4 +923,8 @@ public void extractScaleTransform(Transformation2D scale, rotateNshearNshift.multiply(this); } + public long estimateMemorySize() + { + return SIZE_OF_TRANSFORMATION_2D; + } } diff --git a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java index ae391d8c..b1b40b22 100644 --- a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java +++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java @@ -24,6 +24,7 @@ package com.esri.core.geometry; +import com.esri.core.geometry.Geometry.GeometryAccelerationDegree; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; import com.esri.core.geometry.ogc.OGCGeometry; import com.esri.core.geometry.ogc.OGCLineString; @@ -66,6 +67,14 @@ public void testInstanceSizes() { assertEquals(getInstanceSize(OGCMultiPolygon.class), SizeOf.SIZE_OF_OGC_MULTI_POLYGON); assertEquals(getInstanceSize(OGCPoint.class), SizeOf.SIZE_OF_OGC_POINT); assertEquals(getInstanceSize(OGCPolygon.class), SizeOf.SIZE_OF_OGC_POLYGON); + assertEquals(getInstanceSize(RasterizedGeometry2DImpl.class), SizeOf.SIZE_OF_RASTERIZED_GEOMETRY_2D_IMPL); + assertEquals(getInstanceSize(RasterizedGeometry2DImpl.ScanCallbackImpl.class), SizeOf.SIZE_OF_SCAN_CALLBACK_IMPL); + assertEquals(getInstanceSize(Transformation2D.class), SizeOf.SIZE_OF_TRANSFORMATION_2D); + assertEquals(getInstanceSize(SimpleRasterizer.class), SizeOf.SIZE_OF_SIMPLE_RASTERIZER); + assertEquals(getInstanceSize(SimpleRasterizer.Edge.class), SizeOf.SIZE_OF_EDGE); + assertEquals(getInstanceSize(QuadTreeImpl.class), SizeOf.SIZE_OF_QUAD_TREE_IMPL); + assertEquals(getInstanceSize(QuadTreeImpl.Data.class), SizeOf.SIZE_OF_DATA); + assertEquals(getInstanceSize(StridedIndexTypeCollection.class), SizeOf.SIZE_OF_STRIDED_INDEX_TYPE_COLLECTION); } private static long getInstanceSize(Class clazz) { @@ -93,7 +102,7 @@ public void testEmptyMultiPoint() { } @Test - public void testLineString() { + public void testAcceleratedGeometry() { testGeometry(parseWkt("LINESTRING (0 1, 2 3, 4 5)")); } @@ -104,7 +113,7 @@ public void testEmptyLineString() { @Test public void testMultiLineString() { - testGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); + testAcceleratedGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); } @Test @@ -114,7 +123,7 @@ public void testEmptyMultiLineString() { @Test public void testPolygon() { - testGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); + testAcceleratedGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); } @Test @@ -124,7 +133,7 @@ public void testEmptyPolygon() { @Test public void testMultiPolygon() { - testGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))")); + testAcceleratedGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))")); } @Test @@ -146,6 +155,36 @@ private void testGeometry(OGCGeometry geometry) { assertTrue(geometry.estimateMemorySize() > 0); } + private void testAcceleratedGeometry(OGCGeometry geometry) { + long initialSize = geometry.estimateMemorySize(); + assertTrue(initialSize > 0); + + Envelope envelope = new Envelope(); + geometry.getEsriGeometry().queryEnvelope(envelope); + + long withEnvelopeSize = geometry.estimateMemorySize(); + assertTrue(withEnvelopeSize > initialSize); + + accelerate(geometry, GeometryAccelerationDegree.enumMild); + long mildAcceleratedSize = geometry.estimateMemorySize(); + assertTrue(mildAcceleratedSize > withEnvelopeSize); + + accelerate(geometry, GeometryAccelerationDegree.enumMedium); + long mediumAcceleratedSize = geometry.estimateMemorySize(); + assertTrue(mediumAcceleratedSize > mildAcceleratedSize); + + accelerate(geometry, GeometryAccelerationDegree.enumHot); + long hotAcceleratedSize = geometry.estimateMemorySize(); + assertTrue(hotAcceleratedSize > mediumAcceleratedSize); + } + + private void accelerate(OGCGeometry geometry, GeometryAccelerationDegree accelerationDegree) + { + Operator relateOperator = OperatorFactoryLocal.getInstance().getOperator(Operator.Type.Relate); + boolean accelerated = relateOperator.accelerateGeometry(geometry.getEsriGeometry(), geometry.getEsriSpatialReference(), accelerationDegree); + assertTrue(accelerated); + } + private static OGCGeometry parseWkt(String wkt) { OGCGeometry geometry = OGCGeometry.fromText(wkt); geometry.setSpatialReference(null); From 937ca24b82ddce87a66948c5e8652ab64a83aa4d Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Fri, 30 Nov 2018 11:11:01 -0800 Subject: [PATCH 44/75] Fix rasterization with degenerate segments (#207) * Fix rasterization with degenerate segments * Change javadoc source version to 1.6 --- .gitignore | 2 + build.xml | 4 +- .../geometry/RasterizedGeometry2DImpl.java | 26 +++--- .../esri/core/geometry/SimpleRasterizer.java | 89 ++++++++++--------- .../esri/core/geometry/TestOGCContains.java | 14 +++ 5 files changed, 77 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index 1e2db53a..4f5d1e04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ bin/ results/ javadoc/ +depfiles/ +DepFiles/ esri-geometry-api.jar .project .classpath diff --git a/build.xml b/build.xml index a2e894a4..49f70b58 100644 --- a/build.xml +++ b/build.xml @@ -86,14 +86,14 @@ - + - + diff --git a/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java b/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java index 6b9a2e4d..c6bf1f8d 100644 --- a/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java +++ b/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java @@ -141,10 +141,6 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer, SegmentIteratorImpl segIter = polyPath.querySegmentIterator(); double strokeHalfWidth = m_transform.transform(tol) + 1.5; - double shortSegment = 0.25; - Point2D vec = new Point2D(); - Point2D vecA = new Point2D(); - Point2D vecB = new Point2D(); Point2D ptStart = new Point2D(); Point2D ptEnd = new Point2D(); @@ -153,6 +149,7 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer, double[] helper_xy_10_elm = new double[10]; Envelope2D segEnv = new Envelope2D(); Point2D ptOld = new Point2D(); + double extraWidth = 0; while (segIter.nextPath()) { boolean hasFan = false; boolean first = true; @@ -170,10 +167,11 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer, if (hasFan) { rasterizer.startAddingEdges(); rasterizer.addSegmentStroke(prev_start.x, prev_start.y, - prev_end.x, prev_end.y, strokeHalfWidth, false, + prev_end.x, prev_end.y, strokeHalfWidth + extraWidth, false, helper_xy_10_elm); rasterizer.renderEdges(SimpleRasterizer.EVEN_ODD); hasFan = false; + extraWidth = 0.0; } first = true; @@ -195,19 +193,26 @@ void strokeDrawPolyPath(SimpleRasterizer rasterizer, rasterizer.startAddingEdges(); hasFan = !rasterizer.addSegmentStroke(prev_start.x, - prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth, + prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth + extraWidth, true, helper_xy_10_elm); rasterizer.renderEdges(SimpleRasterizer.EVEN_ODD); - if (!hasFan) + if (!hasFan) { ptOld.setCoords(prev_end); + extraWidth = 0.0; + } + else { + //track length of skipped segment to add it to the stroke width for the next edge. + extraWidth = Math.max(extraWidth, Point2D.distance(prev_start, prev_end)); + } } if (hasFan) { rasterizer.startAddingEdges(); hasFan = !rasterizer.addSegmentStroke(prev_start.x, - prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth, + prev_start.y, prev_end.x, prev_end.y, strokeHalfWidth + extraWidth, false, helper_xy_10_elm); rasterizer.renderEdges(SimpleRasterizer.EVEN_ODD); + extraWidth = 0.0; } } } @@ -308,12 +313,10 @@ void init(MultiVertexGeometryImpl geom, double toleranceXY, m_transform = new Transformation2D(); m_transform.initializeFromRect(worldEnv, pixEnv);// geom to pixels - Transformation2D identityTransform = new Transformation2D(); - switch (geom.getType().value()) { case Geometry.GeometryType.MultiPoint: callback.setColor(m_rasterizer, 2); - fillPoints(m_rasterizer, (MultiPointImpl) geom, m_stroke_half_width); + fillPoints(m_rasterizer, (MultiPointImpl) geom, m_stroke_half_width); break; case Geometry.GeometryType.Polyline: callback.setColor(m_rasterizer, 2); @@ -545,7 +548,6 @@ public boolean dbgSaveToBitmap(String fileName) { // int32_t* rgb4 = (int32_t*)malloc(biSizeImage); for (int y = 0; y < height; y++) { int scanlineIn = y * ((width * 2 + 31) / 32); - int scanlineOut = offset + width * y; for (int x = 0; x < width; x++) { int res = (m_bitmap[scanlineIn + (x >> 4)] >> ((x & 15) * 2)) & 3; diff --git a/src/main/java/com/esri/core/geometry/SimpleRasterizer.java b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java index d91f734f..a2e9dfa0 100644 --- a/src/main/java/com/esri/core/geometry/SimpleRasterizer.java +++ b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java @@ -305,50 +305,51 @@ public final void fillEnvelope(Envelope2D envIn) { } } - final boolean addSegmentStroke(double x1, double y1, double x2, double y2, double half_width, boolean skip_short, double[] helper_xy_10_elm) - { - double vec_x = x2 - x1; - double vec_y = y2 - y1; - double len = Math.sqrt(vec_x * vec_x + vec_y * vec_y); - if (skip_short && len < 0.5) - return false; - - boolean bshort = len < 0.00001; - if (bshort) - { - len = 0.00001; - vec_x = len; - vec_y = 0.0; - } - - double f = half_width / len; - vec_x *= f; vec_y *= f; - double vecA_x = -vec_y; - double vecA_y = vec_x; - double vecB_x = vec_y; - double vecB_y = -vec_x; - //extend by half width - x1 -= vec_x; - y1 -= vec_y; - x2 += vec_x; - y2 += vec_y; - //create rotated rectangle - double[] fan = helper_xy_10_elm; - assert(fan.length == 10); - fan[0] = x1 + vecA_x; - fan[1] = y1 + vecA_y;//fan[0].add(pt_start, vecA); - fan[2] = x1 + vecB_x; - fan[3] = y1 + vecB_y;//fan[1].add(pt_start, vecB); - fan[4] = x2 + vecB_x; - fan[5] = y2 + vecB_y;//fan[2].add(pt_end, vecB) - fan[6] = x2 + vecA_x; - fan[7] = y2 + vecA_y;//fan[3].add(pt_end, vecA) - fan[8] = fan[0]; - fan[9] = fan[1]; - addRing(fan); - return true; - } - + final boolean addSegmentStroke(double x1, double y1, double x2, double y2, double half_width, boolean skip_short, + double[] helper_xy_10_elm) { + double vec_x = x2 - x1; + double vec_y = y2 - y1; + double sqr_len = vec_x * vec_x + vec_y * vec_y; + if (skip_short && sqr_len < (0.5 * 0.5)) { + return false; + } + + boolean veryShort = !skip_short && (sqr_len < (0.00001 * 0.00001)); + if (veryShort) { + vec_x = half_width + 0.00001; + vec_y = 0.0; + } else { + double f = half_width / Math.sqrt(sqr_len); + vec_x *= f; + vec_y *= f; + } + + double vecA_x = -vec_y; + double vecA_y = vec_x; + double vecB_x = vec_y; + double vecB_y = -vec_x; + // extend by half width + x1 -= vec_x; + y1 -= vec_y; + x2 += vec_x; + y2 += vec_y; + // create rotated rectangle + double[] fan = helper_xy_10_elm; + assert (fan.length == 10); + fan[0] = x1 + vecA_x; + fan[1] = y1 + vecA_y;// fan[0].add(pt_start, vecA); + fan[2] = x1 + vecB_x; + fan[3] = y1 + vecB_y;// fan[1].add(pt_start, vecB); + fan[4] = x2 + vecB_x; + fan[5] = y2 + vecB_y;// fan[2].add(pt_end, vecB) + fan[6] = x2 + vecA_x; + fan[7] = y2 + vecA_y;// fan[3].add(pt_end, vecA) + fan[8] = fan[0]; + fan[9] = fan[1]; + addRing(fan); + return true; + } + public final ScanCallback getScanCallback() { return callback_; } public long estimateMemorySize() diff --git a/src/test/java/com/esri/core/geometry/TestOGCContains.java b/src/test/java/com/esri/core/geometry/TestOGCContains.java index fd2c5116..04a328bf 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCContains.java +++ b/src/test/java/com/esri/core/geometry/TestOGCContains.java @@ -55,6 +55,20 @@ public void testGeometryCollection() { "GEOMETRYCOLLECTION (MULTIPOINT (0 0, 2 1))"); } + @Test + public void testAcceleratedPiP() { + String wkt = "MULTIPOLYGON (((-109.642707 30.5236901, -109.607932 30.5367411, -109.5820257 30.574184, -109.5728286 30.5874766, -109.568679 30.5934741, -109.5538097 30.5918356, -109.553714 30.5918251, -109.553289 30.596034, -109.550951 30.6191889, -109.5474935 30.6221179, -109.541059 30.6275689, -109.5373751 30.6326491, -109.522538 30.6531099, -109.514671 30.6611981, -109.456764 30.6548095, -109.4556456 30.6546861, -109.4536755 30.6544688, -109.4526481 30.6543554, -109.446824 30.6537129, -109.437751 30.6702901, -109.433968 30.6709781, -109.43338 30.6774591, -109.416243 30.7164651, -109.401643 30.7230741, -109.377583 30.7145241, -109.3487939 30.7073896, -109.348594 30.7073401, -109.3483718 30.7073797, -109.3477608 30.7074887, -109.3461903 30.7078834, -109.3451022 30.7081569, -109.3431732 30.7086416, -109.3423301 30.708844, -109.3419714 30.7089301, -109.3416347 30.709011, -109.3325693 30.7111874, -109.3323814 30.7112325, -109.332233 30.7112681, -109.332191 30.7112686, -109.3247809 30.7113581, -109.322215 30.7159391, -109.327776 30.7234381, -109.350134 30.7646001, -109.364505 30.8382481, -109.410211 30.8749199, -109.400048 30.8733419, -109.3847799 30.9652412, -109.3841625 30.9689575, -109.375268 31.0224939, -109.390544 31.0227899, -109.399749 31.0363341, -109.395787 31.0468411, -109.388174 31.0810249, -109.3912446 31.0891966, -109.3913452 31.0894644, -109.392735 31.0931629, -109.4000839 31.0979214, -109.402803 31.0996821, -109.4110458 31.1034586, -109.419153 31.1071729, -109.449782 31.1279489, -109.469654 31.1159979, -109.4734874 31.1131178, -109.473753 31.1129183, -109.4739754 31.1127512, -109.491296 31.0997381, -109.507789 31.0721811, -109.512776 31.0537519, -109.5271478 31.0606861, -109.5313703 31.0627234, -109.540698 31.0672239, -109.5805468 31.0674089, -109.5807399 31.0674209, -109.595423 31.0674779, -109.60347 31.0690241, -109.6048011 31.068808, -109.6050803 31.0687627, -109.6192237 31.0664664, -109.635432 31.0638349, -109.6520068 31.0955326, -109.6522294 31.0959584, -109.652373 31.0962329, -109.657709 31.0959719, -109.718258 31.0930099, -109.821036 31.0915909, -109.8183088 31.0793374, -109.8165128 31.0712679, -109.8140062 31.0600052, -109.8138512 31.0593089, -109.812707 31.0541679, -109.8188146 31.0531909, -109.8215447 31.0527542, -109.8436765 31.0492138, -109.8514316 31.0479733, -109.8620535 31.0462742, -109.8655958 31.0457076, -109.868388 31.0452609, -109.8795483 31.0359656, -109.909274 31.0112075, -109.9210382 31.0014092, -109.9216329 31.0009139, -109.920594 30.994183, -109.9195356 30.9873254, -109.9192113 30.9852243, -109.9186281 30.9814453, -109.917814 30.9761709, -109.933894 30.9748879, -109.94094 30.9768059, -109.944854 30.9719821, -109.950803 30.9702809, -109.954025 30.9652409, -109.9584129 30.9636033, -109.958471 30.9635809, -109.9590542 30.9644372, -109.959896 30.9656733, -109.9604184 30.9664405, -109.9606288 30.9667494, -109.9608462 30.9670686, -109.961225 30.9676249, -109.9611615 30.9702903, -109.9611179 30.9721175, -109.9610885 30.9733488, -109.9610882 30.9733604, -109.9610624 30.9744451, -109.961017 30.9763469, -109.962609 30.9786559, -109.9634437 30.9783167, -110.00172 30.9627641, -110.0021152 30.9627564, -110.0224353 30.9623622, -110.0365868 30.9620877, -110.037493 30.9620701, -110.0374055 30.961663, -110.033653 30.9442059, -110.0215506 30.9492932, -110.0180392 30.9507693, -110.011203 30.9536429, -110.0062891 30.9102124, -110.0058721 30.9065268, -110.004869 30.8976609, -109.996392 30.8957129, -109.985038 30.8870439, -109.969416 30.9006011, -109.967905 30.8687239, -109.903498 30.8447749, -109.882925 30.8458289, -109.865184 30.8206519, -109.86465 30.777698, -109.864515 30.7668429, -109.837007 30.7461781, -109.83453 30.7164469, -109.839017 30.7089009, -109.813394 30.6906529, -109.808694 30.6595701, -109.795334 30.6630041, -109.7943042 30.6427223, -109.7940456 30.6376287, -109.7940391 30.637501, -109.793823 30.6332449, -109.833511 30.6274289, -109.830299 30.6252799, -109.844198 30.6254801, -109.852442 30.6056949, -109.832973 30.6021201, -109.8050409 30.591211, -109.773847 30.5790279, -109.772859 30.5521999, -109.754427 30.5393969, -109.743293 30.5443401, -109.6966136 30.5417334, -109.6648181 30.5399578, -109.6560456 30.5394679, -109.6528439 30.5392912, -109.6504039 30.5391565, -109.6473602 30.5389885, -109.646906 30.5389634, -109.6414545 30.5386625, -109.639708 30.5385661, -109.6397729 30.5382443, -109.642707 30.5236901)))"; + String pointWkt = "POINT (-109.65 31.091666666673)"; + + OGCGeometry polygon = OGCGeometry.fromText(wkt); + OGCGeometry point = OGCGeometry.fromText(pointWkt); + assertTrue(polygon.contains(point)); + + OperatorContains.local() + .accelerateGeometry(polygon.getEsriGeometry(), null, Geometry.GeometryAccelerationDegree.enumMild); + assertTrue(polygon.contains(point));; + } + private void assertContains(String wkt, String otherWkt) { OGCGeometry geometry = OGCGeometry.fromText(wkt); OGCGeometry otherGeometry = OGCGeometry.fromText(otherWkt); From fe623e815bad4fca9db6723bcd8bf0e1cf83e7ef Mon Sep 17 00:00:00 2001 From: Maria Basmanova Date: Mon, 3 Dec 2018 14:53:30 -0500 Subject: [PATCH 45/75] Move ScanCallback#estimateMemorySize to implementation (#209) --- .../com/esri/core/geometry/RasterizedGeometry2DImpl.java | 6 +++++- src/main/java/com/esri/core/geometry/SimpleRasterizer.java | 7 ------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java b/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java index c6bf1f8d..c7def2d4 100644 --- a/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java +++ b/src/main/java/com/esri/core/geometry/RasterizedGeometry2DImpl.java @@ -86,7 +86,11 @@ public void drawScan(int[] scans, int scanCount3) { } } - @Override + /** + * Returns an estimate of this object size in bytes. + * + * @return Returns an estimate of this object size in bytes. + */ public long estimateMemorySize() { return SIZE_OF_SCAN_CALLBACK_IMPL + diff --git a/src/main/java/com/esri/core/geometry/SimpleRasterizer.java b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java index a2e9dfa0..8c6d7e46 100644 --- a/src/main/java/com/esri/core/geometry/SimpleRasterizer.java +++ b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java @@ -56,13 +56,6 @@ public interface ScanCallback { * @param scanCount3 The number of initialized elements in the scans array. The scan count is scanCount3 / 3. */ void drawScan(int[] scans, int scanCount3); - - /** - * Returns an estimate of this object size in bytes. - * - * @return Returns an estimate of this object size in bytes. - */ - long estimateMemorySize(); } public SimpleRasterizer() { From 7e51ba0757719bcf3ac4072da26aa261c8a9484f Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Mon, 3 Dec 2018 12:03:40 -0800 Subject: [PATCH 46/75] Geometry release v2.2.2 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 171fa4c6..01481e54 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 2.2.1 + 2.2.2 ``` diff --git a/pom.xml b/pom.xml index 2815d47f..e5907321 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.1 + 2.2.2 jar Esri Geometry API for Java From 494da8ec953d76e7c6072afbc081abfe48ff07cf Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Thu, 3 Jan 2019 10:10:28 -0800 Subject: [PATCH 47/75] v2.2.3 development & copyright year --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 01481e54..d4ea84c7 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Find a bug or want to request a new feature? Please let us know by submitting a Esri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/esri/contributing) ## Licensing -Copyright 2013-2018 Esri +Copyright 2013-2019 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pom.xml b/pom.xml index e5907321..eec05faa 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.2 + 2.2.3-SNAPSHOT jar Esri Geometry API for Java From 8070e1e24afa22396624e900388f31b7405bab11 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 30 Jul 2019 13:15:05 -0700 Subject: [PATCH 48/75] Fix formatting in OperatorCentroid (#226) * Fix formatting in OperatorCentroid * formatting in the unit test --- .../core/geometry/OperatorCentroid2D.java | 25 +- .../geometry/OperatorCentroid2DLocal.java | 267 +++++++++--------- .../esri/core/geometry/TestOGCCentroid.java | 97 +++---- 3 files changed, 187 insertions(+), 202 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java index f44a21f8..9453053d 100644 --- a/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java +++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java @@ -23,18 +23,15 @@ */ package com.esri.core.geometry; -public abstract class OperatorCentroid2D extends Operator -{ - @Override - public Type getType() - { - return Type.Centroid2D; - } - - public abstract Point2D execute(Geometry geometry, ProgressTracker progressTracker); - - public static OperatorCentroid2D local() - { - return (OperatorCentroid2D) OperatorFactoryLocal.getInstance().getOperator(Type.Centroid2D); - } +public abstract class OperatorCentroid2D extends Operator { + @Override + public Type getType() { + return Type.Centroid2D; + } + + public abstract Point2D execute(Geometry geometry, ProgressTracker progressTracker); + + public static OperatorCentroid2D local() { + return (OperatorCentroid2D) OperatorFactoryLocal.getInstance().getOperator(Type.Centroid2D); + } } diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java index 91b7c948..6a6a7394 100644 --- a/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java @@ -25,140 +25,135 @@ import static java.lang.Math.sqrt; -public class OperatorCentroid2DLocal extends OperatorCentroid2D -{ - @Override - public Point2D execute(Geometry geometry, ProgressTracker progressTracker) - { - if (geometry.isEmpty()) { - return null; - } - - Geometry.Type geometryType = geometry.getType(); - switch (geometryType) { - case Point: - return ((Point) geometry).getXY(); - case Line: - return computeLineCentroid((Line) geometry); - case Envelope: - return ((Envelope) geometry).getCenterXY(); - case MultiPoint: - return computePointsCentroid((MultiPoint) geometry); - case Polyline: - return computePolylineCentroid(((Polyline) geometry)); - case Polygon: - return computePolygonCentroid((Polygon) geometry); - default: - throw new UnsupportedOperationException("Unexpected geometry type: " + geometryType); - } - } - - private static Point2D computeLineCentroid(Line line) - { - return new Point2D((line.getEndX() - line.getStartX()) / 2, (line.getEndY() - line.getStartY()) / 2); - } - - // Points centroid is arithmetic mean of the input points - private static Point2D computePointsCentroid(MultiPoint multiPoint) - { - double xSum = 0; - double ySum = 0; - int pointCount = multiPoint.getPointCount(); - Point2D point2D = new Point2D(); - for (int i = 0; i < pointCount; i++) { - multiPoint.getXY(i, point2D); - xSum += point2D.x; - ySum += point2D.y; - } - return new Point2D(xSum / pointCount, ySum / pointCount); - } - - // Lines centroid is weighted mean of each line segment, weight in terms of line length - private static Point2D computePolylineCentroid(Polyline polyline) - { - double xSum = 0; - double ySum = 0; - double weightSum = 0; - - Point2D startPoint = new Point2D(); - Point2D endPoint = new Point2D(); - for (int i = 0; i < polyline.getPathCount(); i++) { - polyline.getXY(polyline.getPathStart(i), startPoint); - polyline.getXY(polyline.getPathEnd(i) - 1, endPoint); - double dx = endPoint.x - startPoint.x; - double dy = endPoint.y - startPoint.y; - double length = sqrt(dx * dx + dy * dy); - weightSum += length; - xSum += (startPoint.x + endPoint.x) * length / 2; - ySum += (startPoint.y + endPoint.y) * length / 2; - } - return new Point2D(xSum / weightSum, ySum / weightSum); - } - - // Polygon centroid: area weighted average of centroids in case of holes - private static Point2D computePolygonCentroid(Polygon polygon) - { - int pathCount = polygon.getPathCount(); - - if (pathCount == 1) { - return getPolygonSansHolesCentroid(polygon); - } - - double xSum = 0; - double ySum = 0; - double areaSum = 0; - - for (int i = 0; i < pathCount; i++) { - int startIndex = polygon.getPathStart(i); - int endIndex = polygon.getPathEnd(i); - - Polygon sansHoles = getSubPolygon(polygon, startIndex, endIndex); - - Point2D centroid = getPolygonSansHolesCentroid(sansHoles); - double area = sansHoles.calculateArea2D(); - - xSum += centroid.x * area; - ySum += centroid.y * area; - areaSum += area; - } - - return new Point2D(xSum / areaSum, ySum / areaSum); - } - - private static Polygon getSubPolygon(Polygon polygon, int startIndex, int endIndex) - { - Polyline boundary = new Polyline(); - boundary.startPath(polygon.getPoint(startIndex)); - for (int i = startIndex + 1; i < endIndex; i++) { - Point current = polygon.getPoint(i); - boundary.lineTo(current); - } - - final Polygon newPolygon = new Polygon(); - newPolygon.add(boundary, false); - return newPolygon; - } - - // Polygon sans holes centroid: - // c[x] = (Sigma(x[i] + x[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = 0 to N - 1) / (6 * signedArea) - // c[y] = (Sigma(y[i] + y[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = 0 to N - 1) / (6 * signedArea) - private static Point2D getPolygonSansHolesCentroid(Polygon polygon) - { - int pointCount = polygon.getPointCount(); - double xSum = 0; - double ySum = 0; - double signedArea = 0; - - Point2D current = new Point2D(); - Point2D next = new Point2D(); - for (int i = 0; i < pointCount; i++) { - polygon.getXY(i, current); - polygon.getXY((i + 1) % pointCount, next); - double ladder = current.x * next.y - next.x * current.y; - xSum += (current.x + next.x) * ladder; - ySum += (current.y + next.y) * ladder; - signedArea += ladder / 2; - } - return new Point2D(xSum / (signedArea * 6), ySum / (signedArea * 6)); - } +public class OperatorCentroid2DLocal extends OperatorCentroid2D { + @Override + public Point2D execute(Geometry geometry, ProgressTracker progressTracker) { + if (geometry.isEmpty()) { + return null; + } + + Geometry.Type geometryType = geometry.getType(); + switch (geometryType) { + case Point: + return ((Point) geometry).getXY(); + case Line: + return computeLineCentroid((Line) geometry); + case Envelope: + return ((Envelope) geometry).getCenterXY(); + case MultiPoint: + return computePointsCentroid((MultiPoint) geometry); + case Polyline: + return computePolylineCentroid(((Polyline) geometry)); + case Polygon: + return computePolygonCentroid((Polygon) geometry); + default: + throw new UnsupportedOperationException("Unexpected geometry type: " + geometryType); + } + } + + private static Point2D computeLineCentroid(Line line) { + return new Point2D((line.getEndX() - line.getStartX()) / 2, (line.getEndY() - line.getStartY()) / 2); + } + + // Points centroid is arithmetic mean of the input points + private static Point2D computePointsCentroid(MultiPoint multiPoint) { + double xSum = 0; + double ySum = 0; + int pointCount = multiPoint.getPointCount(); + Point2D point2D = new Point2D(); + for (int i = 0; i < pointCount; i++) { + multiPoint.getXY(i, point2D); + xSum += point2D.x; + ySum += point2D.y; + } + return new Point2D(xSum / pointCount, ySum / pointCount); + } + + // Lines centroid is weighted mean of each line segment, weight in terms of line + // length + private static Point2D computePolylineCentroid(Polyline polyline) { + double xSum = 0; + double ySum = 0; + double weightSum = 0; + + Point2D startPoint = new Point2D(); + Point2D endPoint = new Point2D(); + for (int i = 0; i < polyline.getPathCount(); i++) { + polyline.getXY(polyline.getPathStart(i), startPoint); + polyline.getXY(polyline.getPathEnd(i) - 1, endPoint); + double dx = endPoint.x - startPoint.x; + double dy = endPoint.y - startPoint.y; + double length = sqrt(dx * dx + dy * dy); + weightSum += length; + xSum += (startPoint.x + endPoint.x) * length / 2; + ySum += (startPoint.y + endPoint.y) * length / 2; + } + return new Point2D(xSum / weightSum, ySum / weightSum); + } + + // Polygon centroid: area weighted average of centroids in case of holes + private static Point2D computePolygonCentroid(Polygon polygon) { + int pathCount = polygon.getPathCount(); + + if (pathCount == 1) { + return getPolygonSansHolesCentroid(polygon); + } + + double xSum = 0; + double ySum = 0; + double areaSum = 0; + + for (int i = 0; i < pathCount; i++) { + int startIndex = polygon.getPathStart(i); + int endIndex = polygon.getPathEnd(i); + + Polygon sansHoles = getSubPolygon(polygon, startIndex, endIndex); + + Point2D centroid = getPolygonSansHolesCentroid(sansHoles); + double area = sansHoles.calculateArea2D(); + + xSum += centroid.x * area; + ySum += centroid.y * area; + areaSum += area; + } + + return new Point2D(xSum / areaSum, ySum / areaSum); + } + + private static Polygon getSubPolygon(Polygon polygon, int startIndex, int endIndex) { + Polyline boundary = new Polyline(); + boundary.startPath(polygon.getPoint(startIndex)); + for (int i = startIndex + 1; i < endIndex; i++) { + Point current = polygon.getPoint(i); + boundary.lineTo(current); + } + + final Polygon newPolygon = new Polygon(); + newPolygon.add(boundary, false); + return newPolygon; + } + + // Polygon sans holes centroid: + // c[x] = (Sigma(x[i] + x[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = + // 0 to N - 1) / (6 * signedArea) + // c[y] = (Sigma(y[i] + y[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = + // 0 to N - 1) / (6 * signedArea) + private static Point2D getPolygonSansHolesCentroid(Polygon polygon) { + int pointCount = polygon.getPointCount(); + double xSum = 0; + double ySum = 0; + double signedArea = 0; + + Point2D current = new Point2D(); + Point2D next = new Point2D(); + for (int i = 0; i < pointCount; i++) { + polygon.getXY(i, current); + polygon.getXY((i + 1) % pointCount, next); + double ladder = current.x * next.y - next.x * current.y; + xSum += (current.x + next.x) * ladder; + ySum += (current.y + next.y) * ladder; + signedArea += ladder / 2; + } + return new Point2D(xSum / (signedArea * 6), ySum / (signedArea * 6)); + } } diff --git a/src/test/java/com/esri/core/geometry/TestOGCCentroid.java b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java index bf183bb9..d9d39adb 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCCentroid.java +++ b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java @@ -28,63 +28,56 @@ import org.junit.Assert; import org.junit.Test; -public class TestOGCCentroid -{ - @Test - public void testPoint() - { - assertCentroid("POINT (1 2)", new Point(1, 2)); - assertEmptyCentroid("POINT EMPTY"); - } +public class TestOGCCentroid { + @Test + public void testPoint() { + assertCentroid("POINT (1 2)", new Point(1, 2)); + assertEmptyCentroid("POINT EMPTY"); + } - @Test - public void testLineString() - { - assertCentroid("LINESTRING (1 1, 2 2, 3 3)", new Point(2, 2)); - assertEmptyCentroid("LINESTRING EMPTY"); - } + @Test + public void testLineString() { + assertCentroid("LINESTRING (1 1, 2 2, 3 3)", new Point(2, 2)); + assertEmptyCentroid("LINESTRING EMPTY"); + } - @Test - public void testPolygon() - { - assertCentroid("POLYGON ((1 1, 1 4, 4 4, 4 1))'", new Point(2.5, 2.5)); - assertCentroid("POLYGON ((1 1, 5 1, 3 4))", new Point(3, 2)); - assertCentroid("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))", new Point(2.5416666666666665, 2.5416666666666665)); - assertEmptyCentroid("POLYGON EMPTY"); - } + @Test + public void testPolygon() { + assertCentroid("POLYGON ((1 1, 1 4, 4 4, 4 1))'", new Point(2.5, 2.5)); + assertCentroid("POLYGON ((1 1, 5 1, 3 4))", new Point(3, 2)); + assertCentroid("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))", + new Point(2.5416666666666665, 2.5416666666666665)); + assertEmptyCentroid("POLYGON EMPTY"); + } - @Test - public void testMultiPoint() - { - assertCentroid("MULTIPOINT (1 2, 2 4, 3 6, 4 8)", new Point(2.5, 5)); - assertEmptyCentroid("MULTIPOINT EMPTY"); - } + @Test + public void testMultiPoint() { + assertCentroid("MULTIPOINT (1 2, 2 4, 3 6, 4 8)", new Point(2.5, 5)); + assertEmptyCentroid("MULTIPOINT EMPTY"); + } - @Test - public void testMultiLineString() - { - assertCentroid("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", new Point(3, 2)); - assertEmptyCentroid("MULTILINESTRING EMPTY"); - } + @Test + public void testMultiLineString() { + assertCentroid("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", new Point(3, 2)); + assertEmptyCentroid("MULTILINESTRING EMPTY"); + } - @Test - public void testMultiPolygon() - { - assertCentroid("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1)), ((2 4, 2 6, 6 6, 6 4)))", new Point (3.3333333333333335,4)); - assertEmptyCentroid("MULTIPOLYGON EMPTY"); - } + @Test + public void testMultiPolygon() { + assertCentroid("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1)), ((2 4, 2 6, 6 6, 6 4)))", + new Point(3.3333333333333335, 4)); + assertEmptyCentroid("MULTIPOLYGON EMPTY"); + } - private static void assertCentroid(String wkt, Point expectedCentroid) - { - OGCGeometry geometry = OGCGeometry.fromText(wkt); - OGCGeometry centroid = geometry.centroid(); - Assert.assertEquals(centroid, new OGCPoint(expectedCentroid, geometry.getEsriSpatialReference())); - } + private static void assertCentroid(String wkt, Point expectedCentroid) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry centroid = geometry.centroid(); + Assert.assertEquals(centroid, new OGCPoint(expectedCentroid, geometry.getEsriSpatialReference())); + } - private static void assertEmptyCentroid(String wkt) - { - OGCGeometry geometry = OGCGeometry.fromText(wkt); - OGCGeometry centroid = geometry.centroid(); - Assert.assertEquals(centroid, new OGCPoint(new Point(), geometry.getEsriSpatialReference())); - } + private static void assertEmptyCentroid(String wkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry centroid = geometry.centroid(); + Assert.assertEquals(centroid, new OGCPoint(new Point(), geometry.getEsriSpatialReference())); + } } From 8e390b90639bf690550012fe7f4b412f7f7795bd Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Sat, 3 Aug 2019 04:18:19 -0700 Subject: [PATCH 49/75] centroid fixes (#227) --- .gitignore | 2 + .travis.yml | 9 +- pom.xml | 6 +- .../geometry/OperatorCentroid2DLocal.java | 144 +++++------ .../com/esri/core/geometry/TestCentroid.java | 226 +++++++++++------- .../esri/core/geometry/TestOGCCentroid.java | 25 +- 6 files changed, 238 insertions(+), 174 deletions(-) diff --git a/.gitignore b/.gitignore index 4f5d1e04..f2a3f602 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ Thumbs.db target/* /bin/ /target/ + +.metadata/ diff --git a/.travis.yml b/.travis.yml index d1fa4fad..2113e3d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ language: java jdk: - - openjdk7 - - openjdk8 - - oraclejdk8 - - oraclejdk9 + - openjdk9 + - openjdk10 + - openjdk14 +# - oraclejdk9 + - oraclejdk11 notifications: email: false diff --git a/pom.xml b/pom.xml index eec05faa..09ac3899 100755 --- a/pom.xml +++ b/pom.xml @@ -94,8 +94,8 @@ UTF-8 - 1.6 - 1.6 + 1.7 + 1.7 2.9.6 @@ -194,7 +194,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.2 + 1.6.8 true ossrh diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java index 6a6a7394..ce7079b8 100644 --- a/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2019 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,8 +23,6 @@ */ package com.esri.core.geometry; -import static java.lang.Math.sqrt; - public class OperatorCentroid2DLocal extends OperatorCentroid2D { @Override public Point2D execute(Geometry geometry, ProgressTracker progressTracker) { @@ -56,7 +54,7 @@ private static Point2D computeLineCentroid(Line line) { } // Points centroid is arithmetic mean of the input points - private static Point2D computePointsCentroid(MultiPoint multiPoint) { + private static Point2D computePointsCentroid(MultiVertexGeometry multiPoint) { double xSum = 0; double ySum = 0; int pointCount = multiPoint.getPointCount(); @@ -71,89 +69,75 @@ private static Point2D computePointsCentroid(MultiPoint multiPoint) { // Lines centroid is weighted mean of each line segment, weight in terms of line // length - private static Point2D computePolylineCentroid(Polyline polyline) { - double xSum = 0; - double ySum = 0; - double weightSum = 0; - - Point2D startPoint = new Point2D(); - Point2D endPoint = new Point2D(); - for (int i = 0; i < polyline.getPathCount(); i++) { - polyline.getXY(polyline.getPathStart(i), startPoint); - polyline.getXY(polyline.getPathEnd(i) - 1, endPoint); - double dx = endPoint.x - startPoint.x; - double dy = endPoint.y - startPoint.y; - double length = sqrt(dx * dx + dy * dy); - weightSum += length; - xSum += (startPoint.x + endPoint.x) * length / 2; - ySum += (startPoint.y + endPoint.y) * length / 2; - } - return new Point2D(xSum / weightSum, ySum / weightSum); - } - - // Polygon centroid: area weighted average of centroids in case of holes - private static Point2D computePolygonCentroid(Polygon polygon) { - int pathCount = polygon.getPathCount(); - - if (pathCount == 1) { - return getPolygonSansHolesCentroid(polygon); + private static Point2D computePolylineCentroid(MultiPath polyline) { + double totalLength = polyline.calculateLength2D(); + if (totalLength == 0) { + return computePointsCentroid(polyline); } - - double xSum = 0; - double ySum = 0; - double areaSum = 0; - - for (int i = 0; i < pathCount; i++) { - int startIndex = polygon.getPathStart(i); - int endIndex = polygon.getPathEnd(i); - - Polygon sansHoles = getSubPolygon(polygon, startIndex, endIndex); - - Point2D centroid = getPolygonSansHolesCentroid(sansHoles); - double area = sansHoles.calculateArea2D(); - - xSum += centroid.x * area; - ySum += centroid.y * area; - areaSum += area; + + MathUtils.KahanSummator xSum = new MathUtils.KahanSummator(0); + MathUtils.KahanSummator ySum = new MathUtils.KahanSummator(0); + Point2D point = new Point2D(); + SegmentIterator iter = polyline.querySegmentIterator(); + while (iter.nextPath()) { + while (iter.hasNextSegment()) { + Segment seg = iter.nextSegment(); + seg.getCoord2D(0.5, point); + double length = seg.calculateLength2D(); + point.scale(length); + xSum.add(point.x); + ySum.add(point.y); + } } - - return new Point2D(xSum / areaSum, ySum / areaSum); + + return new Point2D(xSum.getResult() / totalLength, ySum.getResult() / totalLength); } - private static Polygon getSubPolygon(Polygon polygon, int startIndex, int endIndex) { - Polyline boundary = new Polyline(); - boundary.startPath(polygon.getPoint(startIndex)); - for (int i = startIndex + 1; i < endIndex; i++) { - Point current = polygon.getPoint(i); - boundary.lineTo(current); + // Polygon centroid: area weighted average of centroids + private static Point2D computePolygonCentroid(Polygon polygon) { + double totalArea = polygon.calculateArea2D(); + if (totalArea == 0) + { + return computePolylineCentroid(polygon); } - - final Polygon newPolygon = new Polygon(); - newPolygon.add(boundary, false); - return newPolygon; - } - - // Polygon sans holes centroid: - // c[x] = (Sigma(x[i] + x[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = - // 0 to N - 1) / (6 * signedArea) - // c[y] = (Sigma(y[i] + y[i + 1]) * (x[i] * y[i + 1] - x[i + 1] * y[i]), for i = - // 0 to N - 1) / (6 * signedArea) - private static Point2D getPolygonSansHolesCentroid(Polygon polygon) { - int pointCount = polygon.getPointCount(); - double xSum = 0; - double ySum = 0; - double signedArea = 0; - + + MathUtils.KahanSummator xSum = new MathUtils.KahanSummator(0); + MathUtils.KahanSummator ySum = new MathUtils.KahanSummator(0); + Point2D startPoint = new Point2D(); Point2D current = new Point2D(); Point2D next = new Point2D(); - for (int i = 0; i < pointCount; i++) { - polygon.getXY(i, current); - polygon.getXY((i + 1) % pointCount, next); - double ladder = current.x * next.y - next.x * current.y; - xSum += (current.x + next.x) * ladder; - ySum += (current.y + next.y) * ladder; - signedArea += ladder / 2; + Point2D origin = polygon.getXY(0); + + for (int ipath = 0, npaths = polygon.getPathCount(); ipath < npaths; ipath++) { + int startIndex = polygon.getPathStart(ipath); + int endIndex = polygon.getPathEnd(ipath); + int pointCount = endIndex - startIndex; + if (pointCount < 3) { + continue; + } + + polygon.getXY(startIndex, startPoint); + polygon.getXY(startIndex + 1, current); + current.sub(startPoint); + for (int i = startIndex + 2, n = endIndex; i < n; i++) { + polygon.getXY(i, next); + next.sub(startPoint); + double twiceTriangleArea = next.x * current.y - current.x * next.y; + xSum.add((current.x + next.x) * twiceTriangleArea); + ySum.add((current.y + next.y) * twiceTriangleArea); + current.setCoords(next); + } + + startPoint.sub(origin); + startPoint.scale(6.0 * polygon.calculateRingArea2D(ipath)); + //add weighted startPoint + xSum.add(startPoint.x); + ySum.add(startPoint.y); } - return new Point2D(xSum / (signedArea * 6), ySum / (signedArea * 6)); + + totalArea *= 6.0; + Point2D res = new Point2D(xSum.getResult() / totalArea, ySum.getResult() / totalArea); + res.add(origin); + return res; } } diff --git a/src/test/java/com/esri/core/geometry/TestCentroid.java b/src/test/java/com/esri/core/geometry/TestCentroid.java index 58c430fb..3065ec9e 100644 --- a/src/test/java/com/esri/core/geometry/TestCentroid.java +++ b/src/test/java/com/esri/core/geometry/TestCentroid.java @@ -26,90 +26,144 @@ import org.junit.Assert; import org.junit.Test; -public class TestCentroid -{ - @Test - public void testPoint() - { - assertCentroid(new Point(1, 2), new Point2D(1, 2)); - } - - @Test - public void testLine() - { - assertCentroid(new Line(0, 0, 10, 20), new Point2D(5, 10)); - } - - @Test - public void testEnvelope() - { - assertCentroid(new Envelope(1, 2, 3,4), new Point2D(2, 3)); - assertCentroid(new Envelope(), null); - } - - @Test - public void testMultiPoint() - { - MultiPoint multiPoint = new MultiPoint(); - multiPoint.add(0, 0); - multiPoint.add(1, 2); - multiPoint.add(3, 1); - multiPoint.add(0, 1); - - assertCentroid(multiPoint, new Point2D(1, 1)); - assertCentroid(new MultiPoint(), null); - } - - @Test - public void testPolyline() - { - Polyline polyline = new Polyline(); - polyline.startPath(0, 0); - polyline.lineTo(1, 2); - polyline.lineTo(3, 4); - assertCentroid(polyline, new Point2D(1.5, 2)); - - polyline.startPath(1, -1); - polyline.lineTo(2, 0); - polyline.lineTo(10, 1); - assertCentroid(polyline, new Point2D(4.093485180902371 , 0.7032574095488145)); - - assertCentroid(new Polyline(), null); - } - - @Test - public void testPolygon() - { - Polygon polygon = new Polygon(); - polygon.startPath(0, 0); - polygon.lineTo(1, 2); - polygon.lineTo(3, 4); - polygon.lineTo(5, 2); - polygon.lineTo(0, 0); - assertCentroid(polygon, new Point2D(2.5, 2)); - - // add a hole - polygon.startPath(2, 2); - polygon.lineTo(2.3, 2); - polygon.lineTo(2.3, 2.4); - polygon.lineTo(2, 2); - assertCentroid(polygon, new Point2D(2.5022670025188916 , 1.9989924433249369)); - - // add another polygon - polygon.startPath(-1, -1); - polygon.lineTo(3, -1); - polygon.lineTo(0.5, -2); - polygon.lineTo(-1, -1); - assertCentroid(polygon, new Point2D(2.166465459423206 , 1.3285043594902748)); - - assertCentroid(new Polygon(), null); - } - - private static void assertCentroid(Geometry geometry, Point2D expectedCentroid) - { - OperatorCentroid2D operator = (OperatorCentroid2D) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.Centroid2D); - - Point2D actualCentroid = operator.execute(geometry, null); - Assert.assertEquals(expectedCentroid, actualCentroid); - } +public class TestCentroid { + @Test + public void testPoint() { + assertCentroid(new Point(1, 2), new Point2D(1, 2)); + } + + @Test + public void testLine() { + assertCentroid(new Line(0, 0, 10, 20), new Point2D(5, 10)); + } + + @Test + public void testEnvelope() { + assertCentroid(new Envelope(1, 2, 3, 4), new Point2D(2, 3)); + assertCentroidEmpty(new Envelope()); + } + + @Test + public void testMultiPoint() { + MultiPoint multiPoint = new MultiPoint(); + multiPoint.add(0, 0); + multiPoint.add(1, 2); + multiPoint.add(3, 1); + multiPoint.add(0, 1); + + assertCentroid(multiPoint, new Point2D(1, 1)); + assertCentroidEmpty(new MultiPoint()); + } + + @Test + public void testPolyline() { + Polyline polyline = new Polyline(); + polyline.startPath(0, 0); + polyline.lineTo(1, 2); + polyline.lineTo(3, 4); + assertCentroid(polyline, new Point2D(1.3377223398316207, 2.1169631197754946)); + + polyline.startPath(1, -1); + polyline.lineTo(2, 0); + polyline.lineTo(10, 1); + assertCentroid(polyline, new Point2D(3.93851092460519, 0.9659173294165462)); + + assertCentroidEmpty(new Polyline()); + } + + @Test + public void testPolygon() { + Polygon polygon = new Polygon(); + polygon.startPath(0, 0); + polygon.lineTo(1, 2); + polygon.lineTo(3, 4); + polygon.lineTo(5, 2); + polygon.lineTo(0, 0); + assertCentroid(polygon, new Point2D(2.5, 2)); + + // add a hole + polygon.startPath(2, 2); + polygon.lineTo(2.3, 2); + polygon.lineTo(2.3, 2.4); + polygon.lineTo(2, 2); + assertCentroid(polygon, new Point2D(2.5022670025188916, 1.9989924433249369)); + + // add another polygon + polygon.startPath(-1, -1); + polygon.lineTo(3, -1); + polygon.lineTo(0.5, -2); + polygon.lineTo(-1, -1); + assertCentroid(polygon, new Point2D(2.166465459423206, 1.3285043594902748)); + + assertCentroidEmpty(new Polygon()); + } + + @Test + public void testSmallPolygon() { + // https://github.com/Esri/geometry-api-java/issues/225 + + Polygon polygon = new Polygon(); + polygon.startPath(153.492818, -28.13729); + polygon.lineTo(153.492821, -28.137291); + polygon.lineTo(153.492816, -28.137289); + polygon.lineTo(153.492818, -28.13729); + + assertCentroid(polygon, new Point2D(153.492818333333333, -28.13729)); + } + + @Test + public void testZeroAreaPolygon() { + Polygon polygon = new Polygon(); + polygon.startPath(153, 28); + polygon.lineTo(163, 28); + polygon.lineTo(153, 28); + + Polyline polyline = (Polyline) polygon.getBoundary(); + Point2D expectedCentroid = new Point2D(158, 28); + + assertCentroid(polyline, expectedCentroid); + assertCentroid(polygon, expectedCentroid); + } + + @Test + public void testDegeneratesToPointPolygon() { + Polygon polygon = new Polygon(); + polygon.startPath(-8406364, 560828); + polygon.lineTo(-8406364, 560828); + polygon.lineTo(-8406364, 560828); + polygon.lineTo(-8406364, 560828); + + assertCentroid(polygon, new Point2D(-8406364, 560828)); + } + + @Test + public void testZeroLengthPolyline() { + Polyline polyline = new Polyline(); + polyline.startPath(153, 28); + polyline.lineTo(153, 28); + + assertCentroid(polyline, new Point2D(153, 28)); + } + + @Test + public void testDegeneratesToPointPolyline() { + Polyline polyline = new Polyline(); + polyline.startPath(-8406364, 560828); + polyline.lineTo(-8406364, 560828); + + assertCentroid(polyline, new Point2D(-8406364, 560828)); + } + + private static void assertCentroid(Geometry geometry, Point2D expectedCentroid) { + + Point2D actualCentroid = OperatorCentroid2D.local().execute(geometry, null); + Assert.assertEquals(expectedCentroid.x, actualCentroid.x, 1e-13); + Assert.assertEquals(expectedCentroid.y, actualCentroid.y, 1e-13); + } + + private static void assertCentroidEmpty(Geometry geometry) { + + Point2D actualCentroid = OperatorCentroid2D.local().execute(geometry, null); + Assert.assertTrue(actualCentroid == null); + } } diff --git a/src/test/java/com/esri/core/geometry/TestOGCCentroid.java b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java index d9d39adb..a64c67b5 100644 --- a/src/test/java/com/esri/core/geometry/TestOGCCentroid.java +++ b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java @@ -38,6 +38,10 @@ public void testPoint() { @Test public void testLineString() { assertCentroid("LINESTRING (1 1, 2 2, 3 3)", new Point(2, 2)); + //closed path + assertCentroid("LINESTRING (0 0, 1 0, 1 1, 0 1, 0 0)", new Point(0.5, 0.5)); + //all points coincide + assertCentroid("LINESTRING (0 0, 0 0, 0 0, 0 0, 0 0)", new Point(0.0, 0.0)); assertEmptyCentroid("LINESTRING EMPTY"); } @@ -59,20 +63,39 @@ public void testMultiPoint() { @Test public void testMultiLineString() { assertCentroid("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", new Point(3, 2)); + assertCentroid("MULTILINESTRING ((1 1, 5 1), (2 4, 3 3, 4 4))')))", new Point(3, 2.0355339059327378)); + assertCentroid("MULTILINESTRING ((0 0, 0 0, 0 0), (1 1, 1 1, 1 1, 1 1))", new Point(0.571428571428571429, 0.571428571428571429)); assertEmptyCentroid("MULTILINESTRING EMPTY"); } @Test public void testMultiPolygon() { + assertCentroid("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((2 2, 3 2, 3 3, 2 3, 2 2)))", new Point(1.5, 1.5)); + assertCentroid("MULTIPOLYGON (((2 2, 3 2, 3 3, 2 3, 2 2)), ((4 4, 5 4, 5 5, 4 5, 4 4)))", new Point(3.5, 3.5)); assertCentroid("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1)), ((2 4, 2 6, 6 6, 6 4)))", new Point(3.3333333333333335, 4)); + + //hole is same as exterior - compute as polyline + assertCentroid("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0), (0 0, 0 1, 1 1, 1 0, 0 0)))", new Point(0.5, 0.5)); + + //polygon is only vertices - compute as multipoint. Note that the closing vertex of the ring is not counted + assertCentroid("MULTIPOLYGON (((0 0, 0 0, 0 0), (1 1, 1 1, 1 1, 1 1)))", new Point(0.6, 0.6)); + + // test cases from https://github.com/Esri/geometry-api-java/issues/225 + assertCentroid( + "MULTIPOLYGON (((153.492818 -28.13729, 153.492821 -28.137291, 153.492816 -28.137289, 153.492818 -28.13729)))", + new Point(153.49281833333333, -28.13729)); + assertCentroid( + "MULTIPOLYGON (((153.112475 -28.360526, 153.1124759 -28.360527, 153.1124759 -28.360526, 153.112475 -28.360526)))", + new Point(153.1124756, -28.360526333333333)); assertEmptyCentroid("MULTIPOLYGON EMPTY"); } private static void assertCentroid(String wkt, Point expectedCentroid) { OGCGeometry geometry = OGCGeometry.fromText(wkt); OGCGeometry centroid = geometry.centroid(); - Assert.assertEquals(centroid, new OGCPoint(expectedCentroid, geometry.getEsriSpatialReference())); + Assert.assertEquals(((OGCPoint)centroid).X(), expectedCentroid.getX(), 1e-13); + Assert.assertEquals(((OGCPoint)centroid).Y(), expectedCentroid.getY(), 1e-13); } private static void assertEmptyCentroid(String wkt) { From 43ece8840f291f6eab8bfd44bbca5480a18d3eae Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 6 Aug 2019 11:23:36 -0700 Subject: [PATCH 50/75] Remove duplicate interface (#237) --- .../com/esri/core/geometry/DirtyFlags.java | 64 --------------- .../com/esri/core/geometry/EditShape.java | 4 +- .../geometry/MultiVertexGeometryImpl.java | 77 +++++++------------ 3 files changed, 28 insertions(+), 117 deletions(-) delete mode 100644 src/main/java/com/esri/core/geometry/DirtyFlags.java diff --git a/src/main/java/com/esri/core/geometry/DirtyFlags.java b/src/main/java/com/esri/core/geometry/DirtyFlags.java deleted file mode 100644 index 36ccafda..00000000 --- a/src/main/java/com/esri/core/geometry/DirtyFlags.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - Copyright 1995-2015 Esri - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - - email: contracts@esri.com - */ -package com.esri.core.geometry; - -interface DirtyFlags { - public static final int dirtyIsKnownSimple = 1; // !<0 when is_weak_simple - // or is_strong_simple flag - // is valid - public static final int isWeakSimple = 2; // ! Date: Tue, 6 Aug 2019 11:24:03 -0700 Subject: [PATCH 51/75] Cleanup unused variables and code and small optimization (#233) --- .../com/esri/core/geometry/Simplificator.java | 410 +++++++----------- 1 file changed, 154 insertions(+), 256 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/Simplificator.java b/src/main/java/com/esri/core/geometry/Simplificator.java index e0401cfa..a5102528 100644 --- a/src/main/java/com/esri/core/geometry/Simplificator.java +++ b/src/main/java/com/esri/core/geometry/Simplificator.java @@ -33,16 +33,16 @@ class Simplificator { private AttributeStreamOfInt32 m_bunchEdgeIndices; // private AttributeStreamOfInt32 m_orphanVertices; - private int m_dbgCounter; private int m_sortedVerticesListIndex; private int m_userIndexSortedIndexToVertex; private int m_userIndexSortedAngleIndexToVertex; private int m_nextVertexToProcess; private int m_firstCoincidentVertex; - private int m_knownSimpleResult; - private boolean m_bWinding; + //private int m_knownSimpleResult; private boolean m_fixSelfTangency; private ProgressTracker m_progressTracker; + private int[] m_ar = null; + private int[] m_br = null; private void _beforeRemoveVertex(int vertex, boolean bChangePathFirst) { int vertexlistIndex = m_shape.getUserIndex(vertex, @@ -91,9 +91,15 @@ private void _beforeRemoveVertex(int vertex, boolean bChangePathFirst) { } } - static class SimplificatorAngleComparer extends + static private class SimplificatorAngleComparer extends AttributeStreamOfInt32.IntComparator { - Simplificator m_parent; + private Simplificator m_parent; + private Point2D pt1 = new Point2D(); + private Point2D pt2 = new Point2D(); + private Point2D pt10 = new Point2D(); + private Point2D pt20 = new Point2D(); + private Point2D v1 = new Point2D(); + private Point2D v2 = new Point2D(); public SimplificatorAngleComparer(Simplificator parent) { m_parent = parent; @@ -101,19 +107,35 @@ public SimplificatorAngleComparer(Simplificator parent) { @Override public int compare(int v1, int v2) { - return m_parent._compareAngles(v1, v2); + return _compareAngles(v1, v2); } + private int _compareAngles(int index1, int index2) { + int vert1 = m_parent.m_bunchEdgeEndPoints.get(index1); + m_parent.m_shape.getXY(vert1, pt1); + int vert2 = m_parent.m_bunchEdgeEndPoints.get(index2); + m_parent.m_shape.getXY(vert2, pt2); + + if (pt1.isEqual(pt2)) + return 0;// overlap case + + int vert10 = m_parent.m_bunchEdgeCenterPoints.get(index1); + m_parent.m_shape.getXY(vert10, pt10); + + int vert20 = m_parent.m_bunchEdgeCenterPoints.get(index2); + m_parent.m_shape.getXY(vert20, pt20); + + v1.sub(pt1, pt10); + v2.sub(pt2, pt20); + int result = Point2D._compareVectors(v1, v2); + return result; + } } private boolean _processBunch() { boolean bModified = false; - int iter = 0; Point2D ptCenter = new Point2D(); while (true) { - m_dbgCounter++;// only for debugging - iter++; - // _ASSERT(iter < 10); if (m_bunchEdgeEndPoints == null) { m_bunchEdgeEndPoints = new AttributeStreamOfInt32(0); m_bunchEdgeCenterPoints = new AttributeStreamOfInt32(0); @@ -129,25 +151,17 @@ private boolean _processBunch() { boolean bFirst = true; while (currentVertex != m_nextVertexToProcess) { int v = m_sortedVertices.getData(currentVertex); - {// debug - Point2D pt = new Point2D(); - m_shape.getXY(v, pt); - double y = pt.x; - } if (bFirst) { m_shape.getXY(v, ptCenter); bFirst = false; } int vertP = m_shape.getPrevVertex(v); int vertN = m_shape.getNextVertex(v); - // _ASSERT(vertP != vertN || m_shape.getPrevVertex(vertN) == v - // && m_shape.getNextVertex(vertP) == v); int id = m_shape.getUserIndex(vertP, m_userIndexSortedAngleIndexToVertex); if (id != 0xdeadbeef)// avoid adding a point twice { - // _ASSERT(id == -1); m_bunchEdgeEndPoints.add(vertP); m_shape.setUserIndex(vertP, m_userIndexSortedAngleIndexToVertex, 0xdeadbeef);// mark @@ -165,7 +179,6 @@ private boolean _processBunch() { m_userIndexSortedAngleIndexToVertex); if (id2 != 0xdeadbeef) // avoid adding a point twice { - // _ASSERT(id2 == -1); m_bunchEdgeEndPoints.add(vertN); m_shape.setUserIndex(vertN, m_userIndexSortedAngleIndexToVertex, 0xdeadbeef);// mark @@ -189,8 +202,6 @@ private boolean _processBunch() { // the edge, connecting the endpoint with the bunch center) m_bunchEdgeIndices.Sort(0, m_bunchEdgeIndices.size(), new SimplificatorAngleComparer(this)); - // SORTDYNAMICARRAYEX(m_bunchEdgeIndices, int, 0, - // m_bunchEdgeIndices.size(), SimplificatorAngleComparer, this); for (int i = 0, n = m_bunchEdgeIndices.size(); i < n; i++) { int indexL = m_bunchEdgeIndices.get(i); @@ -199,11 +210,6 @@ private boolean _processBunch() { m_userIndexSortedAngleIndexToVertex, i);// rember the // sort by angle // order - {// debug - Point2D pt = new Point2D(); - m_shape.getXY(vertex, pt); - double y = pt.x; - } } boolean bCrossOverResolved = _processCrossOvers(ptCenter);// see of @@ -254,7 +260,6 @@ private boolean _processCrossOvers(Point2D ptCenter) { int vertexB1 = m_bunchEdgeEndPoints.get(edgeindex1); int vertexB2 = m_bunchEdgeEndPoints.get(edgeindex2); - // _ASSERT(vertexB2 != vertexB1); int vertexA1 = m_shape.getNextVertex(vertexB1); if (!m_shape.isEqualXY(vertexA1, ptCenter)) @@ -263,9 +268,6 @@ private boolean _processCrossOvers(Point2D ptCenter) { if (!m_shape.isEqualXY(vertexA2, ptCenter)) vertexA2 = m_shape.getPrevVertex(vertexB2); - // _ASSERT(m_shape.isEqualXY(vertexA1, vertexA2)); - // _ASSERT(m_shape.isEqualXY(vertexA1, ptCenter)); - boolean bDirection1 = _getDirection(vertexA1, vertexB1); boolean bDirection2 = _getDirection(vertexA2, vertexB2); int vertexC1 = bDirection1 ? m_shape.getPrevVertex(vertexA1) @@ -331,9 +333,6 @@ else if (_removeSpike(vertexC2)) if (!m_shape.isEqualXY(vertexA2, ptCenter)) vertexA2 = m_shape.getPrevVertex(vertexB2); - // _ASSERT(m_shape.isEqualXY(vertexA1, vertexA2)); - // _ASSERT(m_shape.isEqualXY(vertexA1, ptCenter)); - boolean bDirection1 = _getDirection(vertexA1, vertexB1); boolean bDirection2 = _getDirection(vertexA2, vertexB2); int vertexC1 = bDirection1 ? m_shape.getPrevVertex(vertexA1) @@ -355,9 +354,11 @@ else if (_removeSpike(vertexC2)) return bFound; } - static class SimplificatorVertexComparer extends + static private class SimplificatorVertexComparer extends AttributeStreamOfInt32.IntComparator { - Simplificator m_parent; + private Simplificator m_parent; + private Point2D pt1 = new Point2D(); + private Point2D pt2 = new Point2D(); SimplificatorVertexComparer(Simplificator parent) { m_parent = parent; @@ -365,9 +366,21 @@ static class SimplificatorVertexComparer extends @Override public int compare(int v1, int v2) { - return m_parent._compareVerticesSimple(v1, v2); + return _compareVerticesSimple(v1, v2); } + private int _compareVerticesSimple(int v1, int v2) { + m_parent.m_shape.getXY(v1, pt1); + m_parent.m_shape.getXY(v2, pt2); + int res = pt1.compare(pt2); + if (res == 0) {// sort equal vertices by the path ID + int i1 = m_parent.m_shape.getPathFromVertex(v1); + int i2 = m_parent.m_shape.getPathFromVertex(v2); + res = i1 < i2 ? -1 : (i1 == i2 ? 0 : 1); + } + + return res; + } } private boolean _simplify() { @@ -381,8 +394,6 @@ private boolean _simplify() { assert (m_shape.getFillRule(m_geometry) == Polygon.FillRule.enumFillRuleOddEven); } boolean bChanged = false; - boolean bNeedWindingRepeat = true; - boolean bWinding = false; m_userIndexSortedIndexToVertex = -1; m_userIndexSortedAngleIndexToVertex = -1; @@ -406,8 +417,6 @@ private boolean _simplify() { // Sort verticesSorter.Sort(0, pointCount, new SimplificatorVertexComparer(this)); - // SORTDYNAMICARRAYEX(verticesSorter, int, 0, pointCount, - // SimplificatorVertexComparer, this); // Copy sorted vertices to the m_sortedVertices list. Make a mapping // from the edit shape vertices to the sorted vertices. @@ -424,11 +433,6 @@ private boolean _simplify() { m_sortedVerticesListIndex = m_sortedVertices.createList(0); for (int i = 0; i < pointCount; i++) { int vertex = verticesSorter.get(i); - {// debug - Point2D pt = new Point2D(); - m_shape.getXY(vertex, pt);// for debugging - double y = pt.x; - } int vertexlistIndex = m_sortedVertices.addElement( m_sortedVerticesListIndex, vertex); m_shape.setUserIndex(vertex, m_userIndexSortedIndexToVertex, @@ -452,120 +456,100 @@ private boolean _simplify() { if (_cleanupSpikes())// cleanup any spikes on the polygon. bChanged = true; - // External iteration loop for the simplificator. - // ST. I am not sure if it actually needs this loop. TODO: figure this - // out. - while (bNeedWindingRepeat) { - bNeedWindingRepeat = false; + // Simplify polygon + int iRepeatNum = 0; + boolean bNeedRepeat = false; - int max_iter = m_shape.getPointCount(m_geometry) + 10 > 30 ? 1000 - : (m_shape.getPointCount(m_geometry) + 10) - * (m_shape.getPointCount(m_geometry) + 10); - - // Simplify polygon - int iRepeatNum = 0; - boolean bNeedRepeat = false; - - // Internal iteration loop for the simplificator. - // ST. I am not sure if it actually needs this loop. TODO: figure - // this out. - do// while (bNeedRepeat); - { - bNeedRepeat = false; - - boolean bVertexRecheck = false; - m_firstCoincidentVertex = -1; - int coincidentCount = 0; - Point2D ptFirst = new Point2D(); - Point2D pt = new Point2D(); - // Main loop of the simplificator. Go through the vertices and - // for those that have same coordinates, - for (int vlistindex = m_sortedVertices - .getFirst(m_sortedVerticesListIndex); vlistindex != IndexMultiDCList - .nullNode();) { - int vertex = m_sortedVertices.getData(vlistindex); - {// debug - // Point2D pt = new Point2D(); - m_shape.getXY(vertex, pt); - double d = pt.x; - } - - if (m_firstCoincidentVertex != -1) { - // Point2D pt = new Point2D(); - m_shape.getXY(vertex, pt); - if (ptFirst.isEqual(pt)) { - coincidentCount++; - } else { - ptFirst.setCoords(pt); - m_nextVertexToProcess = vlistindex;// we remeber the - // next index in - // the member - // variable to - // allow it to - // be updated if - // a vertex is - // removed - // inside of the - // _ProcessBunch. - if (coincidentCount > 0) { - boolean result = _processBunch();// process a - // bunch of - // coinciding - // vertices - if (result) {// something has changed. - // Note that ProcessBunch may - // change m_nextVertexToProcess - // and m_firstCoincidentVertex. - bNeedRepeat = true; - if (m_nextVertexToProcess != IndexMultiDCList - .nullNode()) { - int v = m_sortedVertices - .getData(m_nextVertexToProcess); - m_shape.getXY(v, ptFirst); - } + // Internal iteration loop for the simplificator. + // ST. I am not sure if it actually needs this loop. TODO: figure + // this out. + do// while (bNeedRepeat); + { + bNeedRepeat = false; + + m_firstCoincidentVertex = -1; + int coincidentCount = 0; + Point2D ptFirst = new Point2D(); + Point2D pt = new Point2D(); + // Main loop of the simplificator. Go through the vertices and + // for those that have same coordinates, + for (int vlistindex = m_sortedVertices + .getFirst(m_sortedVerticesListIndex); vlistindex != IndexMultiDCList + .nullNode();) { + int vertex = m_sortedVertices.getData(vlistindex); + + if (m_firstCoincidentVertex != -1) { + // Point2D pt = new Point2D(); + m_shape.getXY(vertex, pt); + if (ptFirst.isEqual(pt)) { + coincidentCount++; + } else { + ptFirst.setCoords(pt); + m_nextVertexToProcess = vlistindex;// we remeber the + // next index in + // the member + // variable to + // allow it to + // be updated if + // a vertex is + // removed + // inside of the + // _ProcessBunch. + if (coincidentCount > 0) { + boolean result = _processBunch();// process a + // bunch of + // coinciding + // vertices + if (result) {// something has changed. + // Note that ProcessBunch may + // change m_nextVertexToProcess + // and m_firstCoincidentVertex. + bNeedRepeat = true; + if (m_nextVertexToProcess != IndexMultiDCList + .nullNode()) { + int v = m_sortedVertices + .getData(m_nextVertexToProcess); + m_shape.getXY(v, ptFirst); } } - - vlistindex = m_nextVertexToProcess; - m_firstCoincidentVertex = vlistindex; - coincidentCount = 0; } - } else { + + vlistindex = m_nextVertexToProcess; m_firstCoincidentVertex = vlistindex; - m_shape.getXY(m_sortedVertices.getData(vlistindex), - ptFirst); coincidentCount = 0; } - - if (vlistindex != -1)//vlistindex can be set to -1 after ProcessBunch call above - vlistindex = m_sortedVertices.getNext(vlistindex); - } - - m_nextVertexToProcess = -1; - - if (coincidentCount > 0) { - boolean result = _processBunch(); - if (result) - bNeedRepeat = true; + } else { + m_firstCoincidentVertex = vlistindex; + m_shape.getXY(m_sortedVertices.getData(vlistindex), + ptFirst); + coincidentCount = 0; } - if (iRepeatNum++ > 10) { - throw GeometryException.GeometryInternalError(); - } + if (vlistindex != -1)//vlistindex can be set to -1 after ProcessBunch call above + vlistindex = m_sortedVertices.getNext(vlistindex); + } - if (bNeedRepeat) - _fixOrphanVertices();// fix broken structure of the shape + m_nextVertexToProcess = -1; - if (_cleanupSpikes()) + if (coincidentCount > 0) { + boolean result = _processBunch(); + if (result) bNeedRepeat = true; + } + + if (iRepeatNum++ > 10) { + throw GeometryException.GeometryInternalError(); + } - bNeedWindingRepeat |= bNeedRepeat && bWinding; + if (bNeedRepeat) + _fixOrphanVertices();// fix broken structure of the shape - bChanged |= bNeedRepeat; + if (_cleanupSpikes()) + bNeedRepeat = true; - } while (bNeedRepeat); + bChanged |= bNeedRepeat; - }// while (bNeedWindingRepeat) + } while (bNeedRepeat); // Now process rings. Fix ring orientation and determine rings that need // to be deleted. @@ -581,11 +565,8 @@ private boolean _simplify() { private boolean _getDirection(int vert1, int vert2) { if (m_shape.getNextVertex(vert2) == vert1) { - // _ASSERT(m_shape.getPrevVertex(vert1) == vert2); return false; } else { - // _ASSERT(m_shape.getPrevVertex(vert2) == vert1); - // _ASSERT(m_shape.getNextVertex(vert1) == vert2); return true; } } @@ -593,8 +574,6 @@ private boolean _getDirection(int vert1, int vert2) { private boolean _detectAndResolveCrossOver(boolean bDirection1, boolean bDirection2, int vertexB1, int vertexA1, int vertexC1, int vertexB2, int vertexA2, int vertexC2) { - // _ASSERT(!m_shape.isEqualXY(vertexB1, vertexB2)); - // _ASSERT(!m_shape.isEqualXY(vertexC1, vertexC2)); if (vertexA1 == vertexA2) { _removeAngleSortInfo(vertexB1); @@ -602,17 +581,6 @@ private boolean _detectAndResolveCrossOver(boolean bDirection1, return false; } - // _ASSERT(!m_shape.isEqualXY(vertexB1, vertexC2)); - // _ASSERT(!m_shape.isEqualXY(vertexB1, vertexC1)); - // _ASSERT(!m_shape.isEqualXY(vertexB2, vertexC2)); - // _ASSERT(!m_shape.isEqualXY(vertexB2, vertexC1)); - // _ASSERT(!m_shape.isEqualXY(vertexA1, vertexB1)); - // _ASSERT(!m_shape.isEqualXY(vertexA1, vertexC1)); - // _ASSERT(!m_shape.isEqualXY(vertexA2, vertexB2)); - // _ASSERT(!m_shape.isEqualXY(vertexA2, vertexC2)); - - // _ASSERT(m_shape.isEqualXY(vertexA1, vertexA2)); - // get indices of the vertices for the angle sort. int iB1 = m_shape.getUserIndex(vertexB1, m_userIndexSortedAngleIndexToVertex); @@ -622,44 +590,42 @@ private boolean _detectAndResolveCrossOver(boolean bDirection1, m_userIndexSortedAngleIndexToVertex); int iC2 = m_shape.getUserIndex(vertexC2, m_userIndexSortedAngleIndexToVertex); - // _ASSERT(iB1 >= 0); - // _ASSERT(iC1 >= 0); - // _ASSERT(iB2 >= 0); - // _ASSERT(iC2 >= 0); // Sort the indices to restore the angle-sort order - int[] ar = new int[8]; - int[] br = new int[4]; - - ar[0] = 0; - br[0] = iB1; - ar[1] = 0; - br[1] = iC1; - ar[2] = 1; - br[2] = iB2; - ar[3] = 1; - br[3] = iC2; + + if (m_ar == null) { + m_ar = new int[8]; + m_br = new int[4]; + } + m_ar[0] = 0; + m_br[0] = iB1; + m_ar[1] = 0; + m_br[1] = iC1; + m_ar[2] = 1; + m_br[2] = iB2; + m_ar[3] = 1; + m_br[3] = iC2; for (int j = 1; j < 4; j++)// insertion sort { - int key = br[j]; - int data = ar[j]; + int key = m_br[j]; + int data = m_ar[j]; int i = j - 1; - while (i >= 0 && br[i] > key) { - br[i + 1] = br[i]; - ar[i + 1] = ar[i]; + while (i >= 0 && m_br[i] > key) { + m_br[i + 1] = m_br[i]; + m_ar[i + 1] = m_ar[i]; i--; } - br[i + 1] = key; - ar[i + 1] = data; + m_br[i + 1] = key; + m_ar[i + 1] = data; } int detector = 0; - if (ar[0] != 0) + if (m_ar[0] != 0) detector |= 1; - if (ar[1] != 0) + if (m_ar[1] != 0) detector |= 2; - if (ar[2] != 0) + if (m_ar[2] != 0) detector |= 4; - if (ar[3] != 0) + if (m_ar[3] != 0) detector |= 8; if (detector != 5 && detector != 10)// not an overlap return false; @@ -701,19 +667,8 @@ private boolean _detectAndResolveCrossOver(boolean bDirection1, private void _resolveOverlap(boolean bDirection1, boolean bDirection2, int vertexA1, int vertexB1, int vertexA2, int vertexB2) { - if (m_bWinding) { - _resolveOverlapWinding(bDirection1, bDirection2, vertexA1, - vertexB1, vertexA2, vertexB2); - } else { - _resolveOverlapOddEven(bDirection1, bDirection2, vertexA1, - vertexB1, vertexA2, vertexB2); - } - } - - private void _resolveOverlapWinding(boolean bDirection1, - boolean bDirection2, int vertexA1, int vertexB1, int vertexA2, - int vertexB2) { - throw new GeometryException("not implemented."); + _resolveOverlapOddEven(bDirection1, bDirection2, vertexA1, + vertexB1, vertexA2, vertexB2); } private void _resolveOverlapOddEven(boolean bDirection1, @@ -721,8 +676,6 @@ private void _resolveOverlapOddEven(boolean bDirection1, int vertexB2) { if (bDirection1 != bDirection2) { if (bDirection1) { - // _ASSERT(m_shape.getNextVertex(vertexA1) == vertexB1); - // _ASSERT(m_shape.getNextVertex(vertexB2) == vertexA2); m_shape.setNextVertex_(vertexA1, vertexA2); // B1< B2 m_shape.setPrevVertex_(vertexA2, vertexA1); // | | m_shape.setNextVertex_(vertexB2, vertexB1); // | | @@ -753,15 +706,6 @@ private void _resolveOverlapOddEven(boolean bDirection1, } } else// bDirection1 == bDirection2 { - if (!bDirection1) { - // _ASSERT(m_shape.getNextVertex(vertexB1) == vertexA1); - // _ASSERT(m_shape.getNextVertex(vertexB2) == vertexA2); - } else { - // _ASSERT(m_shape.getNextVertex(vertexA1) == vertexB1); - // _ASSERT(m_shape.getNextVertex(vertexA2) == vertexB2); - } - - // if (m_shape._RingParentageCheckInternal(vertexA1, vertexA2)) { int a1 = bDirection1 ? vertexA1 : vertexB1; int a2 = bDirection2 ? vertexA2 : vertexB2; @@ -861,7 +805,6 @@ private boolean _removeSpike(int vertexIn) { // m_shape.dbgVerifyIntegrity(vertex);//debug int vertex = vertexIn; - // _ASSERT(m_shape.isEqualXY(m_shape.getNextVertex(vertex), // m_shape.getPrevVertex(vertex))); boolean bFound = false; while (true) { @@ -984,61 +927,16 @@ private void _removeAngleSortInfo(int vertex) { } protected Simplificator() { - m_dbgCounter = 0; } public static boolean execute(EditShape shape, int geometry, int knownSimpleResult, boolean fixSelfTangency, ProgressTracker progressTracker) { Simplificator simplificator = new Simplificator(); simplificator.m_shape = shape; - // simplificator.m_bWinding = bWinding; simplificator.m_geometry = geometry; - simplificator.m_knownSimpleResult = knownSimpleResult; + //simplificator.m_knownSimpleResult = knownSimpleResult; simplificator.m_fixSelfTangency = fixSelfTangency; simplificator.m_progressTracker = progressTracker; return simplificator._simplify(); } - - int _compareVerticesSimple(int v1, int v2) { - Point2D pt1 = new Point2D(); - m_shape.getXY(v1, pt1); - Point2D pt2 = new Point2D(); - m_shape.getXY(v2, pt2); - int res = pt1.compare(pt2); - if (res == 0) {// sort equal vertices by the path ID - int i1 = m_shape.getPathFromVertex(v1); - int i2 = m_shape.getPathFromVertex(v2); - res = i1 < i2 ? -1 : (i1 == i2 ? 0 : 1); - } - - return res; - } - - int _compareAngles(int index1, int index2) { - int vert1 = m_bunchEdgeEndPoints.get(index1); - Point2D pt1 = new Point2D(); - m_shape.getXY(vert1, pt1); - Point2D pt2 = new Point2D(); - int vert2 = m_bunchEdgeEndPoints.get(index2); - m_shape.getXY(vert2, pt2); - - if (pt1.isEqual(pt2)) - return 0;// overlap case - - int vert10 = m_bunchEdgeCenterPoints.get(index1); - Point2D pt10 = new Point2D(); - m_shape.getXY(vert10, pt10); - - int vert20 = m_bunchEdgeCenterPoints.get(index2); - Point2D pt20 = new Point2D(); - m_shape.getXY(vert20, pt20); - // _ASSERT(pt10.isEqual(pt20)); - - Point2D v1 = new Point2D(); - v1.sub(pt1, pt10); - Point2D v2 = new Point2D(); - v2.sub(pt2, pt20); - int result = Point2D._compareVectors(v1, v2); - return result; - } } From 48b9cbbce57d47cd354d60a8b8ef60288f25bdb4 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 6 Aug 2019 11:26:15 -0700 Subject: [PATCH 52/75] Fix unused variables and a typo (#231) --- .../core/geometry/RelationalOperations.java | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/RelationalOperations.java b/src/main/java/com/esri/core/geometry/RelationalOperations.java index 0b73561a..abf03372 100644 --- a/src/main/java/com/esri/core/geometry/RelationalOperations.java +++ b/src/main/java/com/esri/core/geometry/RelationalOperations.java @@ -4142,9 +4142,6 @@ private static boolean linearPathIntersectsMultiPoint_( SegmentIteratorImpl segIterA = ((MultiPathImpl) multipathA._getImpl()) .querySegmentIterator(); - boolean bContained = true; - boolean bInteriorHitFound = false; - Envelope2D env_a = new Envelope2D(); Envelope2D env_b = new Envelope2D(); Envelope2D envInter = new Envelope2D(); @@ -4152,10 +4149,6 @@ private static boolean linearPathIntersectsMultiPoint_( multipoint_b.queryEnvelope2D(env_b); env_a.inflate(tolerance, tolerance); - if (!env_a.contains(env_b)) { - bContained = false; - } - env_b.inflate(tolerance, tolerance); envInter.setCoords(env_a); envInter.intersect(env_b); @@ -4169,6 +4162,7 @@ private static boolean linearPathIntersectsMultiPoint_( if (accel != null) { quadTreeA = accel.getQuadTree(); + quadTreePathsA = accel.getQuadTreeForPaths(); if (quadTreeA == null) { qtA = InternalUtils.buildQuadTree( (MultiPathImpl) multipathA._getImpl(), envInter); @@ -4187,7 +4181,6 @@ private static boolean linearPathIntersectsMultiPoint_( qtIterPathsA = quadTreePathsA.getIterator(); Point2D ptB = new Point2D(), closest = new Point2D(); - boolean b_intersects = false; double toleranceSq = tolerance * tolerance; for (int i = 0; i < multipoint_b.getPointCount(); i++) { @@ -5153,9 +5146,9 @@ private static final class OverlapEvent { double m_scalar_a_0; double m_scalar_a_1; int m_ivertex_b; - int m_ipath_b; - double m_scalar_b_0; - double m_scalar_b_1; +// int m_ipath_b; +// double m_scalar_b_0; +// double m_scalar_b_1; static OverlapEvent construct(int ivertex_a, int ipath_a, double scalar_a_0, double scalar_a_1, int ivertex_b, @@ -5166,9 +5159,9 @@ static OverlapEvent construct(int ivertex_a, int ipath_a, overlapEvent.m_scalar_a_0 = scalar_a_0; overlapEvent.m_scalar_a_1 = scalar_a_1; overlapEvent.m_ivertex_b = ivertex_b; - overlapEvent.m_ipath_b = ipath_b; - overlapEvent.m_scalar_b_0 = scalar_b_0; - overlapEvent.m_scalar_b_1 = scalar_b_1; +// overlapEvent.m_ipath_b = ipath_b; +// overlapEvent.m_scalar_b_0 = scalar_b_0; +// overlapEvent.m_scalar_b_1 = scalar_b_1; return overlapEvent; } } From 7812fd39290efdb19202b19f1d2f8924e2c9ecb7 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Thu, 15 Aug 2019 11:46:37 -0700 Subject: [PATCH 53/75] Don't return null buffer polygon (#243) --- .../java/com/esri/core/geometry/Bufferer.java | 10 +++++++- .../com/esri/core/geometry/TestBuffer.java | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/esri/core/geometry/Bufferer.java b/src/main/java/com/esri/core/geometry/Bufferer.java index 7578a76c..f098e7e9 100755 --- a/src/main/java/com/esri/core/geometry/Bufferer.java +++ b/src/main/java/com/esri/core/geometry/Bufferer.java @@ -576,6 +576,9 @@ private Geometry bufferPolygon_() { generateCircleTemplate_(); m_geometry = simplify.execute(m_geometry, null, false, m_progress_tracker); + if(m_geometry.isEmpty()) { + return m_geometry; + } if (m_distance < 0) { Polygon poly = (Polygon) (m_geometry); @@ -600,7 +603,12 @@ private Geometry bufferPolygon_() { .getInstance().getOperator(Operator.Type.Union)).execute( cursor, m_spatialReference, m_progress_tracker); Geometry result = union_cursor.next(); - return result; + if (result != null) { + return result; + } else { + //never return empty. + return new Polygon(m_geometry.getDescription()); + } } } diff --git a/src/test/java/com/esri/core/geometry/TestBuffer.java b/src/test/java/com/esri/core/geometry/TestBuffer.java index 341751f5..e60145bb 100755 --- a/src/test/java/com/esri/core/geometry/TestBuffer.java +++ b/src/test/java/com/esri/core/geometry/TestBuffer.java @@ -27,6 +27,8 @@ import junit.framework.TestCase; import org.junit.Test; +import com.esri.core.geometry.ogc.OGCGeometry; + public class TestBuffer extends TestCase { @Override protected void setUp() throws Exception { @@ -389,4 +391,27 @@ public void testBufferPolygon() { assertTrue(simplify.isSimpleAsFeature(result, sr, null)); } } + + @Test + public static void testTinyBufferOfPoint() { + { + Geometry result1 = OperatorBuffer.local().execute(new Point(0, 0), SpatialReference.create(4326), 1e-9, null); + assertTrue(result1 != null); + assertTrue(result1.isEmpty()); + Geometry geom1 = OperatorImportFromWkt.local().execute(0, Geometry.Type.Unknown, "POLYGON ((177.0 64.0, 177.0000000001 64.0, 177.0000000001 64.0000000001, 177.0 64.0000000001, 177.0 64.0))", null); + Geometry result2 = OperatorBuffer.local().execute(geom1, SpatialReference.create(4326), 0.01, null); + assertTrue(result2 != null); + assertTrue(result2.isEmpty()); + + } + + { + OGCGeometry p = OGCGeometry.fromText( + "POLYGON ((177.0 64.0, 177.0000000001 64.0, 177.0000000001 64.0000000001, 177.0 64.0000000001, 177.0 64.0))"); + OGCGeometry buffered = p.buffer(0.01); + assertTrue(buffered != null); + } + + + } } From 4205cd15ac9b453b905df9663520e379b59e81f7 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Mon, 19 Aug 2019 11:33:50 -0700 Subject: [PATCH 54/75] Fix hash calculation in few cases, change Point internals to be more compact (#238) --- .../core/geometry/AttributeStreamOfDbl.java | 2 +- .../java/com/esri/core/geometry/Envelope.java | 44 +-- .../com/esri/core/geometry/Envelope1D.java | 8 +- .../com/esri/core/geometry/Envelope2D.java | 25 +- .../com/esri/core/geometry/Envelope3D.java | 16 + .../java/com/esri/core/geometry/Line.java | 5 + .../geometry/MultiVertexGeometryImpl.java | 7 - .../com/esri/core/geometry/NumberUtils.java | 13 + .../java/com/esri/core/geometry/Point.java | 314 ++++++++---------- .../java/com/esri/core/geometry/Point2D.java | 11 +- .../java/com/esri/core/geometry/Point3D.java | 27 ++ .../java/com/esri/core/geometry/Segment.java | 19 +- .../java/com/esri/core/geometry/SizeOf.java | 2 +- .../com/esri/core/geometry/TestEnvelope.java | 73 ++-- .../com/esri/core/geometry/TestPoint.java | 28 +- 15 files changed, 333 insertions(+), 261 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java index 75d45a76..889121d2 100644 --- a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java +++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java @@ -352,7 +352,7 @@ public boolean equals(AttributeStreamBase other, int start, int end) { end = size; for (int i = start; i < end; i++) - if (read(i) != _other.read(i)) + if (!NumberUtils.isEqualNonIEEE(read(i), _other.read(i))) return false; return true; diff --git a/src/main/java/com/esri/core/geometry/Envelope.java b/src/main/java/com/esri/core/geometry/Envelope.java index 98c46738..c254df1c 100644 --- a/src/main/java/com/esri/core/geometry/Envelope.java +++ b/src/main/java/com/esri/core/geometry/Envelope.java @@ -70,16 +70,20 @@ public Envelope(Envelope2D env2D) { public Envelope(VertexDescription vd) { if (vd == null) throw new IllegalArgumentException(); + m_description = vd; m_envelope.setEmpty(); + _ensureAttributes(); } public Envelope(VertexDescription vd, Envelope2D env2D) { if (vd == null) throw new IllegalArgumentException(); + m_description = vd; m_envelope.setCoords(env2D); m_envelope.normalize(); + _ensureAttributes(); } /** @@ -331,8 +335,8 @@ void _setFromPoint(Point centerPoint, double width, double height) { } void _setFromPoint(Point centerPoint) { - m_envelope.setCoords(centerPoint.m_attributes[0], - centerPoint.m_attributes[1]); + mergeVertexDescription(centerPoint.getDescription()); + m_envelope.setCoords(centerPoint.getX(), centerPoint.getY()); VertexDescription pointVD = centerPoint.m_description; for (int iattrib = 1, nattrib = pointVD.getAttributeCount(); iattrib < nattrib; iattrib++) { int semantics = pointVD._getSemanticsImpl(iattrib); @@ -610,7 +614,6 @@ int getEndPointOffset(VertexDescription descr, int end_point) { throw new IllegalArgumentException(); int attribute_index = m_description.getAttributeIndex(semantics); - _ensureAttributes(); if (attribute_index >= 0) { return m_attributes[getEndPointOffset(m_description, end_point) + m_description.getPointAttributeOffset_(attribute_index) @@ -645,7 +648,6 @@ void setAttributeAsDblImpl_(int end_point, int semantics, int ordinate, throw new IllegalArgumentException(); addAttribute(semantics); - _ensureAttributes(); int attribute_index = m_description.getAttributeIndex(semantics); m_attributes[getEndPointOffset(m_description, end_point) + m_description.getPointAttributeOffset_(attribute_index) - 2 @@ -655,32 +657,17 @@ void setAttributeAsDblImpl_(int end_point, int semantics, int ordinate, void _ensureAttributes() { _touch(); if (m_attributes == null && m_description.getTotalComponentCount() > 2) { - m_attributes = new double[(m_description.getTotalComponentCount() - 2) * 2]; + int halfLength = m_description.getTotalComponentCount() - 2; + m_attributes = new double[halfLength * 2]; int offset0 = _getEndPointOffset(m_description, 0); int offset1 = _getEndPointOffset(m_description, 1); - - int j = 0; - for (int i = 1, n = m_description.getAttributeCount(); i < n; i++) { - int semantics = m_description.getSemantics(i); - int nords = VertexDescription.getComponentCount(semantics); - double d = VertexDescription.getDefaultValue(semantics); - for (int ord = 0; ord < nords; ord++) - { - m_attributes[offset0 + j] = d; - m_attributes[offset1 + j] = d; - j++; - } - } + System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, offset0, halfLength); + System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, offset1, halfLength); } } @Override protected void _assignVertexDescriptionImpl(VertexDescription newDescription) { - if (m_attributes == null) { - m_description = newDescription; - return; - } - if (newDescription.getTotalComponentCount() > 2) { int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(newDescription, m_description); @@ -734,8 +721,6 @@ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) { throw new GeometryException( "This operation was performed on an Empty Geometry."); - // _ASSERT(endPoint == 0 || endPoint == 1); - if (semantics == Semantics.POSITION) { if (endPoint != 0) { return ordinate != 0 ? m_envelope.ymax : m_envelope.xmax; @@ -750,7 +735,6 @@ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) { int attributeIndex = m_description.getAttributeIndex(semantics); if (attributeIndex >= 0) { - _ensureAttributes(); return m_attributes[_getEndPointOffset(m_description, endPoint) + m_description._getPointAttributeOffset(attributeIndex) - 2 + ordinate]; @@ -784,14 +768,10 @@ void _setAttributeAsDbl(int endPoint, int semantics, int ordinate, throw new IndexOutOfBoundsException(); if (!hasAttribute(semantics)) { - if (VertexDescription.isDefaultValue(semantics, value)) - return; - addAttribute(semantics); } int attributeIndex = m_description.getAttributeIndex(semantics); - _ensureAttributes(); m_attributes[_getEndPointOffset(m_description, endPoint) + m_description._getPointAttributeOffset(attributeIndex) - 2 + ordinate] = value; @@ -1015,7 +995,7 @@ public boolean equals(Object _other) { return false; for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++) - if (m_attributes[i] != other.m_attributes[i]) + if (!NumberUtils.isEqualNonIEEE(m_attributes[i], other.m_attributes[i])) return false; return true; @@ -1030,7 +1010,7 @@ public boolean equals(Object _other) { public int hashCode() { int hashCode = m_description.hashCode(); hashCode = NumberUtils.hash(hashCode, m_envelope.hashCode()); - if (!isEmpty() && m_attributes != null) { + if (!isEmpty()) { for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++) { hashCode = NumberUtils.hash(hashCode, m_attributes[i]); } diff --git a/src/main/java/com/esri/core/geometry/Envelope1D.java b/src/main/java/com/esri/core/geometry/Envelope1D.java index c9d0d259..e000ef0a 100644 --- a/src/main/java/com/esri/core/geometry/Envelope1D.java +++ b/src/main/java/com/esri/core/geometry/Envelope1D.java @@ -225,7 +225,13 @@ public boolean equals(Object _other) @Override public int hashCode() { - return NumberUtils.hash(NumberUtils.hash(vmin), vmax); + if (isEmpty()) { + return NumberUtils.hash(NumberUtils.TheNaN); + } + + int hash = NumberUtils.hash(vmin); + hash = NumberUtils.hash(hash, vmax); + return hash; } } diff --git a/src/main/java/com/esri/core/geometry/Envelope2D.java b/src/main/java/com/esri/core/geometry/Envelope2D.java index 79433dd7..5c8bebf5 100644 --- a/src/main/java/com/esri/core/geometry/Envelope2D.java +++ b/src/main/java/com/esri/core/geometry/Envelope2D.java @@ -699,23 +699,14 @@ public boolean equals(Object _other) { @Override public int hashCode() { - - long bits = Double.doubleToLongBits(xmin); - int hc = (int) (bits ^ (bits >>> 32)); - - int hash = NumberUtils.hash(hc); - - bits = Double.doubleToLongBits(xmax); - hc = (int) (bits ^ (bits >>> 32)); - hash = NumberUtils.hash(hash, hc); - - bits = Double.doubleToLongBits(ymin); - hc = (int) (bits ^ (bits >>> 32)); - hash = NumberUtils.hash(hash, hc); - - bits = Double.doubleToLongBits(ymax); - hc = (int) (bits ^ (bits >>> 32)); - hash = NumberUtils.hash(hash, hc); + if (isEmpty()) { + return NumberUtils.hash(NumberUtils.TheNaN); + } + + int hash = NumberUtils.hash(xmin); + hash = NumberUtils.hash(hash, xmax); + hash = NumberUtils.hash(hash, ymin); + hash = NumberUtils.hash(hash, ymax); return hash; } diff --git a/src/main/java/com/esri/core/geometry/Envelope3D.java b/src/main/java/com/esri/core/geometry/Envelope3D.java index 3f64b053..6fa8b522 100644 --- a/src/main/java/com/esri/core/geometry/Envelope3D.java +++ b/src/main/java/com/esri/core/geometry/Envelope3D.java @@ -320,6 +320,22 @@ public boolean equals(Object _other) { return true; } + + @Override + public int hashCode() { + if (isEmpty()) { + return NumberUtils.hash(NumberUtils.TheNaN); + } + + int hash = NumberUtils.hash(xmin); + hash = NumberUtils.hash(hash, xmax); + hash = NumberUtils.hash(hash, ymin); + hash = NumberUtils.hash(hash, ymax); + hash = NumberUtils.hash(hash, zmin); + hash = NumberUtils.hash(hash, zmax); + return hash; + } + public void construct(Envelope1D xinterval, Envelope1D yinterval, Envelope1D zinterval) { if (xinterval.isEmpty() || yinterval.isEmpty()) { diff --git a/src/main/java/com/esri/core/geometry/Line.java b/src/main/java/com/esri/core/geometry/Line.java index 90b08561..ce7b7b23 100644 --- a/src/main/java/com/esri/core/geometry/Line.java +++ b/src/main/java/com/esri/core/geometry/Line.java @@ -548,6 +548,11 @@ public boolean equals(Object other) { return _equalsImpl((Segment)other); } + @Override + public int hashCode() { + return super.hashCode(); + } + boolean equals(Line other) { if (other == this) return true; diff --git a/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java b/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java index 6e847943..e045aa2a 100644 --- a/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java @@ -168,8 +168,6 @@ public void getPointByVal(int index, Point dst) { Point outPoint = dst; outPoint.assignVertexDescription(m_description); - if (outPoint.isEmpty()) - outPoint._setToDefault(); for (int attributeIndex = 0; attributeIndex < m_description .getAttributeCount(); attributeIndex++) { @@ -933,9 +931,6 @@ void _interpolateTwoVertices(int vertex1, int vertex2, double f, _verifyAllStreams(); outPoint.assignVertexDescription(m_description); - if (outPoint.isEmpty()) - outPoint._setToDefault(); - for (int attributeIndex = 0; attributeIndex < m_description .getAttributeCount(); attributeIndex++) { int semantics = m_description._getSemanticsImpl(attributeIndex); @@ -966,8 +961,6 @@ public Point getPoint(int index) { Point outPoint = new Point(); outPoint.assignVertexDescription(m_description); - if (outPoint.isEmpty()) - outPoint._setToDefault(); for (int attributeIndex = 0; attributeIndex < m_description .getAttributeCount(); attributeIndex++) { diff --git a/src/main/java/com/esri/core/geometry/NumberUtils.java b/src/main/java/com/esri/core/geometry/NumberUtils.java index 4ee00a1e..01b6fd92 100644 --- a/src/main/java/com/esri/core/geometry/NumberUtils.java +++ b/src/main/java/com/esri/core/geometry/NumberUtils.java @@ -136,5 +136,18 @@ static int nextRand(int prevRand) { return (1103515245 * prevRand + 12345) & intMax(); // according to Wiki, // this is gcc's } + + /** + * Returns true if two values are equal (also can compare inf and nan). + */ + static boolean isEqualNonIEEE(double a, double b) { + return a == b || (Double.isNaN(a) && Double.isNaN(b)); + } + /** + * Returns true if two values are equal (also can compare inf and nan). + */ + static boolean isEqualNonIEEE(double a, double b, double tolerance) { + return a == b || Math.abs(a - b) <= tolerance || (Double.isNaN(a) && Double.isNaN(b)); + } } diff --git a/src/main/java/com/esri/core/geometry/Point.java b/src/main/java/com/esri/core/geometry/Point.java index a421400f..cc5b7042 100644 --- a/src/main/java/com/esri/core/geometry/Point.java +++ b/src/main/java/com/esri/core/geometry/Point.java @@ -39,19 +39,24 @@ public class Point extends Geometry implements Serializable { //We are using writeReplace instead. //private static final long serialVersionUID = 2L; - double[] m_attributes; // use doubles to store everything (long are bitcast) + private double m_x; + private double m_y; + private double[] m_attributes; // use doubles to store everything (long are bitcast) /** * Creates an empty 2D point. */ public Point() { m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D(); + m_x = NumberUtils.TheNaN; + m_y = NumberUtils.TheNaN; } public Point(VertexDescription vd) { if (vd == null) throw new IllegalArgumentException(); m_description = vd; + _setToDefault(); } /** @@ -68,6 +73,7 @@ public Point(double x, double y) { m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D(); setXY(x, y); } + public Point(Point2D pt) { m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D(); setXY(pt); @@ -91,19 +97,14 @@ public Point(double x, double y, double z) { Point3D pt = new Point3D(); pt.setCoords(x, y, z); setXYZ(pt); - } /** * Returns XY coordinates of this point. */ public final Point2D getXY() { - if (isEmptyImpl()) - throw new GeometryException( - "This operation should not be performed on an empty geometry."); - Point2D pt = new Point2D(); - pt.setCoords(m_attributes[0], m_attributes[1]); + pt.setCoords(m_x, m_y); return pt; } @@ -111,11 +112,7 @@ public final Point2D getXY() { * Returns XY coordinates of this point. */ public final void getXY(Point2D pt) { - if (isEmptyImpl()) - throw new GeometryException( - "This operation should not be performed on an empty geometry."); - - pt.setCoords(m_attributes[0], m_attributes[1]); + pt.setCoords(m_x, m_y); } /** @@ -131,17 +128,10 @@ public final void setXY(Point2D pt) { * Returns XYZ coordinates of the point. Z will be set to 0 if Z is missing. */ public Point3D getXYZ() { - if (isEmptyImpl()) - throw new GeometryException( - "This operation should not be performed on an empty geometry."); - Point3D pt = new Point3D(); - pt.x = m_attributes[0]; - pt.y = m_attributes[1]; - if (m_description.hasZ()) - pt.z = m_attributes[2]; - else - pt.z = VertexDescription.getDefaultValue(Semantics.Z); + pt.x = m_x; + pt.y = m_y; + pt.z = hasZ() ? m_attributes[0] : VertexDescription.getDefaultValue(VertexDescription.Semantics.Z); return pt; } @@ -154,39 +144,17 @@ public Point3D getXYZ() { */ public void setXYZ(Point3D pt) { _touch(); - boolean bHasZ = hasAttribute(Semantics.Z); - if (!bHasZ && !VertexDescription.isDefaultValue(Semantics.Z, pt.z)) {// add - // Z - // only - // if - // pt.z - // is - // not - // a - // default - // value. - addAttribute(Semantics.Z); - bHasZ = true; - } - - if (m_attributes == null) - _setToDefault(); - - m_attributes[0] = pt.x; - m_attributes[1] = pt.y; - if (bHasZ) - m_attributes[2] = pt.z; + addAttribute(Semantics.Z); + m_x = pt.x; + m_y = pt.y; + m_attributes[0] = pt.z; } /** * Returns the X coordinate of the point. */ public final double getX() { - if (isEmptyImpl()) - throw new GeometryException( - "This operation should not be performed on an empty geometry."); - - return m_attributes[0]; + return m_x; } /** @@ -196,18 +164,14 @@ public final double getX() { * The X coordinate to be set for this point. */ public void setX(double x) { - setAttribute(Semantics.POSITION, 0, x); + m_x = x; } /** * Returns the Y coordinate of this point. */ public final double getY() { - if (isEmptyImpl()) - throw new GeometryException( - "This operation should not be performed on an empty geometry."); - - return m_attributes[1]; + return m_y; } /** @@ -217,14 +181,14 @@ public final double getY() { * The Y coordinate to be set for this point. */ public void setY(double y) { - setAttribute(Semantics.POSITION, 1, y); + m_y = y; } /** * Returns the Z coordinate of this point. */ public double getZ() { - return getAttributeAsDbl(Semantics.Z, 0); + return hasZ() ? m_attributes[0] : VertexDescription.getDefaultValue(VertexDescription.Semantics.Z); } /** @@ -282,10 +246,18 @@ public void setID(int id) { * @return The ordinate as double value. */ public double getAttributeAsDbl(int semantics, int ordinate) { - if (isEmptyImpl()) - throw new GeometryException( - "This operation was performed on an Empty Geometry."); - + if (semantics == VertexDescription.Semantics.POSITION) { + if (ordinate == 0) { + return m_x; + } + else if (ordinate == 1) { + return m_y; + } + else { + throw new IndexOutOfBoundsException(); + } + } + int ncomps = VertexDescription.getComponentCount(semantics); if (ordinate >= ncomps) throw new IndexOutOfBoundsException(); @@ -293,7 +265,7 @@ public double getAttributeAsDbl(int semantics, int ordinate) { int attributeIndex = m_description.getAttributeIndex(semantics); if (attributeIndex >= 0) return m_attributes[m_description - ._getPointAttributeOffset(attributeIndex) + ordinate]; + ._getPointAttributeOffset(attributeIndex) - 2 + ordinate]; else return VertexDescription.getDefaultValue(semantics); } @@ -310,20 +282,7 @@ public double getAttributeAsDbl(int semantics, int ordinate) { * @return The ordinate value truncated to a 32 bit integer value. */ public int getAttributeAsInt(int semantics, int ordinate) { - if (isEmptyImpl()) - throw new GeometryException( - "This operation was performed on an Empty Geometry."); - - int ncomps = VertexDescription.getComponentCount(semantics); - if (ordinate >= ncomps) - throw new IndexOutOfBoundsException(); - - int attributeIndex = m_description.getAttributeIndex(semantics); - if (attributeIndex >= 0) - return (int) m_attributes[m_description - ._getPointAttributeOffset(attributeIndex) + ordinate]; - else - return (int) VertexDescription.getDefaultValue(semantics); + return (int)getAttributeAsDbl(semantics, ordinate); } /** @@ -340,6 +299,19 @@ public int getAttributeAsInt(int semantics, int ordinate) { */ public void setAttribute(int semantics, int ordinate, double value) { _touch(); + if (semantics == VertexDescription.Semantics.POSITION) { + if (ordinate == 0) { + m_x = value; + } + else if (ordinate == 1) { + m_y = value; + } + else { + throw new IndexOutOfBoundsException(); + } + return; + } + int ncomps = VertexDescription.getComponentCount(semantics); if (ncomps < ordinate) throw new IndexOutOfBoundsException(); @@ -350,10 +322,7 @@ public void setAttribute(int semantics, int ordinate, double value) { attributeIndex = m_description.getAttributeIndex(semantics); } - if (m_attributes == null) - _setToDefault(); - - m_attributes[m_description._getPointAttributeOffset(attributeIndex) + m_attributes[m_description._getPointAttributeOffset(attributeIndex) - 2 + ordinate] = value; } @@ -380,62 +349,70 @@ public long estimateMemorySize() @Override public void setEmpty() { _touch(); - if (m_attributes != null) { - m_attributes[0] = NumberUtils.NaN(); - m_attributes[1] = NumberUtils.NaN(); - } + _setToDefault(); } @Override protected void _assignVertexDescriptionImpl(VertexDescription newDescription) { - if (m_attributes == null) { - m_description = newDescription; - return; - } - int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(newDescription, m_description); - double[] newAttributes = new double[newDescription.getTotalComponentCount()]; - - int j = 0; - for (int i = 0, n = newDescription.getAttributeCount(); i < n; i++) { - int semantics = newDescription.getSemantics(i); - int nords = VertexDescription.getComponentCount(semantics); - if (mapping[i] == -1) - { - double d = VertexDescription.getDefaultValue(semantics); - for (int ord = 0; ord < nords; ord++) + int newLen = newDescription.getTotalComponentCount() - 2; + if (newLen > 0) { + double[] newAttributes = new double[newLen]; + + int j = 0; + for (int i = 1, n = newDescription.getAttributeCount(); i < n; i++) { + int semantics = newDescription.getSemantics(i); + int nords = VertexDescription.getComponentCount(semantics); + if (mapping[i] == -1) { - newAttributes[j] = d; - j++; + double d = VertexDescription.getDefaultValue(semantics); + for (int ord = 0; ord < nords; ord++) + { + newAttributes[j] = d; + j++; + } } - } - else { - int m = mapping[i]; - int offset = m_description._getPointAttributeOffset(m); - for (int ord = 0; ord < nords; ord++) - { - newAttributes[j] = m_attributes[offset]; - j++; - offset++; + else { + int m = mapping[i]; + int offset = m_description._getPointAttributeOffset(m) - 2; + for (int ord = 0; ord < nords; ord++) + { + newAttributes[j] = m_attributes[offset]; + j++; + offset++; + } } + } - + + m_attributes = newAttributes; } - - m_attributes = newAttributes; + else { + m_attributes = null; + } + m_description = newDescription; } /** - * Sets the Point to a default, non-empty state. + * Sets to a default empty state. */ - void _setToDefault() { - resizeAttributes(m_description.getTotalComponentCount()); - Point.attributeCopy(m_description._getDefaultPointAttributes(), - m_attributes, m_description.getTotalComponentCount()); - m_attributes[0] = NumberUtils.NaN(); - m_attributes[1] = NumberUtils.NaN(); + private void _setToDefault() { + int len = m_description.getTotalComponentCount() - 2; + if (len != 0) { + if (m_attributes == null || m_attributes.length != len) { + m_attributes = new double[len]; + } + + System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, 0, len); + } + else { + m_attributes = null; + } + + m_x = NumberUtils.TheNaN; + m_y = NumberUtils.TheNaN; } @Override @@ -449,7 +426,7 @@ public void applyTransformation(Transformation2D transform) { } @Override - void applyTransformation(Transformation3D transform) { + public void applyTransformation(Transformation3D transform) { if (isEmptyImpl()) return; @@ -462,20 +439,27 @@ void applyTransformation(Transformation3D transform) { public void copyTo(Geometry dst) { if (dst.getType() != Type.Point) throw new IllegalArgumentException(); - - Point pointDst = (Point) dst; + + if (this == dst) + return; + dst._touch(); - if (m_attributes == null) { - pointDst.setEmpty(); + Point pointDst = (Point) dst; + dst.m_description = m_description; + pointDst.m_x = m_x; + pointDst.m_y = m_y; + int attrLen = m_description.getTotalComponentCount() - 2; + if (attrLen == 0) { pointDst.m_attributes = null; - pointDst.assignVertexDescription(m_description); - } else { - pointDst.assignVertexDescription(m_description); - pointDst.resizeAttributes(m_description.getTotalComponentCount()); - attributeCopy(m_attributes, pointDst.m_attributes, - m_description.getTotalComponentCount()); + return; + } + + if (pointDst.m_attributes == null || pointDst.m_attributes.length != attrLen) { + pointDst.m_attributes = new double[attrLen]; } + + System.arraycopy(m_attributes, 0, pointDst.m_attributes, 0, attrLen); } @Override @@ -490,30 +474,29 @@ public boolean isEmpty() { } final boolean isEmptyImpl() { - return ((m_attributes == null) || NumberUtils.isNaN(m_attributes[0]) || NumberUtils - .isNaN(m_attributes[1])); + return NumberUtils.isNaN(m_x) || NumberUtils.isNaN(m_y); } @Override public void queryEnvelope(Envelope env) { - env.setEmpty(); if (m_description != env.m_description) env.assignVertexDescription(m_description); + + env.setEmpty(); env.merge(this); } @Override public void queryEnvelope2D(Envelope2D env) { - if (isEmptyImpl()) { env.setEmpty(); return; } - env.xmin = m_attributes[0]; - env.ymin = m_attributes[1]; - env.xmax = m_attributes[0]; - env.ymax = m_attributes[1]; + env.xmin = m_x; + env.ymin = m_y; + env.xmax = m_x; + env.ymax = m_y; } @Override @@ -523,13 +506,13 @@ void queryEnvelope3D(Envelope3D env) { return; } - Point3D pt = getXYZ(); - env.xmin = pt.x; - env.ymin = pt.y; - env.zmin = pt.z; - env.xmax = pt.x; - env.ymax = pt.y; - env.zmax = pt.z; + env.xmin = m_x; + env.ymin = m_y; + env.xmax = m_x; + env.ymax = m_y; + double z = getZ(); + env.zmin = z; + env.zmax = z; } @Override @@ -546,21 +529,6 @@ public Envelope1D queryInterval(int semantics, int ordinate) { return env; } - private void resizeAttributes(int newSize) { - if (m_attributes == null) { - m_attributes = new double[newSize]; - } else if (m_attributes.length < newSize) { - double[] newbuffer = new double[newSize]; - System.arraycopy(m_attributes, 0, newbuffer, 0, m_attributes.length); - m_attributes = newbuffer; - } - } - - static void attributeCopy(double[] src, double[] dst, int count) { - if (count > 0) - System.arraycopy(src, 0, dst, 0, count); - } - /** * Set the X and Y coordinate of the point. * @@ -572,11 +540,8 @@ static void attributeCopy(double[] src, double[] dst, int count) { public void setXY(double x, double y) { _touch(); - if (m_attributes == null) - _setToDefault(); - - m_attributes[0] = x; - m_attributes[1] = y; + m_x = x; + m_y = y; } /** @@ -596,15 +561,21 @@ public boolean equals(Object _other) { if (m_description != otherPt.m_description) return false; - if (isEmptyImpl()) + if (isEmptyImpl()) { if (otherPt.isEmptyImpl()) return true; else return false; + } + + if (m_x != otherPt.m_x || m_y != otherPt.m_y) { + return false; + } - for (int i = 0, n = m_description.getTotalComponentCount(); i < n; i++) - if (m_attributes[i] != otherPt.m_attributes[i]) + for (int i = 0, n = m_description.getTotalComponentCount() - 2; i < n; i++) { + if (!NumberUtils.isEqualNonIEEE(m_attributes[i], otherPt.m_attributes[i])) return false; + } return true; } @@ -617,12 +588,15 @@ public boolean equals(Object _other) { public int hashCode() { int hashCode = m_description.hashCode(); if (!isEmptyImpl()) { - for (int i = 0, n = m_description.getTotalComponentCount(); i < n; i++) { + hashCode = NumberUtils.hash(hashCode, m_x); + hashCode = NumberUtils.hash(hashCode, m_y); + for (int i = 0, n = m_description.getTotalComponentCount() - 2; i < n; i++) { long bits = Double.doubleToLongBits(m_attributes[i]); int hc = (int) (bits ^ (bits >>> 32)); hashCode = NumberUtils.hash(hashCode, hc); } } + return hashCode; } diff --git a/src/main/java/com/esri/core/geometry/Point2D.java b/src/main/java/com/esri/core/geometry/Point2D.java index 90cc1e46..95a46c66 100644 --- a/src/main/java/com/esri/core/geometry/Point2D.java +++ b/src/main/java/com/esri/core/geometry/Point2D.java @@ -94,6 +94,12 @@ public boolean equals(Object other) { return x == v.x && y == v.y; } + + @Override + public int hashCode() { + return NumberUtils.hash(NumberUtils.hash(x), y); + } + public void sub(Point2D other) { x -= other.x; @@ -751,11 +757,6 @@ static Point2D calculateCircleCenterFromThreePoints(Point2D from, Point2D mid_po } } - @Override - public int hashCode() { - return NumberUtils.hash(NumberUtils.hash(x), y); - } - double getAxis(int ordinate) { assert(ordinate == 0 || ordinate == 1); return (ordinate == 0 ? x : y); diff --git a/src/main/java/com/esri/core/geometry/Point3D.java b/src/main/java/com/esri/core/geometry/Point3D.java index 849b00e1..71cbfdba 100644 --- a/src/main/java/com/esri/core/geometry/Point3D.java +++ b/src/main/java/com/esri/core/geometry/Point3D.java @@ -132,4 +132,31 @@ boolean _isNan() { return NumberUtils.isNaN(x) || NumberUtils.isNaN(y) || NumberUtils.isNaN(z); } + public boolean equals(Point3D other) { + //note that for nan value this returns false. + //this is by design for this class. + return x == other.x && y == other.y && z == other.z; + } + + @Override + public boolean equals(Object other_) { + if (other_ == this) + return true; + + if (!(other_ instanceof Point3D)) + return false; + + Point3D other = (Point3D)other_; + //note that for nan value this returns false. + //this is by design for this class. + return x == other.x && y == other.y && z == other.z; + } + + @Override + public int hashCode() { + int hash = NumberUtils.hash(x); + hash = NumberUtils.hash(hash, y); + hash = NumberUtils.hash(hash, z); + return hash; + } } diff --git a/src/main/java/com/esri/core/geometry/Segment.java b/src/main/java/com/esri/core/geometry/Segment.java index ca2ea184..b15364a2 100644 --- a/src/main/java/com/esri/core/geometry/Segment.java +++ b/src/main/java/com/esri/core/geometry/Segment.java @@ -528,9 +528,6 @@ private void _get(int endPoint, Point outPoint) { outPoint.assignVertexDescription(m_description); - if (outPoint.isEmptyImpl()) - outPoint._setToDefault(); - for (int attributeIndex = 0; attributeIndex < m_description .getAttributeCount(); attributeIndex++) { int semantics = m_description._getSemanticsImpl(attributeIndex); @@ -689,12 +686,26 @@ boolean _equalsImpl(Segment other) { || m_yStart != other.m_yStart || m_yEnd != other.m_yEnd) return false; for (int i = 0; i < (m_description.getTotalComponentCount() - 2) * 2; i++) - if (m_attributes[i] != other.m_attributes[i]) + if (!NumberUtils.isEqualNonIEEE(m_attributes[i], other.m_attributes[i])) return false; return true; } + @Override + public int hashCode() { + int hash = m_description.hashCode(); + hash = NumberUtils.hash(hash, m_xStart); + hash = NumberUtils.hash(hash, m_yStart); + hash = NumberUtils.hash(hash, m_xEnd); + hash = NumberUtils.hash(hash, m_yEnd); + for (int i = 0; i < (m_description.getTotalComponentCount() - 2) * 2; i++) { + hash = NumberUtils.hash(hash, m_attributes[i]); + } + + return hash; + } + /** * Returns true, when this segment is a closed curve (start point is equal * to end point exactly). diff --git a/src/main/java/com/esri/core/geometry/SizeOf.java b/src/main/java/com/esri/core/geometry/SizeOf.java index 6b097dad..8d9f4c77 100644 --- a/src/main/java/com/esri/core/geometry/SizeOf.java +++ b/src/main/java/com/esri/core/geometry/SizeOf.java @@ -68,7 +68,7 @@ public final class SizeOf { public static final int SIZE_OF_MULTI_POINT_IMPL = 56; - public static final int SIZE_OF_POINT = 24; + public static final int SIZE_OF_POINT = 40; public static final int SIZE_OF_POLYGON = 24; diff --git a/src/test/java/com/esri/core/geometry/TestEnvelope.java b/src/test/java/com/esri/core/geometry/TestEnvelope.java index 56edd466..6b5622e8 100644 --- a/src/test/java/com/esri/core/geometry/TestEnvelope.java +++ b/src/test/java/com/esri/core/geometry/TestEnvelope.java @@ -21,29 +21,58 @@ public class TestEnvelope { - @Test - public void testIntersect() - { - assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5)); - assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(1, 1, 6, 6), new Envelope(1, 1, 5, 5)); - assertIntersection(new Envelope(1, 2, 3, 4), new Envelope(0, 0, 2, 3), new Envelope(1, 2, 2, 3)); + @Test + public void testIntersect() { + assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5)); + assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(1, 1, 6, 6), new Envelope(1, 1, 5, 5)); + assertIntersection(new Envelope(1, 2, 3, 4), new Envelope(0, 0, 2, 3), new Envelope(1, 2, 2, 3)); - assertNoIntersection(new Envelope(), new Envelope()); - assertNoIntersection(new Envelope(0, 0, 5, 5), new Envelope()); - assertNoIntersection(new Envelope(), new Envelope(0, 0, 5, 5)); - } + assertNoIntersection(new Envelope(), new Envelope()); + assertNoIntersection(new Envelope(0, 0, 5, 5), new Envelope()); + assertNoIntersection(new Envelope(), new Envelope(0, 0, 5, 5)); + } - private static void assertIntersection(Envelope envelope, Envelope other, Envelope intersection) - { - boolean intersects = envelope.intersect(other); - assertTrue(intersects); - assertEquals(envelope, intersection); - } + @Test + public void testEquals() { + Envelope env1 = new Envelope(10, 9, 11, 12); + Envelope env2 = new Envelope(10, 9, 11, 13); + Envelope1D emptyInterval = new Envelope1D(); + emptyInterval.setEmpty(); + assertFalse(env1.equals(env2)); + env1.queryInterval(VertexDescription.Semantics.M, 0).equals(emptyInterval); + env2.setCoords(10, 9, 11, 12); + assertTrue(env1.equals(env2)); + env1.addAttribute(VertexDescription.Semantics.M); + env1.queryInterval(VertexDescription.Semantics.M, 0).equals(emptyInterval); + assertFalse(env1.equals(env2)); + env2.addAttribute(VertexDescription.Semantics.M); + assertTrue(env1.equals(env2)); + Envelope1D nonEmptyInterval = new Envelope1D(); + nonEmptyInterval.setCoords(1, 2); + env1.setInterval(VertexDescription.Semantics.M, 0, emptyInterval); + assertTrue(env1.equals(env2)); + env2.setInterval(VertexDescription.Semantics.M, 0, emptyInterval); + assertTrue(env1.equals(env2)); + env2.setInterval(VertexDescription.Semantics.M, 0, nonEmptyInterval); + assertFalse(env1.equals(env2)); + env1.setInterval(VertexDescription.Semantics.M, 0, nonEmptyInterval); + assertTrue(env1.equals(env2)); + env1.queryInterval(VertexDescription.Semantics.M, 0).equals(nonEmptyInterval); + env1.queryInterval(VertexDescription.Semantics.POSITION, 0).equals(new Envelope1D(10, 11)); + env1.queryInterval(VertexDescription.Semantics.POSITION, 0).equals(new Envelope1D(9, 13)); + } + + private static void assertIntersection(Envelope envelope, Envelope other, Envelope intersection) { + boolean intersects = envelope.intersect(other); + assertTrue(intersects); + assertEquals(envelope, intersection); + } - private static void assertNoIntersection(Envelope envelope, Envelope other) - { - boolean intersects = envelope.intersect(other); - assertFalse(intersects); - assertTrue(envelope.isEmpty()); - } + private static void assertNoIntersection(Envelope envelope, Envelope other) { + boolean intersects = envelope.intersect(other); + assertFalse(intersects); + assertTrue(envelope.isEmpty()); + } + } + diff --git a/src/test/java/com/esri/core/geometry/TestPoint.java b/src/test/java/com/esri/core/geometry/TestPoint.java index c2e8bd2f..c30f612f 100644 --- a/src/test/java/com/esri/core/geometry/TestPoint.java +++ b/src/test/java/com/esri/core/geometry/TestPoint.java @@ -45,9 +45,35 @@ protected void tearDown() throws Exception { public void testPt() { Point pt = new Point(); assertTrue(pt.isEmpty()); + assertTrue(Double.isNaN(pt.getX())); + assertTrue(Double.isNaN(pt.getY())); + assertTrue(Double.isNaN(pt.getM())); + assertTrue(pt.getZ() == 0); + Point pt1 = new Point(); + assertTrue(pt.equals(pt1)); + int hash1 = pt.hashCode(); pt.setXY(10, 2); assertFalse(pt.isEmpty()); - + assertTrue(pt.getX() == 10); + assertTrue(pt.getY() == 2); + assertTrue(pt.getXY().equals(new Point2D(10, 2))); + assertTrue(pt.getXYZ().x == 10); + assertTrue(pt.getXYZ().y == 2); + assertTrue(pt.getXYZ().z == 0); + assertFalse(pt.equals(pt1)); + pt.copyTo(pt1); + assertTrue(pt.equals(pt1)); + int hash2 = pt.hashCode(); + assertFalse(hash1 == hash2); + pt.setZ(5); + assertFalse(pt.equals(pt1)); + pt.copyTo(pt1); + assertTrue(pt.equals(pt1)); + assertFalse(hash1 == pt.hashCode()); + assertFalse(hash2 == pt.hashCode()); + assertTrue(pt.hasZ()); + assertTrue(pt.getZ() == 5); + assertTrue(pt.hasAttribute(VertexDescription.Semantics.Z)); pt.toString(); } From 961b53555259f691b96948418997d6698d3df950 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Thu, 29 Aug 2019 08:39:58 -0700 Subject: [PATCH 55/75] Geometry release v2.2.3 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d4ea84c7..401315df 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 2.2.2 + 2.2.3 ``` diff --git a/pom.xml b/pom.xml index 09ac3899..a3dcbc19 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.3-SNAPSHOT + 2.2.3 jar Esri Geometry API for Java From 73a8be8d62f809b56ff432144aca468b3d1d9d2c Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Thu, 21 Nov 2019 19:09:43 -0800 Subject: [PATCH 56/75] Fix self-tangency test typo (#248) --- .../geometry/OperatorSimplifyLocalHelper.java | 35 +++++++------------ .../java/com/esri/core/geometry/TestOGC.java | 9 +++++ 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java b/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java index b0bd4dd8..2513693e 100644 --- a/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java +++ b/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java @@ -476,10 +476,12 @@ boolean checkSelfIntersectionsPolylinePlanar_() { || (xyindex == path_last); if (m_bOGCRestrictions) vi_prev.boundary = !is_closed_path && vi_prev.end_point; - else + else { // for regular planar simplify, only the end points are allowed // to coincide vi_prev.boundary = vi_prev.end_point; + } + vi_prev.ipath = ipath; vi_prev.x = pt.x; vi_prev.y = pt.y; @@ -506,11 +508,11 @@ boolean checkSelfIntersectionsPolylinePlanar_() { boolean end_point = (xyindex == path_start) || (xyindex == path_last); if (m_bOGCRestrictions) - boundary = !is_closed_path && vi_prev.end_point; + boundary = !is_closed_path && end_point; else // for regular planar simplify, only the end points are allowed // to coincide - boundary = vi_prev.end_point; + boundary = end_point; vi.x = pt.x; vi.y = pt.y; @@ -522,22 +524,12 @@ boolean checkSelfIntersectionsPolylinePlanar_() { if (vi.x == vi_prev.x && vi.y == vi_prev.y) { if (m_bOGCRestrictions) { if (!vi.boundary || !vi_prev.boundary) { + // check that this is not the endpoints of a closed path if ((vi.ipath != vi_prev.ipath) - || (!vi.end_point && !vi_prev.end_point))// check - // that - // this - // is - // not - // the - // endpoints - // of - // a - // closed - // path - { + || (!vi.end_point && !vi_prev.end_point)) { // one of coincident vertices is not on the boundary - // this is either Non_simple_result::cross_over or - // Non_simple_result::ogc_self_tangency. + // this is either NonSimpleResult.CrossOver or + // NonSimpleResult.OGCPolylineSelfTangency. // too expensive to distinguish between the two. m_nonSimpleResult = new NonSimpleResult( NonSimpleResult.Reason.OGCPolylineSelfTangency, @@ -546,12 +538,9 @@ boolean checkSelfIntersectionsPolylinePlanar_() { } } } else { - if (!vi.end_point || !vi_prev.end_point) {// one of - // coincident - // vertices is - // not an - // endpoint - m_nonSimpleResult = new NonSimpleResult( + if (!vi.end_point || !vi_prev.end_point) { + //one of coincident vertices is not an endpoint + m_nonSimpleResult = new NonSimpleResult( NonSimpleResult.Reason.CrossOver, vi.ivertex, vi_prev.ivertex); return false;// common point not on the boundary diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index 34403661..f55dbb21 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -1036,4 +1036,13 @@ public void testFlattened() { ogcGeometry = (OGCConcreteGeometryCollection)OGCGeometry.fromText("GEOMETRYCOLLECTION (MULTIPOINT (1 1), MULTILINESTRING ((1 2, 3 4)), MULTIPOLYGON (((1 2, 3 4, 5 6, 1 2))))"); assertTrue(ogcGeometry.isFlattened()); } + + @Test + public void testIssue247IsSimple() { + //https://github.com/Esri/geometry-api-java/issues/247 + String wkt = "MULTILINESTRING ((-103.4894322 25.6164519, -103.4889647 25.6159054, -103.489434 25.615654), (-103.489434 25.615654, -103.4894322 25.6164519), (-103.4897361 25.6168342, -103.4894322 25.6164519))"; + OGCGeometry ogcGeom = OGCGeometry.fromText(wkt); + boolean b = ogcGeom.isSimple(); + assertTrue(b); + } } From abf6b7c6b825788b866266e2aad834f7309bab42 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Fri, 6 Dec 2019 12:19:14 -0800 Subject: [PATCH 57/75] close a stream in debug methods (#252) --- .../core/geometry/OperatorFactoryLocal.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java b/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java index 153b4728..04368b9d 100644 --- a/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorFactoryLocal.java @@ -29,6 +29,7 @@ import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.Reader; @@ -182,20 +183,28 @@ public static MapGeometry loadGeometryFromJSONFileDbg(String file_name) { } String jsonString = null; + Reader reader = null; try { FileInputStream stream = new FileInputStream(file_name); - Reader reader = new BufferedReader(new InputStreamReader(stream)); + reader = new BufferedReader(new InputStreamReader(stream)); StringBuilder builder = new StringBuilder(); char[] buffer = new char[8192]; int read; while ((read = reader.read(buffer, 0, buffer.length)) > 0) { builder.append(buffer, 0, read); } - stream.close(); jsonString = builder.toString(); } catch (Exception ex) { } + finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } + } MapGeometry mapGeom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jsonString); return mapGeom; @@ -276,20 +285,28 @@ public static Geometry loadGeometryFromWKTFileDbg(String file_name) { } String s = null; + Reader reader = null; try { FileInputStream stream = new FileInputStream(file_name); - Reader reader = new BufferedReader(new InputStreamReader(stream)); + reader = new BufferedReader(new InputStreamReader(stream)); StringBuilder builder = new StringBuilder(); char[] buffer = new char[8192]; int read; while ((read = reader.read(buffer, 0, buffer.length)) > 0) { builder.append(buffer, 0, read); } - stream.close(); s = builder.toString(); } catch (Exception ex) { } + finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } + } return OperatorImportFromWkt.local().execute(0, Geometry.Type.Unknown, s, null); } From 4c2fbd3d35e83c39544e85b3ca9fec57b8c03566 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 14 Jan 2020 09:18:29 -0800 Subject: [PATCH 58/75] Make Transformation3D class public (#254) --- src/main/java/com/esri/core/geometry/Transformation3D.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/Transformation3D.java b/src/main/java/com/esri/core/geometry/Transformation3D.java index 99702706..cac98407 100644 --- a/src/main/java/com/esri/core/geometry/Transformation3D.java +++ b/src/main/java/com/esri/core/geometry/Transformation3D.java @@ -33,7 +33,7 @@ * are the matrices. This is equivalent to the following line of code: * ResultVector = (M1.Mul(M2).Mul(M3)).Transform(Vector) */ -final class Transformation3D { +final public class Transformation3D { public double xx, yx, zx, xd, xy, yy, zy, yd, xz, yz, zz, zd; @@ -112,7 +112,7 @@ public Envelope3D transform(Envelope3D env) { return env; } - void transform(Point3D[] pointsIn, int count, Point3D[] pointsOut) { + public void transform(Point3D[] pointsIn, int count, Point3D[] pointsOut) { for (int i = 0; i < count; i++) { Point3D res = new Point3D(); Point3D src = pointsIn[i]; From 37b7635d9c1f3d1f4119191272a8e8406a379d0d Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Wed, 15 Jan 2020 20:04:29 -0800 Subject: [PATCH 59/75] Add a unit test and a fix for the crash in cut (#255) --- .../java/com/esri/core/geometry/Cutter.java | 5 +- .../java/com/esri/core/geometry/TestCut.java | 54 ++++++++++++------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/Cutter.java b/src/main/java/com/esri/core/geometry/Cutter.java index f56dc5de..3c34c064 100644 --- a/src/main/java/com/esri/core/geometry/Cutter.java +++ b/src/main/java/com/esri/core/geometry/Cutter.java @@ -27,7 +27,6 @@ import com.esri.core.geometry.OperatorCutLocal; -import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Arrays; @@ -138,6 +137,8 @@ static EditShape CutPolyline(boolean bConsiderTouch, Polyline cuttee, private static ArrayList _getCutEvents(int orderIndex, EditShape editShape) { int pointCount = editShape.getTotalPointCount(); + if (pointCount == 0) + return null; // Sort vertices lexicographically // Firstly copy allvertices to an array. @@ -156,8 +157,6 @@ private static ArrayList _getCutEvents(int orderIndex, CompareVertices compareVertices = new CompareVertices(orderIndex, editShape); vertices.Sort(0, pointCount, new CutterVertexComparer(compareVertices)); - // SORTDYNAMICARRAYEX(vertices, index_type, 0, pointCount, - // CutterVertexComparer, compareVertices); // Find Cut Events ArrayList cutEvents = new ArrayList(0); diff --git a/src/test/java/com/esri/core/geometry/TestCut.java b/src/test/java/com/esri/core/geometry/TestCut.java index 456973cd..a388ff01 100644 --- a/src/test/java/com/esri/core/geometry/TestCut.java +++ b/src/test/java/com/esri/core/geometry/TestCut.java @@ -51,7 +51,7 @@ public static void testCut4326() { } - public static void testConsiderTouch1(SpatialReference spatialReference) { + private static void testConsiderTouch1(SpatialReference spatialReference) { OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); @@ -101,7 +101,7 @@ public static void testConsiderTouch1(SpatialReference spatialReference) { assertTrue(cut == null); } - public static void testConsiderTouch2(SpatialReference spatialReference) { + private static void testConsiderTouch2(SpatialReference spatialReference) { OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); @@ -167,7 +167,7 @@ public static void testConsiderTouch2(SpatialReference spatialReference) { assertTrue(cut == null); } - public static void testPolygon5(SpatialReference spatialReference) { + private static void testPolygon5(SpatialReference spatialReference) { OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); @@ -201,7 +201,7 @@ public static void testPolygon5(SpatialReference spatialReference) { assertTrue(cut == null); } - public static void testPolygon7(SpatialReference spatialReference) { + private static void testPolygon7(SpatialReference spatialReference) { OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); @@ -238,7 +238,7 @@ public static void testPolygon7(SpatialReference spatialReference) { assertTrue(cut == null); } - public static void testPolygon8(SpatialReference spatialReference) { + private static void testPolygon8(SpatialReference spatialReference) { OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); @@ -275,7 +275,7 @@ public static void testPolygon8(SpatialReference spatialReference) { assertTrue(cut == null); } - public static void testPolygon9(SpatialReference spatialReference) { + private static void testPolygon9(SpatialReference spatialReference) { OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance(); OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut); @@ -309,7 +309,7 @@ public static void testPolygon9(SpatialReference spatialReference) { assertTrue(cut == null); } - public static void testEngine(SpatialReference spatialReference) { + private static void testEngine(SpatialReference spatialReference) { Polygon polygon8 = makePolygon8(); Polyline cutter8 = makePolygonCutter8(); @@ -337,7 +337,7 @@ public static void testEngine(SpatialReference spatialReference) { assertTrue(area == 800); } - public static Polyline makePolyline1() { + private static Polyline makePolyline1() { Polyline poly = new Polyline(); poly.startPath(0, 0); @@ -355,7 +355,7 @@ public static Polyline makePolyline1() { return poly; } - public static Polyline makePolylineCutter1() { + private static Polyline makePolylineCutter1() { Polyline poly = new Polyline(); poly.startPath(1, 0); @@ -395,7 +395,7 @@ public static Polyline makePolylineCutter1() { return poly; } - public static Polyline makePolyline2() { + private static Polyline makePolyline2() { Polyline poly = new Polyline(); poly.startPath(-2, 0); @@ -410,7 +410,7 @@ public static Polyline makePolyline2() { return poly; } - public static Polyline makePolylineCutter2() { + private static Polyline makePolylineCutter2() { Polyline poly = new Polyline(); poly.startPath(-1.5, 0); @@ -443,7 +443,7 @@ public static Polyline makePolylineCutter2() { return poly; } - public static Polygon makePolygon5() { + private static Polygon makePolygon5() { Polygon poly = new Polygon(); poly.startPath(0, 0); @@ -454,7 +454,7 @@ public static Polygon makePolygon5() { return poly; } - public static Polyline makePolygonCutter5() { + private static Polyline makePolygonCutter5() { Polyline poly = new Polyline(); poly.startPath(15, 0); @@ -466,7 +466,7 @@ public static Polyline makePolygonCutter5() { return poly; } - public static Polygon makePolygon7() { + private static Polygon makePolygon7() { Polygon poly = new Polygon(); poly.startPath(0, 0); @@ -477,7 +477,7 @@ public static Polygon makePolygon7() { return poly; } - public static Polyline makePolygonCutter7() { + private static Polyline makePolygonCutter7() { Polyline poly = new Polyline(); poly.startPath(10, 10); @@ -489,7 +489,7 @@ public static Polyline makePolygonCutter7() { return poly; } - public static Polygon makePolygon8() { + private static Polygon makePolygon8() { Polygon poly = new Polygon(); poly.startPath(0, 0); @@ -500,7 +500,7 @@ public static Polygon makePolygon8() { return poly; } - public static Polyline makePolygonCutter8() { + private static Polyline makePolygonCutter8() { Polyline poly = new Polyline(); poly.startPath(10, 10); @@ -512,7 +512,7 @@ public static Polyline makePolygonCutter8() { return poly; } - public static Polygon makePolygon9() { + private static Polygon makePolygon9() { Polygon poly = new Polygon(); poly.startPath(0, 0); @@ -533,7 +533,7 @@ public static Polygon makePolygon9() { return poly; } - public static Polyline makePolygonCutter9() { + private static Polyline makePolygonCutter9() { Polyline poly = new Polyline(); poly.startPath(5, -1); @@ -541,4 +541,20 @@ public static Polyline makePolygonCutter9() { return poly; } + + @Test + public void testGithubIssue253() { + //https://github.com/Esri/geometry-api-java/issues/253 + SpatialReference spatialReference = SpatialReference.create(3857); + Polyline poly1 = new Polyline(); + poly1.startPath(610, 552); + poly1.lineTo(610, 552); + Polyline poly2 = new Polyline(); + poly2.startPath(610, 552); + poly2.lineTo(610, 552); + GeometryCursor cursor = OperatorCut.local().execute(true, poly1, poly2, spatialReference, null); + + Geometry res = cursor.next(); + assertTrue(res == null); + } } From 6add959ef028b993607e0a97a507d8b3bffa1f08 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Wed, 12 Aug 2020 10:33:50 -0700 Subject: [PATCH 60/75] Fix a hang in union of a point with polyline (#267) --- .../esri/core/geometry/PlaneSweepCrackerHelper.java | 9 +++++++-- src/test/java/com/esri/core/geometry/TestOGC.java | 11 +++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/PlaneSweepCrackerHelper.java b/src/main/java/com/esri/core/geometry/PlaneSweepCrackerHelper.java index 4bdf00cc..c84b4724 100644 --- a/src/main/java/com/esri/core/geometry/PlaneSweepCrackerHelper.java +++ b/src/main/java/com/esri/core/geometry/PlaneSweepCrackerHelper.java @@ -1212,9 +1212,14 @@ void splitEdge_(int edge1, int edge2, int intersectionCluster, // Adjust the vertex coordinates and split the segments in the the edit // shape. applyIntersectorToEditShape_(edgeOrigins1, intersector, 0); - if (edge2 != -1) + if (edgeOrigins2 != -1) applyIntersectorToEditShape_(edgeOrigins2, intersector, 1); - + else { + assert (intersectionCluster != -1); + Point2D pt = intersector.getResultPoint().getXY(); + updateClusterXY(intersectionCluster, pt); + } + // Produce clusters, and new edges. The new edges are added to // m_edges_to_insert_in_sweep_structure. createEdgesAndClustersFromSplitEdge_(edge1, intersector, 0); diff --git a/src/test/java/com/esri/core/geometry/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java index f55dbb21..b68f2fcc 100644 --- a/src/test/java/com/esri/core/geometry/TestOGC.java +++ b/src/test/java/com/esri/core/geometry/TestOGC.java @@ -1045,4 +1045,15 @@ public void testIssue247IsSimple() { boolean b = ogcGeom.isSimple(); assertTrue(b); } + + @Test + public void testOGCUnionLinePoint() { + OGCGeometry point = OGCGeometry.fromText("POINT (-44.16176186699087 -19.943264803833348)"); + OGCGeometry lineString = OGCGeometry.fromText( + "LINESTRING (-44.1247493 -19.9467657, -44.1247979 -19.9468385, -44.1249043 -19.946934, -44.1251096 -19.9470651, -44.1252609 -19.9471383, -44.1254992 -19.947204, -44.1257652 -19.947229, -44.1261292 -19.9471833, -44.1268946 -19.9470098, -44.1276847 -19.9468416, -44.127831 -19.9468143, -44.1282639 -19.9467366, -44.1284569 -19.9467237, -44.1287119 -19.9467261, -44.1289437 -19.9467665, -44.1291499 -19.9468221, -44.1293856 -19.9469396, -44.1298857 -19.9471497, -44.1300908 -19.9472071, -44.1302743 -19.9472331, -44.1305029 -19.9472364, -44.1306498 -19.9472275, -44.1308054 -19.947216, -44.1308553 -19.9472037, -44.1313206 -19.9471394, -44.1317889 -19.9470854, -44.1330422 -19.9468887, -44.1337465 -19.9467083, -44.1339922 -19.9466842, -44.1341506 -19.9466997, -44.1343621 -19.9467226, -44.1345134 -19.9467855, -44.1346494 -19.9468456, -44.1347295 -19.946881, -44.1347988 -19.9469299, -44.1350231 -19.9471131, -44.1355843 -19.9478307, -44.1357802 -19.9480557, -44.1366289 -19.949198, -44.1370384 -19.9497001, -44.137386 -19.9501921, -44.1374113 -19.9502263, -44.1380888 -19.9510925, -44.1381769 -19.9513526, -44.1382509 -19.9516202, -44.1383014 -19.9522136, -44.1383889 -19.9530931, -44.1384227 -19.9538784, -44.1384512 -19.9539653, -44.1384555 -19.9539807, -44.1384901 -19.9541928, -44.1385563 -19.9543859, -44.1386656 -19.9545781, -44.1387339 -19.9546889, -44.1389219 -19.9548661, -44.1391695 -19.9550384, -44.1393672 -19.9551414, -44.1397538 -19.9552208, -44.1401714 -19.9552332, -44.1405656 -19.9551143, -44.1406198 -19.9550853, -44.1407579 -19.9550224, -44.1409029 -19.9549201, -44.1410283 -19.9548257, -44.1413902 -19.9544132, -44.141835 -19.9539274, -44.142268 -19.953484, -44.1427036 -19.9531023, -44.1436229 -19.952259, -44.1437568 -19.9521565, -44.1441783 -19.9517273, -44.144644 -19.9512109, -44.1452538 -19.9505663, -44.1453541 -19.9504774, -44.1458653 -19.9500442, -44.1463563 -19.9496473, -44.1467534 -19.9492812, -44.1470553 -19.9490028, -44.1475804 -19.9485293, -44.1479838 -19.9482096, -44.1485003 -19.9478532, -44.1489451 -19.9477314, -44.1492225 -19.9477024, -44.149453 -19.9476684, -44.149694 -19.9476387, -44.1499556 -19.9475436, -44.1501398 -19.9474234, -44.1502723 -19.9473206, -44.150421 -19.9471473, -44.1505043 -19.9470004, -44.1507664 -19.9462594, -44.150867 -19.9459518, -44.1509225 -19.9457843, -44.1511168 -19.945466, -44.1513601 -19.9452272, -44.1516846 -19.944999, -44.15197 -19.9448738, -44.1525994 -19.9447263, -44.1536614 -19.9444791, -44.1544071 -19.9442671, -44.1548978 -19.9441275, -44.1556247 -19.9438304, -44.1565996 -19.9434083, -44.1570351 -19.9432556, -44.1573142 -19.9432091, -44.1575332 -19.9431645, -44.157931 -19.9431484, -44.1586408 -19.9431504, -44.1593575 -19.9431457, -44.1596498 -19.9431562, -44.1600991 -19.9431475, -44.1602331 -19.9431567, -44.1607926 -19.9432449, -44.1609723 -19.9432499, -44.1623815 -19.9432765, -44.1628299 -19.9433645, -44.1632475 -19.9435839, -44.1633456 -19.9436559, -44.1636261 -19.9439375, -44.1638186 -19.9442439, -44.1642535 -19.9451781, -44.165178 -19.947156, -44.1652928 -19.9474016, -44.1653074 -19.9474329, -44.1654026 -19.947766, -44.1654774 -19.9481718, -44.1655699 -19.9490241, -44.1656196 -19.9491538, -44.1659735 -19.9499097, -44.1662485 -19.9504925, -44.1662996 -19.9506347, -44.1663574 -19.9512961, -44.1664094 -19.9519273, -44.1664144 -19.9519881, -44.1664799 -19.9526399, -44.1666965 -19.9532586, -44.1671191 -19.9544126, -44.1672019 -19.9545869, -44.1673344 -19.9547603, -44.1675958 -19.9550466, -44.1692349 -19.9567775, -44.1694607 -19.9569284, -44.1718843 -19.9574147, -44.1719167 -19.9574206, -44.1721627 -19.9574748, -44.1723207 -19.9575386, -44.1724439 -19.9575883, -44.1742798 -19.9583293, -44.1748841 -19.9585688, -44.1751118 -19.9586796, -44.1752554 -19.9587769, -44.1752644 -19.9587881, -44.1756052 -19.9592143, -44.1766415 -19.9602689, -44.1774912 -19.9612387, -44.177663 -19.961364, -44.177856 -19.9614494, -44.178034 -19.9615125, -44.1782475 -19.9615423, -44.1785115 -19.9615155, -44.1795404 -19.9610879, -44.1796393 -19.9610759, -44.1798873 -19.9610459, -44.1802404 -19.961036, -44.1804714 -19.9609634, -44.181059 -19.9605365, -44.1815113 -19.9602333, -44.1826712 -19.9594067, -44.1829715 -19.9592551, -44.1837201 -19.9590611, -44.1839277 -19.9590073, -44.1853022 -19.9586512, -44.1856812 -19.9585316, -44.1862915 -19.9584212, -44.1866215 -19.9583494, -44.1867651 -19.9583391, -44.1868852 -19.9583372, -44.1872523 -19.9583313, -44.187823 -19.9583281, -44.1884457 -19.958351, -44.1889559 -19.958437, -44.1893825 -19.9585816, -44.1897582 -19.9587828, -44.1901186 -19.9590453, -44.1912457 -19.9602029, -44.1916575 -19.9606307, -44.1921624 -19.9611588, -44.1925367 -19.9615872, -44.1931832 -19.9622566, -44.1938468 -19.9629343, -44.194089 -19.9631996, -44.1943924 -19.9634141, -44.1946006 -19.9635104, -44.1948789 -19.963599, -44.1957402 -19.9637569, -44.1964094 -19.9638505, -44.1965875 -19.9639188, -44.1967865 -19.9640801, -44.197096 -19.9643572, -44.1972765 -19.964458, -44.1974407 -19.9644824, -44.1976234 -19.9644668, -44.1977654 -19.9644282, -44.1980715 -19.96417, -44.1984541 -19.9638069, -44.1986632 -19.9636002, -44.1988132 -19.9634172, -44.1989542 -19.9632962, -44.1991349 -19.9631081)"); + OGCGeometry result12 = point.union(lineString); + String text12 = result12.asText(); + assertEquals(text12, "LINESTRING (-44.1247493 -19.9467657, -44.1247979 -19.9468385, -44.1249043 -19.946934, -44.1251096 -19.9470651, -44.1252609 -19.9471383, -44.1254992 -19.947204, -44.1257652 -19.947229, -44.1261292 -19.9471833, -44.1268946 -19.9470098, -44.1276847 -19.9468416, -44.127831 -19.9468143, -44.1282639 -19.9467366, -44.1284569 -19.9467237, -44.1287119 -19.9467261, -44.1289437 -19.9467665, -44.1291499 -19.9468221, -44.1293856 -19.9469396, -44.1298857 -19.9471497, -44.1300908 -19.9472071, -44.1302743 -19.9472331, -44.1305029 -19.9472364, -44.1306498 -19.9472275, -44.1308054 -19.947216, -44.1308553 -19.9472037, -44.1313206 -19.9471394, -44.1317889 -19.9470854, -44.1330422 -19.9468887, -44.1337465 -19.9467083, -44.1339922 -19.9466842, -44.1341506 -19.9466997, -44.1343621 -19.9467226, -44.1345134 -19.9467855, -44.1346494 -19.9468456, -44.1347295 -19.946881, -44.1347988 -19.9469299, -44.1350231 -19.9471131, -44.1355843 -19.9478307, -44.1357802 -19.9480557, -44.1366289 -19.949198, -44.1370384 -19.9497001, -44.137386 -19.9501921, -44.1374113 -19.9502263, -44.1380888 -19.9510925, -44.1381769 -19.9513526, -44.1382509 -19.9516202, -44.1383014 -19.9522136, -44.1383889 -19.9530931, -44.1384227 -19.9538784, -44.1384512 -19.9539653, -44.1384555 -19.9539807, -44.1384901 -19.9541928, -44.1385563 -19.9543859, -44.1386656 -19.9545781, -44.1387339 -19.9546889, -44.1389219 -19.9548661, -44.1391695 -19.9550384, -44.1393672 -19.9551414, -44.1397538 -19.9552208, -44.1401714 -19.9552332, -44.1405656 -19.9551143, -44.1406198 -19.9550853, -44.1407579 -19.9550224, -44.1409029 -19.9549201, -44.1410283 -19.9548257, -44.1413902 -19.9544132, -44.141835 -19.9539274, -44.142268 -19.953484, -44.1427036 -19.9531023, -44.1436229 -19.952259, -44.1437568 -19.9521565, -44.1441783 -19.9517273, -44.144644 -19.9512109, -44.1452538 -19.9505663, -44.1453541 -19.9504774, -44.1458653 -19.9500442, -44.1463563 -19.9496473, -44.1467534 -19.9492812, -44.1470553 -19.9490028, -44.1475804 -19.9485293, -44.1479838 -19.9482096, -44.1485003 -19.9478532, -44.1489451 -19.9477314, -44.1492225 -19.9477024, -44.149453 -19.9476684, -44.149694 -19.9476387, -44.1499556 -19.9475436, -44.1501398 -19.9474234, -44.1502723 -19.9473206, -44.150421 -19.9471473, -44.1505043 -19.9470004, -44.1507664 -19.9462594, -44.150867 -19.9459518, -44.1509225 -19.9457843, -44.1511168 -19.945466, -44.1513601 -19.9452272, -44.1516846 -19.944999, -44.15197 -19.9448738, -44.1525994 -19.9447263, -44.1536614 -19.9444791, -44.1544071 -19.9442671, -44.1548978 -19.9441275, -44.1556247 -19.9438304, -44.1565996 -19.9434083, -44.1570351 -19.9432556, -44.1573142 -19.9432091, -44.1575332 -19.9431645, -44.157931 -19.9431484, -44.1586408 -19.9431504, -44.1593575 -19.9431457, -44.1596498 -19.9431562, -44.1600991 -19.9431475, -44.1602331 -19.9431567, -44.1607926 -19.9432449, -44.1609723 -19.9432499, -44.16176186699087 -19.94326480383335, -44.1623815 -19.9432765, -44.1628299 -19.9433645, -44.1632475 -19.9435839, -44.1633456 -19.9436559, -44.1636261 -19.9439375, -44.1638186 -19.9442439, -44.1642535 -19.9451781, -44.165178 -19.947156, -44.1652928 -19.9474016, -44.1653074 -19.9474329, -44.1654026 -19.947766, -44.1654774 -19.9481718, -44.1655699 -19.9490241, -44.1656196 -19.9491538, -44.1659735 -19.9499097, -44.1662485 -19.9504925, -44.1662996 -19.9506347, -44.1663574 -19.9512961, -44.1664094 -19.9519273, -44.1664144 -19.9519881, -44.1664799 -19.9526399, -44.1666965 -19.9532586, -44.1671191 -19.9544126, -44.1672019 -19.9545869, -44.1673344 -19.9547603, -44.1675958 -19.9550466, -44.1692349 -19.9567775, -44.1694607 -19.9569284, -44.1718843 -19.9574147, -44.1719167 -19.9574206, -44.1721627 -19.9574748, -44.1723207 -19.9575386, -44.1724439 -19.9575883, -44.1742798 -19.9583293, -44.1748841 -19.9585688, -44.1751118 -19.9586796, -44.1752554 -19.9587769, -44.1752644 -19.9587881, -44.1756052 -19.9592143, -44.1766415 -19.9602689, -44.1774912 -19.9612387, -44.177663 -19.961364, -44.177856 -19.9614494, -44.178034 -19.9615125, -44.1782475 -19.9615423, -44.1785115 -19.9615155, -44.1795404 -19.9610879, -44.1796393 -19.9610759, -44.1798873 -19.9610459, -44.1802404 -19.961036, -44.1804714 -19.9609634, -44.181059 -19.9605365, -44.1815113 -19.9602333, -44.1826712 -19.9594067, -44.1829715 -19.9592551, -44.1837201 -19.9590611, -44.1839277 -19.9590073, -44.1853022 -19.9586512, -44.1856812 -19.9585316, -44.1862915 -19.9584212, -44.1866215 -19.9583494, -44.1867651 -19.9583391, -44.1868852 -19.9583372, -44.1872523 -19.9583313, -44.187823 -19.9583281, -44.1884457 -19.958351, -44.1889559 -19.958437, -44.1893825 -19.9585816, -44.1897582 -19.9587828, -44.1901186 -19.9590453, -44.1912457 -19.9602029, -44.1916575 -19.9606307, -44.1921624 -19.9611588, -44.1925367 -19.9615872, -44.1931832 -19.9622566, -44.1938468 -19.9629343, -44.194089 -19.9631996, -44.1943924 -19.9634141, -44.1946006 -19.9635104, -44.1948789 -19.963599, -44.1957402 -19.9637569, -44.1964094 -19.9638505, -44.1965875 -19.9639188, -44.1967865 -19.9640801, -44.197096 -19.9643572, -44.1972765 -19.964458, -44.1974407 -19.9644824, -44.1976234 -19.9644668, -44.1977654 -19.9644282, -44.1980715 -19.96417, -44.1984541 -19.9638069, -44.1986632 -19.9636002, -44.1988132 -19.9634172, -44.1989542 -19.9632962, -44.1991349 -19.9631081)"); + } + } From d5a9a3fcf90626cbd1381cf48d3e9c2e6abe5422 Mon Sep 17 00:00:00 2001 From: johansettlin <37585850+johansettlin@users.noreply.github.com> Date: Wed, 12 Aug 2020 19:36:26 +0200 Subject: [PATCH 61/75] Test cases see issue #5 (#259) Add unit test for: - Envelope: getCenter() & Merge() - Envelope2D: clipLine() & sqrDistances() --- .../com/esri/core/geometry/TestEnvelope.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/src/test/java/com/esri/core/geometry/TestEnvelope.java b/src/test/java/com/esri/core/geometry/TestEnvelope.java index 6b5622e8..9ee34862 100644 --- a/src/test/java/com/esri/core/geometry/TestEnvelope.java +++ b/src/test/java/com/esri/core/geometry/TestEnvelope.java @@ -21,6 +21,107 @@ public class TestEnvelope { + @Test + /**The function returns the x and y coordinates of the center of the envelope. + * If the envelope is empty the point is set to empty otherwise the point is set to the center of the envelope. + */ + public void testGetCeneter(){ + //xmin,ymin,xmax,ymax of envelope + Envelope env1 = new Envelope(1,1, 2, 4); + Envelope env2 = new Envelope(); + Point p = new Point(); + Point p1 = new Point(1,2); + + /**Tests if the point is correctly set to the center of the envelope, */ + env1.getCenter(p); + assertTrue(p.getX() == 1.5); + + /** Tests if the point is empty because of the envelope is empty */ + env2.getCenter(p1); + assertTrue(p1.isEmpty()); + } + @Test + /* Merge takes a Point as input and increas the bouandary of the envelope to contain the point. + *If the point is empty the envelope remains the same or if the envelope is empty the coordinates + *of the point is assigned to the envelope */ + public void testMerge(){ + + /* To increase the covarege the branch where the envelope is empty can be tested + * And that the envelope and the point is not empty */ + Envelope env1 = new Envelope(1,1, 2, 4); + Envelope env2 = new Envelope(1,1, 2, 4); + Envelope env3 = new Envelope(1,1, 2, 4); + Point p = new Point(100,4); + + /*This should be false since env1 should change depending on point p */ + env1.merge(p); + assertFalse(env1.equals(env2)); + + /* This assert should be true since the point is empty and therefore env2 should not change */ + Point p1 = new Point(); + env2.merge(p1); + assertTrue(env2.equals(env3)); + } + + + @Test + /** TESTEST ENVELOPE2D ** + * ClipLine modify a line to be inside a envelope if possible */ + public void TestClipLine(){ + + //checking if segPrama is 0 and the segment is outside of the clipping window + //covers first return + Envelope2D env0 = new Envelope2D(1, 1, 4, 4); + // Reaches the branch where the delta is 0 + Point2D p1 = new Point2D(2,2); + Point2D p2 = new Point2D(2,2); + + int lineExtension = 0; + double[] segParams = {3,4}; + //reaches the branch where boundaryDistances is not 0 + double[] boundaryDistances = {2.0, 3.0}; + + int a = env0.clipLine(p1, p2, lineExtension, segParams, boundaryDistances); + //should be true since the points are inside the envelope + assertTrue(a == 4); + + // Changes p3 to fit the envelop, the line is on the edge of the envelope + Envelope2D env1 = new Envelope2D(1, 1, 4, 4); + Point2D p3 = new Point2D(1,10); + Point2D p4 = new Point2D(1,1); + + int b = env1.clipLine(p3, p4, lineExtension, segParams, boundaryDistances); + assertTrue(b == 1); + // the second point is outside and therefore changed + Envelope2D env2 = new Envelope2D(1, 1, 4, 4); + Point2D p5 = new Point2D(2,2); + Point2D p6 = new Point2D(1,10); + + int c = env2.clipLine(p5, p6, lineExtension, segParams, boundaryDistances); + assertTrue(c == 2); + + //Both points is outside the envelope and therefore no line is possible to clip, and this should return 0 + Envelope2D env3 = new Envelope2D(1, 1, 4, 4); + Point2D p7 = new Point2D(11,10); + Point2D p8 = new Point2D(5,5); + + int d = env3.clipLine(p7, p8, lineExtension, segParams, boundaryDistances); + assertTrue(d == 0); + } + + @Test + public void testSqrDistances(){ + //the point is on the envelope, which means that the distance is 0 + Envelope2D env0 = new Envelope2D(1, 1, 4, 4); + Point2D p0 = new Point2D(4,4); + assertTrue(env0.sqrDistance(p0) == 0.0); + + Envelope2D env1 = new Envelope2D(1, 1, 4, 4); + Point2D p1 = new Point2D(1,0); + + assertTrue(env0.sqrDistance(p1) == 1.0); + + } @Test public void testIntersect() { assertIntersection(new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5), new Envelope(0, 0, 5, 5)); From 222c0e0d4cb0d4dc7dc02a4c417d7dc516f36a51 Mon Sep 17 00:00:00 2001 From: satish-csi <67928686+satish-csi@users.noreply.github.com> Date: Tue, 1 Sep 2020 03:14:03 +0530 Subject: [PATCH 62/75] Fix Geometry WKB parsing issue For MultiPoint ZM geometry (#268) --- .../com/esri/core/geometry/OperatorExportToWkbLocal.java | 2 +- src/test/java/com/esri/core/geometry/TestWKBSupport.java | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java b/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java index bb3abaad..a1ddec68 100644 --- a/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java +++ b/src/main/java/com/esri/core/geometry/OperatorExportToWkbLocal.java @@ -750,7 +750,7 @@ else if (wkbBuffer.capacity() < (int) size) if ((exportFlags & WkbExportFlags.wkbExportPoint) == 0) { wkbBuffer.put(offset, byteOrder); offset += 1; - wkbBuffer.putInt(offset, WkbGeometryType.wkbMultiPolygonZM); + wkbBuffer.putInt(offset, WkbGeometryType.wkbMultiPointZM); offset += 4; wkbBuffer.putInt(offset, point_count); offset += 4; diff --git a/src/test/java/com/esri/core/geometry/TestWKBSupport.java b/src/test/java/com/esri/core/geometry/TestWKBSupport.java index a55252fb..dfbaba16 100644 --- a/src/test/java/com/esri/core/geometry/TestWKBSupport.java +++ b/src/test/java/com/esri/core/geometry/TestWKBSupport.java @@ -24,6 +24,7 @@ package com.esri.core.geometry; +import com.esri.core.geometry.ogc.OGCGeometry; import java.io.IOException; import java.nio.ByteBuffer; import junit.framework.TestCase; @@ -107,4 +108,12 @@ public void testWKB2() throws Exception { } + @Test + public void testWKB3() throws Exception { + String multiPointWKT = "MULTIPOINT ZM(10 40 1 23, 40 30 2 45)"; + OGCGeometry geometry = OGCGeometry.fromText(multiPointWKT); + ByteBuffer byteBuffer = geometry.asBinary(); + OGCGeometry geomFromBinary = OGCGeometry.fromBinary(byteBuffer); + assertTrue(geometry.Equals(geomFromBinary)); + } } From c0c621789c4e2b4f8b11ef1b8dd032f207294857 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Mon, 21 Sep 2020 13:27:20 -0700 Subject: [PATCH 63/75] Geometry release v2.2.4 --- README.md | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 401315df..5a1468c6 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 2.2.3 + 2.2.4 ``` diff --git a/pom.xml b/pom.xml index a3dcbc19..34e8318d 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.3 + 2.2.4 jar Esri Geometry API for Java From a1af6612f4de7fc1baee1c331c335f154a4a96c9 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Thu, 8 Oct 2020 12:23:32 -0700 Subject: [PATCH 64/75] Fix exception in WKB export for polygon with first ring of zero area (#276) --- .../com/esri/core/geometry/MultiPathImpl.java | 43 +++++++++++-------- .../esri/core/geometry/TestImportExport.java | 23 ++++++---- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java index c9400ee0..d70e5c5d 100644 --- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java @@ -2133,27 +2133,34 @@ int getOGCPolygonCount() { protected void _updateOGCFlags() { if (_hasDirtyFlag(DirtyFlags.DirtyOGCFlags)) { _updateRingAreas2D(); - - int pathCount = getPathCount(); - if (pathCount > 0 && (m_pathFlags == null || m_pathFlags.size() < pathCount)) - m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase - .createByteStream(pathCount + 1); - - int firstSign = 1; - for (int ipath = 0; ipath < pathCount; ipath++) { - double area = m_cachedRingAreas2D.read(ipath); - if (ipath == 0) - firstSign = area > 0 ? 1 : -1; - if (area * firstSign > 0.0) - m_pathFlags.setBits(ipath, - (byte) PathFlags.enumOGCStartPolygon); - else - m_pathFlags.clearBits(ipath, - (byte) PathFlags.enumOGCStartPolygon); - } + _updateOGCFlagsHelper(); _setDirtyFlag(DirtyFlags.DirtyOGCFlags, false); } } + + private void _updateOGCFlagsHelper() { + int pathCount = getPathCount(); + if (pathCount > 0 && (m_pathFlags == null || m_pathFlags.size() < pathCount)) + m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(pathCount + 1); + + // firstSign is the sign of first ring. + // a first ring with non zero area defines the + // value. First zero area rings are written out as enumOGCStartPolygon. + int firstSign = 0; + for (int ipath = 0; ipath < pathCount; ipath++) { + double area = m_cachedRingAreas2D.read(ipath); + if (firstSign == 0) { + // if the first ring is inverted we assume that the + // whole polygon is inverted. + firstSign = MathUtils.sign(area); + } + + if (area * firstSign > 0.0 || firstSign == 0) + m_pathFlags.setBits(ipath, (byte) PathFlags.enumOGCStartPolygon); + else + m_pathFlags.clearBits(ipath, (byte) PathFlags.enumOGCStartPolygon); + } + } public int getPathIndexFromPointIndex(int pointIndex) { int positionHint = m_currentPathIndex;// in case of multithreading diff --git a/src/test/java/com/esri/core/geometry/TestImportExport.java b/src/test/java/com/esri/core/geometry/TestImportExport.java index 0b9e2bc8..73faed01 100644 --- a/src/test/java/com/esri/core/geometry/TestImportExport.java +++ b/src/test/java/com/esri/core/geometry/TestImportExport.java @@ -44,15 +44,6 @@ protected void tearDown() throws Exception { @Test public static void testImportExportShapePolygon() { -// { -// String s = "MULTIPOLYGON (((-1.4337158203098852 53.42590083930004, -1.4346462383651897 53.42590083930004, -1.4349713164114632 53.42426406667512, -1.4344808816770183 53.42391134176576, -1.4337158203098852 53.424339319373516, -1.4337158203098852 53.42590083930004, -1.4282226562499147 53.42590083930004, -1.4282226562499147 53.42262754610009, -1.423659941537096 53.42262754610009, -1.4227294921872726 53.42418897437618, -1.4199829101572732 53.42265258737483, -1.4172363281222147 53.42418897437334, -1.4144897460898278 53.42265258737625, -1.4144897460898278 53.42099079900008, -1.4117431640598568 53.42099079712516, -1.4117431640598568 53.41849780932388, -1.4112778948070286 53.41771711805022, -1.4114404909237805 53.41689867267529, -1.411277890108579 53.416080187950215, -1.4117431640598568 53.4152995338453, -1.4117431657531654 53.40953184824072, -1.41723632610001 53.40953184402311, -1.4172363281199125 53.406257299700044, -1.4227294921899158 53.406257299700044, -1.4227294921899158 53.40789459668797, -1.4254760767598498 53.40789460061099, -1.4262193642339867 53.40914148401417, -1.4273828468095076 53.409531853100034, -1.4337158203098852 53.409531790075235, -1.4337158203098852 53.41280609140024, -1.4392089843723568 53.41280609140024, -1.439208984371362 53.41608014067522, -1.441160015802268 53.41935368587538, -1.4427511170075604 53.41935368587538, -1.4447021484373863 53.42099064750012, -1.4501953124999432 53.42099064750012, -1.4501953124999432 53.43214683850347, -1.4513643355446106 53.434108816701794, -1.4502702625278232 53.43636597733034, -1.4494587195580948 53.437354845300334, -1.4431075935937656 53.437354845300334, -1.4372459179209045 53.43244635455021, -1.433996276212838 53.42917388040006, -1.4337158203098852 53.42917388040006, -1.4337158203098852 53.42590083930004)))"; -// Geometry g = OperatorImportFromWkt.local().execute(0, Geometry.Type.Unknown, s, null); -// boolean result1 = OperatorSimplify.local().isSimpleAsFeature(g, null, null); -// boolean result2 = OperatorSimplifyOGC.local().isSimpleOGC(g, null, true, null, null); -// Geometry simple = OperatorSimplifyOGC.local().execute(g, null, true, null); -// OperatorFactoryLocal.saveToWKTFileDbg("c:/temp/simplifiedeeee", simple, null); -// int i = 0; -// } OperatorExportToESRIShape exporterShape = (OperatorExportToESRIShape) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.ExportToESRIShape); OperatorImportFromESRIShape importerShape = (OperatorImportFromESRIShape) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.ImportFromESRIShape); @@ -1754,6 +1745,20 @@ public static void testImportGeoJsonSpatialReference() throws Exception { assertTrue(mapGeometry4326.getGeometry().equals(mapGeometry3857.getGeometry())); } + @Test + public void testZeroRingWkb() { + //https://github.com/Esri/geometry-api-java/issues/275 + Polygon poly = new Polygon(); + poly.startPath(0, 0); + poly.lineTo(0, 10); + poly.lineTo(0, 10); + poly.addEnvelope(new Envelope(1, 1, 3, 3), false); + + ByteBuffer bb = OperatorExportToWkb.local().execute(0, poly, null); + Geometry res = OperatorImportFromWkb.local().execute(0, Geometry.Type.Unknown, bb, null); + assertTrue(res.equals(poly)); + } + public static Polygon makePolygon() { Polygon poly = new Polygon(); poly.startPath(0, 0); From 48149c80c6cb9ff0f1575fcbb60d3cb942a80f87 Mon Sep 17 00:00:00 2001 From: sllynn Date: Mon, 4 Apr 2022 15:45:46 +0100 Subject: [PATCH 65/75] added spatial reference into calls to geojson operator for OGCMultiLineString and OGCMultiPolygon --- .../core/geometry/ogc/OGCMultiLineString.java | 2 +- .../core/geometry/ogc/OGCMultiPolygon.java | 2 +- .../esri/core/geometry/TestGeomToGeoJson.java | 62 +++++++++++++++++-- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java index 6a2381e3..e0608f61 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java @@ -64,7 +64,7 @@ public String asText() { public String asGeoJson() { OperatorExportToGeoJson op = (OperatorExportToGeoJson) OperatorFactoryLocal.getInstance() .getOperator(Operator.Type.ExportToGeoJson); - return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, null, getEsriGeometry()); + return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, esriSR, getEsriGeometry()); } @Override diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java index 52afbe86..941bc7c2 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPolygon.java @@ -71,7 +71,7 @@ public ByteBuffer asBinary() { public String asGeoJson() { OperatorExportToGeoJson op = (OperatorExportToGeoJson) OperatorFactoryLocal .getInstance().getOperator(Operator.Type.ExportToGeoJson); - return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, null, getEsriGeometry()); + return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, esriSR, getEsriGeometry()); } @Override public int numGeometries() { diff --git a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java index aa480b26..83271d5b 100644 --- a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java +++ b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java @@ -22,14 +22,9 @@ package com.esri.core.geometry; -import com.esri.core.geometry.ogc.OGCGeometry; -import com.esri.core.geometry.ogc.OGCPoint; -import com.esri.core.geometry.ogc.OGCMultiPoint; -import com.esri.core.geometry.ogc.OGCLineString; -import com.esri.core.geometry.ogc.OGCPolygon; +import com.esri.core.geometry.ogc.*; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; -import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; import junit.framework.TestCase; import org.junit.Test; @@ -161,6 +156,20 @@ public void testOGCLineString() { assertEquals("{\"type\":\"LineString\",\"coordinates\":[[100,0],[101,0],[101,1],[100,1]],\"crs\":null}", result); } + @Test + public void testOGCMultiLineStringCRS() throws IOException { + Polyline p = new Polyline(); + p.startPath(100.0, 0.0); + p.lineTo(101.0, 0.0); + p.lineTo(101.0, 1.0); + p.lineTo(100.0, 1.0); + + OGCMultiLineString multiLineString = new OGCMultiLineString(p, SpatialReference.create(4326)); + + String result = multiLineString.asGeoJson(); + assertEquals("{\"type\":\"MultiLineString\",\"coordinates\":[[[100,0],[101,0],[101,1],[100,1]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", result); + } + @Test public void testPolygon() { Polygon p = new Polygon(); @@ -241,6 +250,24 @@ public void testMultiPolygon() throws IOException { assertEquals("{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-100,-100],[100,-100],[100,100],[-100,100],[-100,-100]],[[-90,-90],[90,-90],[-90,90],[90,90],[-90,-90]]],[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]]}", result); } + @Test + public void testOGCMultiPolygonCRS() throws IOException { + JsonFactory jsonFactory = new JsonFactory(); + + String esriJsonPolygon = "{\"rings\": [[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[-90, -90], [90, 90], [-90, 90], [90, -90], [-90, -90]], [[-10, -10], [-10, 10], [10, 10], [10, -10], [-10, -10]]]}"; + + JsonParser parser = jsonFactory.createParser(esriJsonPolygon); + MapGeometry parsedPoly = GeometryEngine.jsonToGeometry(parser); + + parsedPoly.setSpatialReference(SpatialReference.create(4326)); + Polygon poly = (Polygon) parsedPoly.getGeometry(); + OGCMultiPolygon multiPolygon = new OGCMultiPolygon(poly, parsedPoly.getSpatialReference()); + + + String result = multiPolygon.asGeoJson(); + assertEquals("{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-100,-100],[100,-100],[100,100],[-100,100],[-100,-100]],[[-90,-90],[90,-90],[-90,90],[90,90],[-90,-90]]],[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", result); + } + @Test public void testEmptyPolygon() { @@ -334,6 +361,29 @@ public void testOGCPolygonWithHole() { assertEquals("{\"type\":\"Polygon\",\"coordinates\":[[[100,0],[101,0],[101,1],[100,1],[100,0]],[[100.2,0.2],[100.2,0.8],[100.8,0.8],[100.8,0.2],[100.2,0.2]]],\"crs\":null}", result); } + @Test + public void testOGCPolygonWithHoleCRS() { + Polygon p = new Polygon(); + + p.startPath(100.0, 0.0); + p.lineTo(100.0, 1.0); + p.lineTo(101.0, 1.0); + p.lineTo(101.0, 0.0); + p.closePathWithLine(); + + p.startPath(100.2, 0.2); + p.lineTo(100.8, 0.2); + p.lineTo(100.8, 0.8); + p.lineTo(100.2, 0.8); + p.closePathWithLine(); + + SpatialReference sr = SpatialReference.create(4326); + + OGCPolygon ogcPolygon = new OGCPolygon(p, sr); + String result = ogcPolygon.asGeoJson(); + assertEquals("{\"type\":\"Polygon\",\"coordinates\":[[[100,0],[101,0],[101,1],[100,1],[100,0]],[[100.2,0.2],[100.2,0.8],[100.8,0.8],[100.8,0.2],[100.2,0.2]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", result); + } + @Test public void testGeometryCollection() { SpatialReference sr = SpatialReference.create(4326); From 74a99e7d2027a80c995679afea78de4bfe432569 Mon Sep 17 00:00:00 2001 From: Sergey Tolstov Date: Tue, 31 May 2022 09:28:00 -0700 Subject: [PATCH 66/75] Remove a copyright comment (#293) --- .../com/esri/core/geometry/JsonReaderCursor.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/JsonReaderCursor.java b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java index 94f72a30..8e0f16de 100644 --- a/src/main/java/com/esri/core/geometry/JsonReaderCursor.java +++ b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java @@ -19,21 +19,6 @@ 380 New York Street Redlands, California, USA 92373 - email: contracts@esri.com - */ -/* - COPYRIGHT 1995-2017 ESRI - - TRADE SECRETS: ESRI PROPRIETARY AND CONFIDENTIAL - Unpublished material - all rights reserved under the - Copyright Laws of the United States. - - For additional information, contact: - Environmental Systems Research Institute, Inc. - Attn: Contracts Dept - 380 New York Street - Redlands, California, USA 92373 - email: contracts@esri.com */ From 60f239c0515ab43f6354f38ce8728b8656cb9277 Mon Sep 17 00:00:00 2001 From: Randall Whitman Date: Thu, 2 Jun 2022 08:37:38 -0700 Subject: [PATCH 67/75] Link Esri.github.io for Javadoc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a1468c6..d64e0db5 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: ## Documentation * [geometry-api-java/Wiki](https://github.com/Esri/geometry-api-java/wiki/) -* [geometry-api-java/Javadoc](http://esri.github.com/geometry-api-java/javadoc/) +* [geometry-api-java/Javadoc](http://Esri.github.io/geometry-api-java/javadoc/) ## Resources From 20c5cbd814c3cdedbcda81ee1086d3888ba6bfd5 Mon Sep 17 00:00:00 2001 From: Annette Locke Date: Thu, 2 Feb 2023 14:38:25 -0800 Subject: [PATCH 68/75] Temp file for testing geometry server --- data/AK_3338_MULTIPOINTS_JSON_GEOMETRY.TXT | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/AK_3338_MULTIPOINTS_JSON_GEOMETRY.TXT diff --git a/data/AK_3338_MULTIPOINTS_JSON_GEOMETRY.TXT b/data/AK_3338_MULTIPOINTS_JSON_GEOMETRY.TXT new file mode 100644 index 00000000..b5b56aa2 --- /dev/null +++ b/data/AK_3338_MULTIPOINTS_JSON_GEOMETRY.TXT @@ -0,0 +1 @@ +{"geometryType" : "esriGeometryMultipoint","geometries" : [{"points" : [[-422460.131402843,994009.192353492],[-425621.226482613,991032.590063632],[-424201.949054824,986531.313422172],[-449572.721437023,976682.216676533],[-445757.973353393,983081.453278027],[-447565.625031025,986731.192475301],[-449041.127659045,981860.757795434],[-471763.09284187,990302.643172824],[-455639.101461489,988686.731761123],[-440188.279632496,1003500.47178871],[-446996.90483744,1002326.25256318],[-445579.971866621,1023106.39454493],[-448587.475766268,1030185.56721526],[-431199.893662673,1036568.02753379],[-447336.100526733,1039637.52849332],[-448745.674369452,1033832.34834033]]}],"spatialReference" : {"wkid" : 3338}} \ No newline at end of file From db56dc80057192be78478ae3fba23b6f6026113b Mon Sep 17 00:00:00 2001 From: Annette Locke Date: Thu, 2 Feb 2023 14:50:08 -0800 Subject: [PATCH 69/75] Temp file for server test --- data/INTERSTATE10_102009_POLYLINE_GEOMETRY2.TXT | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/INTERSTATE10_102009_POLYLINE_GEOMETRY2.TXT diff --git a/data/INTERSTATE10_102009_POLYLINE_GEOMETRY2.TXT b/data/INTERSTATE10_102009_POLYLINE_GEOMETRY2.TXT new file mode 100644 index 00000000..9b46512f --- /dev/null +++ b/data/INTERSTATE10_102009_POLYLINE_GEOMETRY2.TXT @@ -0,0 +1 @@ +[{"paths" : [[[-1860932.82127223,-388270.616031549],[-1846957.20718179,-391464.562129146],[-1840307.63567473,-394033.481586339],[-1918707.73887222,-377413.212554243],[-1914222.88941537,-376015.003856398],[-1906334.46244651,-378208.210897945],[-1898644.6777357,-378779.474294907],[-1891889.43366789,-379905.354171953],[-1884733.69891171,-382651.410161352],[-1883937.29591364,-382454.447279954],[-1936756.2564541,-373739.523949398],[-1924276.48838184,-376332.106982319],[-1920512.79000794,-377655.198817429],[-1918707.73887222,-377413.212554243],[-1883937.29591364,-382454.447279954],[-1870439.63374804,-384750.380696851],[-1867879.05963065,-386707.364069535],[-1860932.82127223,-388270.616031549],[-1942584.19056967,-372494.956589206],[-1936756.2564541,-373739.523949398],[-1409097.63488798,-551869.261070279],[-1409523.01440632,-554656.915811257],[-1840307.63567473,-394033.481586339],[-1831508.27455814,-398407.122999975],[-1826863.67560942,-402643.014773565],[-1821015.04269462,-406241.500127598],[-1817735.66345434,-412991.69676903],[-1813480.00041146,-415363.587122058],[-1804394.9196369,-416954.436337427],[-1800845.07258485,-419152.320953585],[-1791834.05687365,-420232.283109151],[-1784027.25683367,-423374.413978621],[-1779380.26258846,-426183.936541837],[-1777557.80520672,-428104.598329479],[-1771046.93481117,-436333.194981073],[-1765596.1415797,-442582.458365353],[-1760884.64466077,-445947.366036213],[-1757733.87097148,-447947.089025783],[-1754170.7352927,-452948.196724181],[-1747551.58921333,-456877.696319367],[-1745156.79401807,-456873.145387547],[-1740963.5553046,-459914.071569563],[-1721825.23950976,-466900.622601992],[-1705392.42558765,-469042.810066407],[-1686982.69670194,-469009.666799931],[-1684122.55796452,-469755.631053038],[-1675999.9086547,-473454.5971056],[-1653558.62949401,-487961.62076816],[-1627004.40554155,-493383.327896274],[-1619637.12729604,-495073.914894848],[-1617155.56334704,-495351.793322275],[-1616112.99057719,-495282.072620393],[-1605499.7571852,-494572.633205635],[-1602626.47117254,-493620.772230954],[-1590641.82987419,-495281.949210788],[-1588314.58186174,-496080.371608566],[-1586759.81276419,-496468.345673322],[-1583113.44679489,-495731.506909874],[-1575775.215391,-496394.444746467],[-1571678.82445026,-498818.807671611],[-1480398.4816489,-532854.62017299],[-1452852.22751085,-547262.639157195],[-1444216.68445375,-544966.879608767],[-1409097.63488798,-551869.261070279],[-1409523.01440632,-554656.915811257],[-1404176.29800062,-556880.553833265],[-1399534.3089503,-559866.27553626],[-1401783.49287842,-571710.278685015],[-1393513.70189299,-591417.565729961],[-1388075.76799737,-604306.93702367],[-1384196.66113984,-613280.686797792],[-1384815.79170956,-618950.906859659],[-1386132.48063215,-625339.350743451],[-1386132.48063215,-625339.350743451],[-1373313.84971144,-638740.589542896],[-1361965.20235478,-651191.082814489],[-1355218.50835855,-664881.949750467],[-1347001.22496875,-674725.006126551],[-1340260.56839497,-684926.857390148],[-1334998.33589704,-696799.859699966],[-1334665.42360899,-698162.030945824],[-1335844.30363362,-702694.148342999],[-1245210.95724443,-718431.080285172],[-1238717.2640838,-713547.342478722],[-1230199.08023375,-706191.966182859],[-1224070.47756294,-702312.559825601],[-1218105.24137078,-702436.57083677],[-1214061.44067799,-702949.590340844],[-1209021.15588085,-706281.9252118],[-1203124.24661422,-708821.565988461],[-1201075.35462315,-710198.06636224],[-1198540.32612232,-710628.525608014],[-1183330.43394871,-716802.70081487],[-1181419.54410298,-718449.355276614],[-1175919.76505775,-721024.065253884],[-1173663.57075243,-721023.633571428],[-1167076.61455832,-724198.542337905],[-1164285.63224225,-726910.514437306],[-1163352.53966945,-727817.234271247],[-1159099.8246554,-727921.741917781],[-1154948.4644574,-726408.995383046],[-1139421.30728818,-719369.434615407],[-1124845.23519314,-722912.914602716],[-1106243.39289231,-739872.893279173],[-1104217.10771599,-740758.388433313],[-1097691.72532186,-740422.708079669],[-1047775.54466794,-737914.788753216],[-1035923.5080803,-738027.748654808],[-1015627.39806565,-745993.662454439],[-1012803.9856812,-745150.854690653],[-997372.532029047,-747245.187918835],[-971736.184680474,-746673.101628281],[-961364.955127864,-752137.603723688],[-957982.669061466,-753802.10402492],[-955359.597173141,-754966.139811466],[-1335844.30363362,-702694.148342999],[-1334518.25884188,-703333.677362167],[-1330862.04433071,-705104.54484834],[-1328701.96846369,-708008.476326118],[-1327769.68784457,-710920.085437616],[-1311621.8901602,-726109.485508868],[-1306081.06552574,-728409.866473137],[-1301017.41111561,-729324.710614419],[-1293254.84575945,-732836.804983335],[-1283715.20817654,-734332.440884748],[-1280390.19280606,-733767.230085431],[-1277015.36942673,-733841.097825953],[-1275645.35862002,-735166.906876661],[-1262040.57789063,-732172.040312738],[-1253875.6884213,-725875.517154103],[-1248666.43278994,-720299.256004177],[-1245210.95724443,-718431.080285172],[-955359.597173141,-754966.139811466],[-952056.701432983,-763124.339787109],[-948546.873621568,-774860.547430418],[-948352.879021394,-779844.258199058],[-947981.528764897,-784911.407359661],[-948659.483767897,-790266.338447856],[-947649.70242825,-797238.392850766],[-946341.462502304,-798533.006572085],[-945874.23940249,-800511.147804896],[-942614.750164408,-803698.174722712],[-940056.530035286,-803611.400076444],[-937463.330307175,-803266.045082759],[-933617.842662257,-804094.590924077],[-931177.065105375,-805995.30588653],[-922450.756370351,-817038.699657056],[-912259.387590314,-837019.469569108],[-901695.153574011,-847078.644808715],[-896571.22498808,-850482.87667744],[-892978.23510254,-856268.93524594],[-886226.45560338,-863040.083826403],[-886156.02290211,-867389.174209029],[-880788.106964542,-873704.139337095],[-876152.801603457,-876262.74407912],[-872750.915412895,-876293.58252762],[-867948.585353543,-874609.483239542],[-864204.78280361,-875575.372986374],[-859352.212917072,-874810.997216439],[-853482.951382145,-877962.665940733],[-843216.321624105,-881677.853694242],[-816012.209487552,-893794.042653468],[-812378.845600151,-896009.064203036],[-810202.945501474,-896264.755720976],[-805510.700365156,-898678.445928985],[-801719.872894014,-898725.987726727],[-780450.130108813,-899368.06735481],[-764889.739533328,-898413.060026565],[-751607.914276247,-901208.140214766],[-742971.489015314,-901593.805686476],[-738658.90076313,-901906.344584241],[-736743.357981191,-900552.363631087],[-732696.174564229,-900320.440779244],[-730973.339967641,-898908.754305918],[575352.916860983,-994799.763036069],[583180.696877742,-993876.639834322],[585635.319253531,-993021.122789163],[587788.744863143,-992270.228826663],[591580.042340177,-990821.663686742],[602683.205299627,-988729.490384552],[613752.039933598,-983579.467164824],[633884.082196908,-977117.455852276],[640318.1819108,-975177.757418059],[652905.673247639,-973405.41363682],[661345.941279076,-972867.572927195],[668348.050774387,-973309.256311963],[677951.283096452,-975254.718438393],[684549.086372028,-974852.51671385],[693748.799987452,-967602.526018881],[695146.656861169,-966542.25086226],[697943.398428829,-964421.275341788],[715668.230698317,-954584.52750052],[718041.51656543,-949892.762486286],[720361.063979655,-948358.383244131],[720361.063979655,-948358.383244131],[722461.933493544,-946500.998072774],[725026.372146054,-943056.777194635],[725356.402677451,-941625.351253375],[726144.515536742,-940450.241305277],[729054.978127155,-940752.466844363],[729906.557033605,-941362.396286676],[730647.198649882,-941998.273539696],[731992.86996737,-943892.253970391],[734695.53116178,-944503.550751599],[738247.19837036,-943892.056617691],[739682.309298133,-943540.046598061],[751175.404405563,-942808.223649276],[751905.629882262,-942800.904792179],[757321.457602038,-942871.80730766],[766809.053722063,-944519.369922698],[775381.973460679,-948930.909534568],[785407.385115877,-947426.713959655],[785599.613640667,-947397.767624351],[788962.653876163,-948507.547665137],[793306.344710799,-951692.918358162],[793997.067352187,-952146.647076597],[798073.787655093,-954730.838563901],[800495.405708707,-954929.43422266],[802431.901650757,-954747.205541846],[804741.933715814,-954423.026444915],[808298.498089107,-953462.469815359],[811745.508145724,-950678.148756826],[817512.292610224,-948658.962792098],[819519.381338945,-944570.135595441],[821440.198836967,-943075.05852926],[827174.717361574,-940245.448834636],[839385.62671965,-933086.518392322],[850281.998571202,-928032.35908958],[860971.372316781,-925387.830717164],[864680.720703888,-924845.595124155],[872523.531373039,-926144.045883601],[877406.707821227,-924924.744105547],[883255.913009189,-923053.285452875],[899710.637324936,-923996.41378933],[901447.685004908,-923397.479000235],[918336.586850844,-921411.678442947],[922536.461117099,-920515.947861362],[932244.95164992,-915400.30711948],[940974.555191437,-913128.488731009],[953119.262931405,-911173.475732888],[968591.969932034,-908813.755972633],[975149.423808406,-908408.646619507],[981131.620632017,-910117.842853021],[986746.9320397,-911628.210819928],[991676.755125067,-913124.212744749],[997869.880795841,-916561.209290884],[1003303.29037402,-916972.984639167],[1009707.97704788,-916097.084768555],[1024695.33934841,-916174.207532096],[1028115.45263723,-916926.983445833],[1032978.67973518,-919891.998800418],[1035343.79026678,-920822.265641539],[1041521.59196371,-922506.218808777],[1045393.20074409,-923740.057209495],[1054904.39396888,-923457.029418946],[1064213.54590749,-924319.217929752],[1067432.55659644,-924218.388176459],[1073629.10137284,-924046.20778549],[1076666.8357316,-924064.856544828],[1081289.82014802,-924230.771361769],[1095185.07046038,-921749.534865562],[1103957.59147264,-921406.005526682],[1107546.54135469,-921941.201116782],[1124273.1703054,-923351.235853165],[1131491.36685625,-923147.365522488],[1139748.46585969,-920571.297893148],[1147330.93847969,-920516.587978908],[1157640.55723499,-923149.834098207],[1171713.02990369,-926831.518180989],[1182881.97724001,-925307.199021827],[1188554.90125587,-923240.363419346],[1193689.97457051,-922801.368888602],[1199206.83152608,-923827.805681958],[1208292.66652335,-928024.891631578],[1208292.66652335,-928024.891631578],[1216069.59391038,-929113.119365303],[1219674.33773366,-928569.094348959],[1223845.85844784,-928638.569319719],[1231791.62892553,-927117.143494849],[1236936.54454001,-927113.837907763],[1250540.82051822,-923473.029772133],[1254714.25651926,-924761.506069283],[1258038.38732707,-924690.498666897],[1269770.52199636,-918593.472029025],[1270880.32317345,-918064.874362793],[1282803.18836572,-914677.093761606],[1301672.21428071,-909640.834250306],[1305278.85905396,-907921.688813134],[1308848.19800415,-907476.307131558],[513165.371872435,-1023903.77019165],[506949.089732182,-1019596.84849971],[487004.816992026,-1018196.43208866],[480396.822018087,-1018487.39495938],[475683.512661196,-1018687.58626175],[471032.443579414,-1017084.40854554],[468387.600478024,-1016257.65520298],[466656.977378729,-1014586.19051933],[454684.734944637,-998216.765140984],[451912.800164073,-994972.065766407],[449351.585885809,-993265.855296364],[575352.916860983,-994799.763036069],[574886.966388113,-997700.638645804],[574721.887806386,-999413.371840635],[574191.255501014,-1004069.01729427],[572274.323517449,-1008439.88196554],[570390.649642987,-1009989.55795832],[566487.00624464,-1011252.1035564],[564557.227584298,-1014798.51858814],[559457.956022949,-1022277.00001518],[553184.517089836,-1026439.27334736],[552319.209393629,-1027914.1568042],[551148.300739445,-1029217.27749673],[549693.345567865,-1029325.16638881],[543382.630840925,-1029695.53597659],[539462.203590489,-1030083.17584039],[539462.203590489,-1030083.17584039],[535721.038576166,-1030262.83373266],[525175.774427311,-1028756.12205238],[515725.28293541,-1025562.88539953],[513165.371872435,-1023903.77019165],[449351.585885809,-993265.855296364],[442449.924303394,-990857.489711945],[439623.61408176,-990190.004546803],[390286.240668772,-997903.671773396],[385832.437516809,-1000993.57608467],[383570.456511053,-1004070.91609958],[369142.13795887,-1012108.12841001],[367061.095067366,-1012307.09352576],[364776.099269007,-1013055.0970963],[362507.399315924,-1013364.53363339],[354569.927435781,-1014131.24261668],[343696.660703846,-1014033.07168194],[332859.277135792,-1016519.10557814],[318885.62701576,-1017372.74945521],[311882.180644164,-1016904.35802189],[307302.971576565,-1015582.29413376],[282987.134808647,-1016299.25836854],[277591.613696029,-1016489.41113601],[264468.841446095,-1017666.65552109],[259872.978577373,-1018139.01653873],[256488.965649622,-1019204.8451938],[251490.940512464,-1019511.60677846],[249879.987365968,-1020840.72521134],[241865.025376377,-1021894.76929824],[231353.805569256,-1023366.86074435],[224966.301890999,-1025277.0027521],[219223.287156696,-1028355.99422714],[217667.54080258,-1029097.70230575],[212200.444493473,-1031994.1412628],[211954.602217841,-1032133.24034698],[210358.870227183,-1033036.7451334],[207774.282372493,-1033176.61064378],[203341.460580485,-1034504.35588428],[201039.029443652,-1034897.87590271],[195447.163130772,-1033606.92314442],[182218.186988688,-1033465.75818353],[179765.51182488,-1033949.74087309],[176002.677693372,-1036759.26769463],[172488.873477125,-1037006.27198673],[171281.908600622,-1037977.11157945],[170651.178378547,-1040330.24596238],[170802.730402945,-1041404.14984348],[161766.771268855,-1051819.97767216],[148523.545624947,-1065131.6007235],[119780.164359756,-1064594.69196167],[101896.32205977,-1066293.05961961],[97575.3897995831,-1068400.130909],[87164.7810864157,-1069746.29753127],[78784.3400300031,-1073168.67144331],[67330.0926725612,-1072355.12042547],[60429.7761875881,-1073236.29488827],[59500.7512043746,-1073343.73598084],[57222.8460555218,-1073103.48513836],[57222.8460555218,-1073103.48513836],[49830.8268393272,-1072942.29953355],[32240.2019934744,-1072209.77086171],[21788.576477514,-1071870.075084],[12126.5746239013,-1073604.45102842],[1786.24835324287,-1072927.07970355],[-5322.72282712883,-1074135.17138073],[-10451.2225478069,-1073384.08689046],[-14808.2158731411,-1076263.43642263],[-16316.716143104,-1076248.38328289],[-18832.3370748974,-1074732.09912827],[-23621.0126606509,-1075161.5112425],[-39474.7653784111,-1079352.49162442],[-45820.980666855,-1079763.72494873],[-50551.3845846837,-1082237.45755732],[-73206.9778210527,-1081513.02986402],[-77452.2100060822,-1080601.5406818],[-80074.7425430997,-1079321.66002543],[-83727.4270109524,-1079359.28943472],[-102716.633047599,-1079417.78356824],[-113039.021397429,-1079458.21945742],[-115588.807872392,-1081001.73007724],[-120824.321561725,-1082720.96050199],[-131208.440888363,-1084168.00124346],[-142058.250604208,-1083988.06839615],[-149209.512565563,-1083870.98809668],[-153718.477661156,-1084550.16344772],[-163319.881304415,-1085882.01155002],[-166662.819585015,-1087730.93698476],[-172370.484291913,-1089086.64234129],[-178612.029413752,-1089299.41957619],[-181042.082298536,-1089192.7556272],[-182588.888330004,-1088930.0297339],[-185612.836642543,-1090159.71734169],[-187630.148920998,-1092845.42273789],[-222338.217162394,-1105774.19645384],[-222338.217162394,-1105774.19645384],[-226199.731674855,-1108282.10690453],[-229675.316578143,-1109784.31512831],[-234306.079537844,-1109870.6101174],[-233264.613641968,-1108357.80091609],[-233696.504949821,-1104928.44643169],[-233803.705371492,-1104046.76811036],[-234313.021256047,-1100176.42424255],[-236955.53945654,-1097185.46393511],[-239908.560746955,-1092428.60263746],[-245109.634624337,-1078035.27214725],[-249294.186375222,-1071428.20977862],[-254911.220796075,-1067481.51331602],[-255046.054732099,-1063975.01513734],[-259235.908987459,-1057517.38243586],[-264287.710564967,-1051848.92930436],[-267665.532240482,-1045770.84704077],[-279560.028027375,-1037515.59035431],[-286285.477524195,-1035562.24714744],[-292905.193336488,-1032351.52127157],[-301698.666699814,-1024480.54636189],[-311865.133538458,-1020090.61775317],[-323594.327628477,-1011555.37551476],[-326322.783374792,-1009491.40029984],[-331711.161221129,-1000665.12628752],[-336081.089040626,-997267.24886101],[-339475.470812427,-995949.318787587],[-339958.786865015,-994812.722555545],[-340865.741054511,-992300.005228251],[-342509.488854784,-988881.91340958],[-345325.387696331,-986621.845757984],[-348354.903717,-984788.098556224],[-353370.600026566,-983832.189732435],[-366677.9065106,-989713.442403571],[-381308.67697851,-993644.278984853],[-386048.58799054,-993038.102078345],[-394020.240594272,-989714.314681328],[-404559.96427707,-984091.222154755],[-410826.064758872,-979683.638887757],[-415891.238631707,-977704.971530676],[-423719.290385192,-974483.766951312],[-431248.784620829,-973213.152785218],[-437122.904076817,-970857.022997443],[-444060.088484067,-969419.275002957],[-447234.756349965,-966559.733401117],[-449860.246339521,-966533.504819414],[-470546.939463806,-959560.82603034],[-474825.983933445,-960569.365286018],[-480100.600879141,-962063.456826469],[-487708.878630979,-962478.905617731],[-492691.549147872,-961904.590094888],[-508185.848272988,-957298.387205547],[-511687.555642549,-955244.498898082],[-520911.221610588,-954854.489576609],[-531873.66849203,-953263.135724329],[-539959.056363882,-950364.808982733],[-544112.872928349,-945666.384008732],[-548415.808178655,-941057.117572303],[-553646.204229286,-937518.545649007],[-561158.748486031,-933963.897264104],[-569210.143925863,-932511.361288993],[-597091.638105678,-934792.618584339],[-604779.108251832,-932825.646069359],[-615240.002974165,-929898.073583769],[-626111.033747536,-929417.402304793],[-626882.54912018,-929282.989989699],[-627960.517261167,-929414.874960798],[-632640.499376021,-928663.184896687],[-641805.443349296,-927102.68493463],[-654533.318799192,-923818.890523293],[-691295.485187774,-913786.75898745],[-696149.868873251,-912568.82998114],[-700803.719446554,-911333.63401215],[-722093.029572382,-905199.219738293],[-726656.559593404,-901105.082166024],[-730973.339967641,-898908.754305918],[-229675.316578143,-1109784.31512831],[-230457.101281106,-1109847.02139603],[-232562.931887238,-1110094.44705976],[-234306.079537844,-1109870.6101174]]]}] \ No newline at end of file From 4816815401e17be4eea3a7969d472bfd231d3252 Mon Sep 17 00:00:00 2001 From: Annette Locke Date: Thu, 2 Feb 2023 14:56:16 -0800 Subject: [PATCH 70/75] Temp file for server test --- data/AreasAndLengths.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 data/AreasAndLengths.txt diff --git a/data/AreasAndLengths.txt b/data/AreasAndLengths.txt new file mode 100644 index 00000000..f58196f9 --- /dev/null +++ b/data/AreasAndLengths.txt @@ -0,0 +1,15 @@ +[ + { + "rings" : + [ + [[-117,34],[-116,34],[-117,33],[-117,34]], + [[-115,44],[-114,43],[-115,43],[-115,44]] + ] + }, + { + "rings" : + [ + [[32,17],[31,17],[30,17],[30,16],[32,17]] + ] + } +] \ No newline at end of file From e237fc0fe4a7fb43583dd335d58e1f23ab18ac4b Mon Sep 17 00:00:00 2001 From: Thomas Calmant Date: Mon, 13 Feb 2023 19:50:36 +0100 Subject: [PATCH 71/75] Added OSGi package information (#300) --- pom.xml | 58 +++++++++++++++++-- .../esri/core/geometry/ogc/package-info.java | 19 ++++++ .../com/esri/core/geometry/package-info.java | 19 ++++++ 3 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/esri/core/geometry/ogc/package-info.java create mode 100644 src/main/java/com/esri/core/geometry/package-info.java diff --git a/pom.xml b/pom.xml index 34e8318d..11b47dea 100755 --- a/pom.xml +++ b/pom.xml @@ -101,14 +101,23 @@ 2.9.6 4.12 0.9 + 7.0.0 2.3.1 2.2.1 3.0.0-M1 + 3.3.0 + 6.4.0 + + org.osgi + osgi.annotation + ${osgi.core.version} + provided + com.fasterxml.jackson.core jackson-core @@ -151,12 +160,49 @@ - maven-compiler-plugin - ${compiler.plugin.version} - - ${java.source.version} - ${java.target.version} - + maven-compiler-plugin + ${compiler.plugin.version} + + ${java.source.version} + ${java.target.version} + + + + biz.aQute.bnd + bnd-maven-plugin + ${bnd.version} + + + + bnd-process + + + + + + bnd.bnd + + + + + + org.apache.maven.plugins + maven-jar-plugin + ${jar.plugin.version} + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + true + org.apache.maven.plugins diff --git a/src/main/java/com/esri/core/geometry/ogc/package-info.java b/src/main/java/com/esri/core/geometry/ogc/package-info.java new file mode 100644 index 00000000..b6b69aa6 --- /dev/null +++ b/src/main/java/com/esri/core/geometry/ogc/package-info.java @@ -0,0 +1,19 @@ +/* + Copyright 2017-2023 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +@org.osgi.annotation.bundle.Export +@org.osgi.annotation.versioning.Version("2.2.4") +package com.esri.core.geometry.ogc; diff --git a/src/main/java/com/esri/core/geometry/package-info.java b/src/main/java/com/esri/core/geometry/package-info.java new file mode 100644 index 00000000..5a613f65 --- /dev/null +++ b/src/main/java/com/esri/core/geometry/package-info.java @@ -0,0 +1,19 @@ +/* + Copyright 2017-2023 Esri + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +@org.osgi.annotation.bundle.Export +@org.osgi.annotation.versioning.Version("2.2.4") +package com.esri.core.geometry; From d9ed3598b72029c9ebde024e0e616933cff81db2 Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Sun, 3 Sep 2023 19:20:56 +0200 Subject: [PATCH 72/75] Declare "com.esri.geometry.api" as Java Module Name. (#303) Also set version number to 2.2.5-SNAPSHOT on the assumption that other changes may be added before release. --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 11b47dea..472eb349 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 2.2.4 + 2.2.5-SNAPSHOT jar Esri Geometry API for Java @@ -179,6 +179,7 @@ Date: Sun, 5 Nov 2023 23:17:12 -0400 Subject: [PATCH 73/75] New test case added --- pom.xml | 6 ++ .../esri/core/geometry/TestEnvelope1D.java | 22 ++++++ .../core/geometry/TestIndexHashTable.java | 72 +++++++++++++++++++ .../com/esri/core/geometry/TestJSONUtils.java | 47 ++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 src/test/java/com/esri/core/geometry/TestEnvelope1D.java create mode 100644 src/test/java/com/esri/core/geometry/TestIndexHashTable.java create mode 100644 src/test/java/com/esri/core/geometry/TestJSONUtils.java diff --git a/pom.xml b/pom.xml index 472eb349..b59ca4a4 100755 --- a/pom.xml +++ b/pom.xml @@ -132,6 +132,12 @@ ${junit.version} test + + org.mockito + mockito-core + 3.12.4 + test + org.openjdk.jol jol-core diff --git a/src/test/java/com/esri/core/geometry/TestEnvelope1D.java b/src/test/java/com/esri/core/geometry/TestEnvelope1D.java new file mode 100644 index 00000000..4ecd8cbc --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestEnvelope1D.java @@ -0,0 +1,22 @@ +package com.esri.core.geometry; + +import junit.framework.TestCase; +import org.junit.Test; +public class TestEnvelope1D extends TestCase{ + @Test + public void testCalculateToleranceFromEnvelopeEmpty() { + Envelope1D envelope = new Envelope1D(); + envelope.setEmpty(); + double tolerance = envelope._calculateToleranceFromEnvelope(); + assertEquals(100.0 * NumberUtils.doubleEps(), tolerance, 0.0001); + } + + @Test + public void testCalculateToleranceFromEnvelopeNonEmpty() { + Envelope1D envelope = new Envelope1D(2.0, 4.0); + double tolerance = envelope._calculateToleranceFromEnvelope(); + assertEquals(2.220446049250313e-14, tolerance, 1e-10); + } + + +} diff --git a/src/test/java/com/esri/core/geometry/TestIndexHashTable.java b/src/test/java/com/esri/core/geometry/TestIndexHashTable.java new file mode 100644 index 00000000..36ec75ac --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestIndexHashTable.java @@ -0,0 +1,72 @@ +package com.esri.core.geometry; +import org.junit.Test; +import junit.framework.TestCase; +public class TestIndexHashTable extends TestCase{ + @Test + public void testAddElement() { + IndexHashTable.HashFunction hashFunction = new IndexHashTable.HashFunction() { + @Override + public int getHash(int element) { + return element % 10; // A simple hash function for testing + } + + @Override + public boolean equal(int element1, int element2) { + return element1 == element2; + } + + @Override + public int getHash(Object elementDescriptor) { + return ((Integer) elementDescriptor) % 10; + } + + @Override + public boolean equal(Object elementDescriptor, int element) { + return ((Integer) elementDescriptor) == element; + } + }; + + IndexHashTable hashTable = new IndexHashTable(10, hashFunction); + + int element1 = 5; + + int node1 = hashTable.addElement(element1); + + assertEquals(node1, hashTable.findNode(element1)); + } + + @Test + public void testDeleteElement() { + IndexHashTable.HashFunction hashFunction = new IndexHashTable.HashFunction() { + @Override + public int getHash(int element) { + return element % 10; // A simple hash function for testing + } + + @Override + public boolean equal(int element1, int element2) { + return element1 == element2; + } + + @Override + public int getHash(Object elementDescriptor) { + return ((Integer) elementDescriptor) % 10; + } + + @Override + public boolean equal(Object elementDescriptor, int element) { + return ((Integer) elementDescriptor) == element; + } + }; + + IndexHashTable hashTable = new IndexHashTable(10, hashFunction); + + int element1 = 5; + + int node1 = hashTable.addElement(element1); + + hashTable.deleteElement(element1); + assertEquals(IndexHashTable.nullNode(), hashTable.findNode(element1)); + } + +} diff --git a/src/test/java/com/esri/core/geometry/TestJSONUtils.java b/src/test/java/com/esri/core/geometry/TestJSONUtils.java new file mode 100644 index 00000000..86a29aff --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestJSONUtils.java @@ -0,0 +1,47 @@ +package com.esri.core.geometry; + +import org.junit.Test; +import junit.framework.TestCase; +import org.mockito.Mockito; +public class TestJSONUtils extends TestCase{ + + @Test + public void testReadDoubleWithFloatValue() { + JsonReader parser = Mockito.mock(JsonReader.class); + Mockito.when(parser.currentToken()).thenReturn(JsonReader.Token.VALUE_NUMBER_FLOAT); + Mockito.when(parser.currentDoubleValue()).thenReturn(3.14); + + double result = JSONUtils.readDouble(parser); + assertEquals(3.14, result, 0.0001); + } + + @Test + public void testReadDoubleWithIntValue() { + JsonReader parser = Mockito.mock(JsonReader.class); + Mockito.when(parser.currentToken()).thenReturn(JsonReader.Token.VALUE_NUMBER_INT); + Mockito.when(parser.currentIntValue()).thenReturn(42); + + double result = JSONUtils.readDouble(parser); + assertEquals(42.0, result, 0.0001); + } + + @Test + public void testReadDoubleWithNullValue() { + JsonReader parser = Mockito.mock(JsonReader.class); + Mockito.when(parser.currentToken()).thenReturn(JsonReader.Token.VALUE_NULL); + + double result = JSONUtils.readDouble(parser); + assertTrue(Double.isNaN(result)); + } + + @Test + public void testReadDoubleWithNaNString() { + JsonReader parser = Mockito.mock(JsonReader.class); + Mockito.when(parser.currentToken()).thenReturn(JsonReader.Token.VALUE_STRING); + Mockito.when(parser.currentString()).thenReturn("NaN"); + + double result = JSONUtils.readDouble(parser); + assertTrue(Double.isNaN(result)); + } + +} From bde380cb3305802f03114189a95a010e1ef93d60 Mon Sep 17 00:00:00 2001 From: "fabian.maysen" Date: Thu, 21 Mar 2024 12:17:21 -0300 Subject: [PATCH 74/75] make public the execute method in OperatorBuffer --- .../com/esri/core/geometry/OperatorBuffer.java | 2 +- .../com/esri/core/geometry/ogc/OGCGeometry.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/esri/core/geometry/OperatorBuffer.java b/src/main/java/com/esri/core/geometry/OperatorBuffer.java index 93c71b02..4150a9f9 100644 --- a/src/main/java/com/esri/core/geometry/OperatorBuffer.java +++ b/src/main/java/com/esri/core/geometry/OperatorBuffer.java @@ -81,7 +81,7 @@ public abstract Geometry execute(Geometry inputGeometry, *Note that max_deviation can be exceeded because geometry is generalized with 0.25 * real_deviation, also input segments closer than 0.25 * real_deviation are *snapped to a point. */ - abstract GeometryCursor execute(GeometryCursor input_geometries, SpatialReference sr, double[] distances, double max_deviation, int max_vertices_in_full_circle, boolean b_union, ProgressTracker progress_tracker); + public abstract GeometryCursor execute(GeometryCursor input_geometries, SpatialReference sr, double[] distances, double max_deviation, int max_vertices_in_full_circle, boolean b_union, ProgressTracker progress_tracker); public static OperatorBuffer local() { return (OperatorBuffer) OperatorFactoryLocal.getInstance().getOperator( diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index 17ef2f8f..fba49234 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -466,6 +466,21 @@ public OGCGeometry buffer(double distance) { return OGCGeometry.createFromEsriGeometry(cursor.next(), esriSR); } + public OGCGeometry buffer(double distance, int max_vertices_in_full_circle) { + OperatorBuffer op = (OperatorBuffer) OperatorFactoryLocal.getInstance() + .getOperator(Operator.Type.Buffer); + if (distance == 0) {// when distance is 0, return self (maybe we should + // create a copy instead). + return this; + } + + double d[] = { distance }; + com.esri.core.geometry.GeometryCursor cursor = op.execute( + getEsriGeometryCursor(), getEsriSpatialReference(), d, Double.NaN, max_vertices_in_full_circle, true, + null); + return OGCGeometry.createFromEsriGeometry(cursor.next(), esriSR); + } + public OGCGeometry centroid() { OperatorCentroid2D op = (OperatorCentroid2D) OperatorFactoryLocal.getInstance() .getOperator(Operator.Type.Centroid2D); From 81eddaa4b6a3df6d0fb3898f2a2e7078e1073492 Mon Sep 17 00:00:00 2001 From: "fabian.maysen" Date: Tue, 16 Apr 2024 10:51:37 -0300 Subject: [PATCH 75/75] add max_deviation parameter in buffer method --- src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java index fba49234..a6fdeaa9 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -466,7 +466,7 @@ public OGCGeometry buffer(double distance) { return OGCGeometry.createFromEsriGeometry(cursor.next(), esriSR); } - public OGCGeometry buffer(double distance, int max_vertices_in_full_circle) { + public OGCGeometry buffer(double distance, int max_vertices_in_full_circle, double max_deviation) { OperatorBuffer op = (OperatorBuffer) OperatorFactoryLocal.getInstance() .getOperator(Operator.Type.Buffer); if (distance == 0) {// when distance is 0, return self (maybe we should @@ -476,7 +476,7 @@ public OGCGeometry buffer(double distance, int max_vertices_in_full_circle) { double d[] = { distance }; com.esri.core.geometry.GeometryCursor cursor = op.execute( - getEsriGeometryCursor(), getEsriSpatialReference(), d, Double.NaN, max_vertices_in_full_circle, true, + getEsriGeometryCursor(), getEsriSpatialReference(), d, max_deviation, max_vertices_in_full_circle, true, null); return OGCGeometry.createFromEsriGeometry(cursor.next(), esriSR); }

?@Ib4$R$ZbA6MIsF(ZEk4Ii=sfRBa)&Yo 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�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 TY(h;@!?}i$7z!3V8^-w`q)kqw diff --git a/build.xml b/build.xml index 5cf6c1b8..a4bc51b1 100644 --- a/build.xml +++ b/build.xml @@ -14,10 +14,14 @@ - + + + - + + + diff --git a/pom.xml b/pom.xml index f9e62a0c..d55f9fcf 100755 --- a/pom.xml +++ b/pom.xml @@ -98,9 +98,9 @@ 1.6 - 2.6.5 + 2.9.4 4.12 - 0.2 + 0.9 2.3.1 @@ -115,14 +115,14 @@ ${jackson.version} false + + junit junit ${junit.version} test - - org.openjdk.jol jol-core diff --git a/src/main/java/com/esri/core/geometry/CombineOperator.java b/src/main/java/com/esri/core/geometry/CombineOperator.java index 43e5ac2c..e3d1bcc1 100644 --- a/src/main/java/com/esri/core/geometry/CombineOperator.java +++ b/src/main/java/com/esri/core/geometry/CombineOperator.java @@ -36,7 +36,8 @@ public interface CombineOperator { * Operation on two geometries, returning a third. Examples include * Intersection, Difference, and so forth. * - * @param geom1 and geom2 are the geometry instances to be operated on. + * @param geom1 is the geometry instance to be operated on. + * @param geom2 is the geometry instance to be operated on. * @param sr The spatial reference to get the tolerance value from. * When sr is null, the tolerance is calculated from the input geometries. * @param progressTracker ProgressTracker instance that is used to cancel the lengthy operation. Can be null. diff --git a/src/main/java/com/esri/core/geometry/Envelope.java b/src/main/java/com/esri/core/geometry/Envelope.java index ca884b55..98c46738 100644 --- a/src/main/java/com/esri/core/geometry/Envelope.java +++ b/src/main/java/com/esri/core/geometry/Envelope.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1118,28 +1118,28 @@ public void setYMax(double y) { m_envelope.ymax = y; } - @Override - public Geometry getBoundary() { - return Boundary.calculate(this, null); - } - - @Override - public void replaceNaNs(int semantics, double value) { - addAttribute(semantics); - if (isEmpty()) - return; - - int ncomps = VertexDescription.getComponentCount(semantics); - for (int i = 0; i < ncomps; i++) { - Envelope1D interval = queryInterval(semantics, i); - if (interval.isEmpty()) { - interval.vmin = value; - interval.vmax = value; - setInterval(semantics, i, interval); - } - } - } - + @Override + public Geometry getBoundary() { + return Boundary.calculate(this, null); + } + + @Override + public void replaceNaNs(int semantics, double value) { + addAttribute(semantics); + if (isEmpty()) + return; + + int ncomps = VertexDescription.getComponentCount(semantics); + for (int i = 0; i < ncomps; i++) { + Envelope1D interval = queryInterval(semantics, i); + if (interval.isEmpty()) { + interval.vmin = value; + interval.vmax = value; + setInterval(semantics, i, interval); + } + } + } + /** * The output of this method can be only used for debugging. It is subject to change without notice. */ diff --git a/src/main/java/com/esri/core/geometry/Envelope1D.java b/src/main/java/com/esri/core/geometry/Envelope1D.java index 96540895..c9d0d259 100644 --- a/src/main/java/com/esri/core/geometry/Envelope1D.java +++ b/src/main/java/com/esri/core/geometry/Envelope1D.java @@ -133,8 +133,10 @@ public boolean contains(double v) { /** * Returns True if the envelope contains the other envelope (boundary * inclusive). Note: Will return false if either envelope is empty. + * @param other The other envelope. + * @return Return true if this contains the other. */ - public boolean contains(/* const */Envelope1D other) /* const */ + public boolean contains(Envelope1D other) { return other.vmin >= vmin && other.vmax <= vmax; } diff --git a/src/main/java/com/esri/core/geometry/Envelope2D.java b/src/main/java/com/esri/core/geometry/Envelope2D.java index fa41db68..8e44dd33 100644 --- a/src/main/java/com/esri/core/geometry/Envelope2D.java +++ b/src/main/java/com/esri/core/geometry/Envelope2D.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -131,6 +131,7 @@ public Envelope2D getInflated(double dx, double dy) { /** * Sets the envelope from the array of points. The envelope will be set to * empty if the array is null. + * @param points The points to set the envelope from. No element in the array can be null. */ public void setFromPoints(Point2D[] points) { if (points == null || points.length == 0) { @@ -198,6 +199,8 @@ else if (ymax < y) /** * Merges a point with this envelope without checking if the envelope is * empty. Use with care. + * @param x The x coord of the point + * @param y the y coord in the point */ public void mergeNE(double x, double y) { if (xmin > x) @@ -258,6 +261,7 @@ public void zoom(double factorX, double factorY) { /** * Checks if this envelope intersects the other. + * @param other The other envelope. * @return True if this envelope intersects the other. */ public boolean isIntersecting(Envelope2D other) { @@ -274,6 +278,7 @@ public boolean isIntersecting(Envelope2D other) { /** * Checks if this envelope intersects the other assuming neither one is empty. + * @param other The other envelope. * @return True if this envelope intersects the other. Assumes this and * other envelopes are not empty. */ @@ -289,6 +294,10 @@ public boolean isIntersectingNE(Envelope2D other) { /** * Checks if this envelope intersects the other. + * @param xmin_ + * @param ymin_ + * @param xmax_ + * @param ymax_ * @return True if this envelope intersects the other. */ public boolean isIntersecting(double xmin_, double ymin_, double xmax_, double ymax_) { @@ -307,7 +316,7 @@ public boolean isIntersecting(double xmin_, double ymin_, double xmax_, double y /** * Intersects this envelope with the other and stores result in this * envelope. - * + * @param other The other envelope. * @return True if this envelope intersects the other, otherwise sets this * envelope to empty state and returns False. */ @@ -370,6 +379,7 @@ public Point2D queryCorner(int index) { /** * Queries corners into a given array. The array length must be at least * 4. Starts from the lower left corner and goes clockwise. + * @param corners The array of four points. */ public void queryCorners(Point2D[] corners) { if ((corners == null) || (corners.length < 4)) @@ -399,6 +409,7 @@ public void queryCorners(Point2D[] corners) { * Queries corners into a given array in reversed order. The array length * must be at least 4. Starts from the lower left corner and goes * counterclockwise. + * @param corners The array of four points. */ public void queryCornersReversed(Point2D[] corners) { if (corners == null || ((corners != null) && (corners.length < 4))) @@ -500,6 +511,8 @@ public double getHeight() { /** * Moves the Envelope by given distance. + * @param dx + * @param dy */ public void move(double dx, double dy) { if (isEmpty()) @@ -558,6 +571,7 @@ public void queryUpperRight(Point2D pt) { /** * Returns True if this envelope is valid (empty, or has xmin less or equal * to xmax, or ymin less or equal to ymax). + * @return True if the envelope is valid. */ public boolean isValid() { return isEmpty() || (xmin <= xmax && ymin <= ymax); @@ -621,6 +635,8 @@ public boolean contains(double x, double y) { /** * Returns True if the envelope contains the other envelope (boundary * inclusive). + * @param other The other envelope. + * @return True if this contains the other. */ public boolean contains(Envelope2D other) {// Note: Will return False, if // either envelope is empty. @@ -630,7 +646,10 @@ public boolean contains(Envelope2D other) {// Note: Will return False, if /** * Returns True if the envelope contains the point (boundary exclusive). - */ + * @param x + * @param y + * @return True if this contains the point. + * */ public boolean containsExclusive(double x, double y) { // Note: This will return False, if envelope is empty, thus no need to // call is_empty(). @@ -647,6 +666,8 @@ public boolean containsExclusive(Point2D pt) { /** * Returns True if the envelope contains the other envelope (boundary * exclusive). + * @param other The other envelope + * @return True if this contains the other, boundary exclusive. */ boolean containsExclusive(Envelope2D other) { // Note: This will return False, if either envelope is empty, thus no @@ -1075,8 +1096,10 @@ public boolean isPointOnBoundary(Point2D pt, double tolerance) { /** * Calculates minimum distance from this envelope to the other. * Returns 0 for empty envelopes. + * @param other The other envelope. + * @return Returns the distance */ - public double distance(/* const */Envelope2D other) + public double distance(Envelope2D other) { return Math.sqrt(sqrDistance(other)); } @@ -1084,6 +1107,8 @@ public double distance(/* const */Envelope2D other) /** * Calculates minimum distance from this envelope to the point. * Returns 0 for empty envelopes. + * @param pt2D The other point. + * @return Returns the distance */ public double distance(Point2D pt2D) { @@ -1093,6 +1118,8 @@ public double distance(Point2D pt2D) /** * Calculates minimum squared distance from this envelope to the other. * Returns 0 for empty envelopes. + * @param other The other envelope. + * @return Returns the squared distance */ public double sqrDistance(Envelope2D other) { @@ -1122,6 +1149,11 @@ public double sqrDistance(Envelope2D other) /** * Calculates minimum squared distance from this envelope to the other. * Returns 0 for empty envelopes. + * @param xmin_ + * @param ymin_ + * @param xmax_ + * @param ymax_ + * @return Returns the squared distance. */ public double sqrDistance(double xmin_, double ymin_, double xmax_, double ymax_) { @@ -1178,6 +1210,8 @@ public double sqrMaxDistance(Envelope2D other) { /** * Calculates minimum squared distance from this envelope to the point. * Returns 0 for empty envelopes. + * @param pt2D The point. + * @return Returns the squared distance */ public double sqrDistance(Point2D pt2D) { diff --git a/src/main/java/com/esri/core/geometry/Geometry.java b/src/main/java/com/esri/core/geometry/Geometry.java index 01614b14..8a71a236 100644 --- a/src/main/java/com/esri/core/geometry/Geometry.java +++ b/src/main/java/com/esri/core/geometry/Geometry.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -167,7 +167,8 @@ protected static long estimateMemorySize(double[] attributes) } /** - * Returns the VertexDescription of this geomtry. + * Returns the VertexDescription of this geometry. + * @return VertexDescription */ public VertexDescription getDescription() { return m_description; @@ -176,6 +177,7 @@ public VertexDescription getDescription() { /** * Assigns the new VertexDescription by adding or dropping attributes. The * Geometry will have the src description as a result. + * @param src VertexDescription to assign. */ public void assignVertexDescription(VertexDescription src) { _touch(); @@ -191,6 +193,7 @@ public void assignVertexDescription(VertexDescription src) { * Merges the new VertexDescription by adding missing attributes from the * src. The Geometry will have a union of the current and the src * descriptions. + * @param src VertexDescription to merge. */ public void mergeVertexDescription(VertexDescription src) { _touch(); @@ -207,6 +210,8 @@ public void mergeVertexDescription(VertexDescription src) { /** * A shortcut for getDescription().hasAttribute() + * @param semantics The VertexDescription.Semantics to check. + * @return Return true if the attribute is present. */ public boolean hasAttribute(int semantics) { return getDescription().hasAttribute(semantics); @@ -215,7 +220,7 @@ public boolean hasAttribute(int semantics) { /** * Adds a new attribute to the Geometry. * - * @param semantics + * @param semantics The VertexDescription.Semantics to add. */ public void addAttribute(int semantics) { _touch(); @@ -231,6 +236,7 @@ public void addAttribute(int semantics) { * equivalent to setting the attribute to the default value for each vertex, * However, it is faster and the result Geometry has smaller memory * footprint and smaller size when persisted. + * @param semantics The VertexDescription.Semantics to drop. */ public void dropAttribute(int semantics) { _touch(); @@ -250,7 +256,10 @@ public void dropAllAttributes() { } /** - * Returns the min and max attribute values at the ordinate of the Geometry + * Returns the min and max attribute values at the ordinate of the Geometry. + * @param semantics The semantics of the interval. + * @param ordinate The ordinate of the interval. + * @return The interval. */ public abstract Envelope1D queryInterval(int semantics, int ordinate); @@ -262,19 +271,17 @@ public void dropAllAttributes() { */ public abstract void queryEnvelope(Envelope env); - // { - // Envelope2D e2d = new Envelope2D(); - // queryEnvelope2D(e2d); - // env.setEnvelope2D(e2d); - // } - /** * Returns tight bbox of the Geometry in X, Y plane. + * @param env + * The envelope to return the result in. */ public abstract void queryEnvelope2D(Envelope2D env); /** * Returns tight bbox of the Geometry in 3D. + * @param env + * The envelope to return the result in. */ abstract void queryEnvelope3D(Envelope3D env); @@ -282,6 +289,8 @@ public void dropAllAttributes() { * Returns the conservative bbox of the Geometry in X, Y plane. This is a * faster method than QueryEnvelope2D. However, the bbox could be larger * than the tight box. + * @param env + * The envelope to return the result in. */ public void queryLooseEnvelope2D(Envelope2D env) { queryEnvelope2D(env); @@ -291,6 +300,8 @@ public void queryLooseEnvelope2D(Envelope2D env) { * Returns tight conservative box of the Geometry in 3D. This is a faster * method than the QueryEnvelope3D. However, the box could be larger than * the tight box. + * @param env + * The envelope to return the result in. */ void queryLooseEnvelope3D(Envelope3D env) { queryEnvelope3D(env); @@ -328,13 +339,14 @@ void queryLooseEnvelope3D(Envelope3D env) { /** * Creates an instance of an empty geometry of the same type. + * @return The new instance. */ public abstract Geometry createInstance(); /** * Copies this geometry to another geometry of the same type. The result * geometry is an exact copy. - * + * @param dst The geometry instance to copy to. * @exception GeometryException * invalid_argument if the geometry is of different type. */ @@ -525,20 +537,22 @@ public Geometry copy() { return geom; } - /** - * Returns boundary of this geometry. - * - * Polygon and Envelope boundary is a Polyline. For Polyline and Line, the - * boundary is a Multi_point consisting of path endpoints. For Multi_point - * and Point NULL is returned. - */ - public abstract Geometry getBoundary(); - + /** + * Returns boundary of this geometry. + * + * Polygon and Envelope boundary is a Polyline. For Polyline and Line, the + * boundary is a Multi_point consisting of path end points. For Multi_point and + * Point null is returned. + * @return The boundary geometry. + */ + public abstract Geometry getBoundary(); + /** * Replaces NaNs in the attribute with the given value. * If the geometry is not empty, it adds the attribute if geometry does not have it yet, and replaces the values. * If the geometry is empty, it adds the attribute and does not set any values. - * + * @param semantics The semantics for which to replace the NaNs. + * @param value The value to replace NaNs with. */ public abstract void replaceNaNs(int semantics, double value); @@ -629,30 +643,31 @@ public String toString() { } } - /** - *Returns count of geometry vertices: - *1 for Point, 4 for Envelope, get_point_count for MultiVertexGeometry types, - *2 for segment types - *Returns 0 if geometry is empty. - */ - public static int vertex_count(Geometry geom) { - Geometry.Type gt = geom.getType(); - if (Geometry.isMultiVertex(gt.value())) - return ((MultiVertexGeometry)geom).getPointCount(); + /** + * Returns count of geometry vertices: 1 for Point, 4 for Envelope, + * get_point_count for MultiVertexGeometry types, 2 for segment types Returns 0 + * if geometry is empty. + * @param geom The geometry to get the vertex count for. + * @return The vertex count. + */ + public static int vertex_count(Geometry geom) { + Geometry.Type gt = geom.getType(); + if (Geometry.isMultiVertex(gt.value())) + return ((MultiVertexGeometry) geom).getPointCount(); - if (geom.isEmpty()) - return 0; + if (geom.isEmpty()) + return 0; - if (gt == Geometry.Type.Envelope) - return 4; + if (gt == Geometry.Type.Envelope) + return 4; - if (gt == Geometry.Type.Point) - return 1; + if (gt == Geometry.Type.Point) + return 1; - if (Geometry.isSegment(gt.value())) - return 2; + if (Geometry.isSegment(gt.value())) + return 2; + + throw new GeometryException("missing type"); + } - throw new GeometryException("missing type"); - } - } diff --git a/src/main/java/com/esri/core/geometry/GeometryEngine.java b/src/main/java/com/esri/core/geometry/GeometryEngine.java index 6f729cea..99466fd2 100644 --- a/src/main/java/com/esri/core/geometry/GeometryEngine.java +++ b/src/main/java/com/esri/core/geometry/GeometryEngine.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2017 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -88,8 +88,6 @@ public static MapGeometry jsonToGeometry(JsonReader json) { * reference). * @return The MapGeometry instance containing the imported geometry and its * spatial reference. - * @throws IOException - * @throws JsonParseException */ public static MapGeometry jsonToGeometry(String json) { MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json); @@ -153,8 +151,6 @@ public static String geometryToGeoJson(Geometry geometry) { * reference). * @return The MapGeometry instance containing the imported geometry and its * spatial reference. - * @throws IOException - * @throws JsonParseException */ public static MapGeometry geoJsonToGeometry(String json, int importFlags, Geometry.Type type) { MapGeometry geom = OperatorImportFromGeoJson.local().execute(importFlags, type, json, null); @@ -254,7 +250,7 @@ public static byte[] geometryToEsriShape(Geometry geometry) { * @param geometryType The required type of the Geometry to be imported. Use Geometry.Type.Unknown if the geometry type needs to be determined from the WKT context. * @return The geometry. * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the WKT contains a geometry that cannot be converted to the given geometryType. - * @throws IllegalArgument exception if an error is found while parsing the WKT string. + * @throws IllegalArgumentException if an error is found while parsing the WKT string. */ public static Geometry geometryFromWkt(String wkt, int importFlags, Geometry.Type geometryType) { diff --git a/src/main/java/com/esri/core/geometry/MapGeometry.java b/src/main/java/com/esri/core/geometry/MapGeometry.java index d7161d52..dbd90646 100644 --- a/src/main/java/com/esri/core/geometry/MapGeometry.java +++ b/src/main/java/com/esri/core/geometry/MapGeometry.java @@ -1,5 +1,5 @@ /* - Copyright 1995-2015 Esri + Copyright 1995-2018 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,6 +25,8 @@ package com.esri.core.geometry; +import static com.esri.core.geometry.SizeOf.SIZE_OF_MAPGEOMETRY; + import java.io.Serializable; /** @@ -132,6 +134,22 @@ public boolean equals(Object other) { return true; } + /** + * Returns an estimate of this object size in bytes. + *