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/.gitignore b/.gitignore index f31512c4..f2a3f602 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,15 @@ bin/ results/ javadoc/ +depfiles/ +DepFiles/ esri-geometry-api.jar .project .classpath description.jardesc *.bak *.properties +*.zip # Intellij project files *.iml @@ -34,3 +37,6 @@ ehthumbs.db Thumbs.db target/* /bin/ +/target/ + +.metadata/ diff --git a/.travis.yml b/.travis.yml index 7406d2b7..2113e3d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,9 @@ language: java jdk: - - openjdk6 - - openjdk7 - - oraclejdk7 + - openjdk9 + - openjdk10 + - openjdk14 +# - oraclejdk9 + - oraclejdk11 notifications: - email: false \ No newline at end of file + email: false 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 145fc489..00000000 Binary files a/DepFiles/public/jackson-core-asl-1.9.11.jar and /dev/null differ diff --git a/DepFiles/public/java-json.jar b/DepFiles/public/java-json.jar deleted file mode 100644 index 35f1446b..00000000 Binary files a/DepFiles/public/java-json.jar and /dev/null differ diff --git a/DepFiles/unittest/junit-4.8.2.jar b/DepFiles/unittest/junit-4.8.2.jar deleted file mode 100644 index 5b4bb849..00000000 Binary files a/DepFiles/unittest/junit-4.8.2.jar and /dev/null differ diff --git a/README.md b/README.md index d6d243c1..d64e0db5 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: @@ -23,20 +24,20 @@ The project is also available as a [Maven](http://maven.apache.org/) dependency: com.esri.geometry esri-geometry-api - 1.2.1 + 2.2.4 ``` ## 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. ## 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 @@ -53,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-2017 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/build.xml b/build.xml index 14f0f909..49f70b58 100644 --- a/build.xml +++ b/build.xml @@ -14,11 +14,15 @@ + + + - - - + + + + @@ -82,14 +86,14 @@ - + - + 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 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 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 diff --git a/pom.xml b/pom.xml index 01d43877..b59ca4a4 100755 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ com.esri.geometry esri-geometry-api - 1.2.1 + 2.2.5-SNAPSHOT jar Esri Geometry API for Java @@ -94,37 +94,56 @@ UTF-8 - 1.6 - 1.6 + 1.7 + 1.7 - 20140107 - 1.9.13 + 2.9.6 4.12 + 0.9 + 7.0.0 2.3.1 2.2.1 - 2.9 + 3.0.0-M1 + 3.3.0 + 6.4.0 - org.json - json - ${json.version} + org.osgi + osgi.annotation + ${osgi.core.version} + provided - org.codehaus.jackson - jackson-core-asl + com.fasterxml.jackson.core + jackson-core ${jackson.version} + false + + junit junit ${junit.version} test + + org.mockito + mockito-core + 3.12.4 + test + + + org.openjdk.jol + jol-core + ${jol.version} + test + @@ -147,12 +166,50 @@ - 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 @@ -190,7 +247,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/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 bbf40fde..889121d2 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. @@ -26,19 +26,24 @@ 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 { - 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 +59,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) @@ -169,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) { @@ -337,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/AttributeStreamOfFloat.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfFloat.java index 1e90b35b..95ef8c5f 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. @@ -26,12 +26,15 @@ 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; - float[] m_buffer = null; - int m_size; +final class AttributeStreamOfFloat extends AttributeStreamBase { + private float[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +56,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) @@ -141,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; @@ -314,7 +327,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..987ffae3 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. @@ -26,12 +26,15 @@ 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; - short[] m_buffer = null; - int m_size; +final class AttributeStreamOfInt16 extends AttributeStreamBase { + private short[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +56,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) @@ -141,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; @@ -299,7 +312,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..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-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. @@ -26,15 +26,24 @@ package com.esri.core.geometry; 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; -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; - int[] m_buffer = null; - int m_size; +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)// only in Java + public void reserve(int reserve) { if (reserve <= 0) return; @@ -54,6 +63,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) @@ -154,6 +167,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; @@ -352,7 +371,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; @@ -581,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]; @@ -715,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/AttributeStreamOfInt64.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt64.java index 62516ea2..99376590 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. @@ -26,12 +26,15 @@ 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; - long[] m_buffer = null; - int m_size; +final class AttributeStreamOfInt64 extends AttributeStreamBase { + private long[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +56,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) @@ -141,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; @@ -299,7 +312,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..a93d154a 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. @@ -26,12 +26,16 @@ 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 { - byte[] m_buffer = null; - int m_size; + private byte[] m_buffer = null; + private int m_size; public int size() { return m_size; @@ -53,6 +57,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) @@ -148,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; @@ -350,7 +364,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/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/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/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/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/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; // != 0) { return m_attributes[getEndPointOffset(m_description, end_point) + m_description.getPointAttributeOffset_(attribute_index) @@ -637,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 @@ -647,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); @@ -726,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; @@ -742,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]; @@ -776,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; @@ -1007,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; @@ -1022,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]); } @@ -1110,28 +1098,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..e000ef0a 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; } @@ -223,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 172619dd..5c8bebf5 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. @@ -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; @@ -124,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) { @@ -191,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) @@ -251,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) { @@ -267,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. */ @@ -282,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_) { @@ -300,13 +316,15 @@ 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. */ public boolean intersect(Envelope2D other) { - if (isEmpty() || other.isEmpty()) + if (isEmpty() || other.isEmpty()) { + setEmpty(); return false; + } if (other.xmin > xmin) xmin = other.xmin; @@ -363,6 +381,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)) @@ -392,6 +411,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))) @@ -493,6 +513,8 @@ public double getHeight() { /** * Moves the Envelope by given distance. + * @param dx + * @param dy */ public void move(double dx, double dy) { if (isEmpty()) @@ -551,6 +573,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); @@ -614,6 +637,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. @@ -623,7 +648,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(). @@ -640,6 +668,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 @@ -669,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; } @@ -1068,8 +1089,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)); } @@ -1077,6 +1100,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) { @@ -1086,6 +1111,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) { @@ -1115,6 +1142,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_) { @@ -1171,6 +1203,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/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/Geometry.java b/src/main/java/com/esri/core/geometry/Geometry.java index 68e93671..d108d328 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. @@ -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. @@ -151,7 +151,24 @@ static public Geometry.Type intToType(int geometryType) public abstract int getDimension(); /** - * Returns the VertexDescription of this geomtry. + * 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 geometry. + * @return VertexDescription */ public VertexDescription getDescription() { return m_description; @@ -160,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(); @@ -175,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(); @@ -191,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); @@ -199,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(); @@ -215,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(); @@ -234,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); @@ -246,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); @@ -266,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); @@ -275,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); @@ -312,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. */ @@ -428,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; @@ -509,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); @@ -613,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/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/GeometryEngine.java b/src/main/java/com/esri/core/geometry/GeometryEngine.java index 7bed73ea..99466fd2 100644 --- a/src/main/java/com/esri/core/geometry/GeometryEngine.java +++ b/src/main/java/com/esri/core/geometry/GeometryEngine.java @@ -1,899 +1,908 @@ -/* - 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.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; - -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.json.JSONException; - -/** - * 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, 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) throws JsonParseException, IOException { - 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); - } - - /** - * 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); - } - - /** - * 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. - * - * 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-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.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. + */ + 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. + */ + 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 IllegalArgumentException 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/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 83% rename from src/main/java/com/esri/core/geometry/JsonParserCursor.java rename to src/main/java/com/esri/core/geometry/JsonReaderCursor.java index 1a1f14f3..8e0f16de 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,19 @@ email: contracts@esri.com */ -package com.esri.core.geometry; -import org.codehaus.jackson.JsonParser; +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/Line.java b/src/main/java/com/esri/core/geometry/Line.java index 4eccd513..ce7b7b23 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; @@ -540,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/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. + *

+ * 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/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 -} diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java index f6d606bb..d70e5c5d 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 java.util.ArrayList; +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,32 @@ 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 != 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); + + if (m_vertexAttributes != null) { + for (int i = 0; i < m_vertexAttributes.length; i++) { + size += m_vertexAttributes[i].estimateMemorySize(); + } + } + + if (m_accelerators != null) { + size += m_accelerators.estimateMemorySize(); + } + + return size; + } + public boolean hasNonLinearSegments() { return m_curveParamwritePoint > 0; } @@ -2108,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 @@ -2561,30 +2593,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/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/MultiVertexGeometryImpl.java b/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java index 6e2694c7..e045aa2a 100644 --- a/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java +++ b/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java @@ -63,52 +63,34 @@ public interface GeometryXSimple { protected abstract void _verifyStreamsImpl(); public interface DirtyFlags { - public static final int DirtyIsKnownSimple = 1; // !<0 when IsWeakSimple - // flag is valid - public static final int IsWeakSimple = 2; // ! 0) { builder.append(buffer, 0, read); } - stream.close(); jsonString = builder.toString(); } catch (Exception ex) { } - - JsonFactory jf = new JsonFactory(); - JsonParser jp = null; - try { - jp = jf.createJsonParser(jsonString); - jp.nextToken(); - } catch (Exception ex) { + finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } } - MapGeometry mapGeom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jp); + + MapGeometry mapGeom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jsonString); return mapGeom; } @@ -288,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); } diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java index 88cb4653..2a25215d 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 @@ -39,11 +34,11 @@ 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 */ - 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. @@ -54,10 +49,9 @@ 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) throws JSONException; + public abstract MapGeometry execute(int import_flags, Geometry.Type type, String geoJsonString, ProgressTracker progress_tracker); /** * @@ -66,9 +60,8 @@ 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) 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/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/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/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/main/java/com/esri/core/geometry/Point.java b/src/main/java/com/esri/core/geometry/Point.java index 2343c5df..cc5b7042 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,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(); } /** @@ -66,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); @@ -89,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; } @@ -109,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); } /** @@ -129,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; } @@ -152,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; } /** @@ -194,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; } /** @@ -215,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); } /** @@ -280,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(); @@ -291,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); } @@ -308,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); } /** @@ -338,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(); @@ -348,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; } @@ -369,65 +340,79 @@ public int getDimension() { return 0; } + @Override + public long estimateMemorySize() + { + return SIZE_OF_POINT + estimateMemorySize(m_attributes); + } + @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 @@ -441,7 +426,7 @@ public void applyTransformation(Transformation2D transform) { } @Override - void applyTransformation(Transformation3D transform) { + public void applyTransformation(Transformation3D transform) { if (isEmptyImpl()) return; @@ -454,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 @@ -482,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 @@ -515,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 @@ -538,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. * @@ -564,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; } /** @@ -588,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; } @@ -609,31 +588,34 @@ 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; } - @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..95a46c66 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. @@ -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; @@ -435,7 +441,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. */ @@ -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/Polygon.java b/src/main/java/com/esri/core/geometry/Polygon.java index cb027357..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. @@ -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. * @@ -139,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 4c83a147..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. @@ -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/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..e9234bb5 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,19 @@ */ 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 { +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; + static final class QuadTreeIteratorImpl { /** * Resets the iterator to an starting state on the Quad_tree_impl. If @@ -771,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"); @@ -1248,19 +1274,25 @@ 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(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 +1301,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/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..c7def2d4 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,17 @@ public 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. + */ + 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) { @@ -138,10 +145,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(); @@ -150,6 +153,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; @@ -167,10 +171,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; @@ -192,19 +197,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; } } } @@ -305,12 +317,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); @@ -542,7 +552,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; @@ -559,4 +568,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/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; } } 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/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/SimpleRasterizer.java b/src/main/java/com/esri/core/geometry/SimpleRasterizer.java index de817443..8c6d7e46 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,15 @@ 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); } public SimpleRasterizer() { @@ -295,62 +298,96 @@ 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() + { + // 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/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; - } } 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..8d9f4c77 --- /dev/null +++ b/src/main/java/com/esri/core/geometry/SizeOf.java @@ -0,0 +1,144 @@ +/* + 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_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; + +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 = 40; + + 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 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); + } + + 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); + } + + 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/SpatialReference.java b/src/main/java/com/esri/core/geometry/SpatialReference.java index 39b1e90a..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-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. @@ -24,14 +24,10 @@ package com.esri.core.geometry; +import com.fasterxml.jackson.core.JsonParser; + 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; /** * A class that represents the spatial reference for the geometry. @@ -91,7 +87,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 +105,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/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/StridedIndexTypeCollection.java b/src/main/java/com/esri/core/geometry/StridedIndexTypeCollection.java index c54cfe9a..ae1f4dca 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,21 @@ */ package com.esri.core.geometry; +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. * 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; @@ -273,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/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]; 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..66eb1310 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java @@ -1,24 +1,79 @@ +/* + 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.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; +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.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.GeoJsonExportFlags; -import com.esri.core.geometry.OperatorExportToGeoJson; +import com.esri.core.geometry.VertexDescription; + 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 { + 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); @@ -26,6 +81,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; @@ -77,7 +137,19 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "GeometryCollection"; + return TYPE; + } + + @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 @@ -228,6 +300,7 @@ public boolean isSimple() { for (int i = 0, n = numGeometries(); i < n; i++) if (!geometryN(i).isSimple()) return false; + return true; } @@ -289,7 +362,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; @@ -338,8 +411,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"); + } + } - List geometries; + Geometry resultGeom = null; + if (!mp.isEmpty()) { + resultGeom = OperatorConvexHull.local().execute(mp, null); + } + + if (!polygon.isEmpty()) { + if (resultGeom != null && !resultGeom.isEmpty()) { + Geometry[] geoms = { resultGeom, polygon }; + resultGeom = OperatorConvexHull.local().execute( + new SimpleGeometryCursor(geoms), true, null).next(); + } + else { + resultGeom = OperatorConvexHull.local().execute(polygon, null); + } + } + + if (resultGeom == null) { + Point pt = new Point(); + if (vd != null) + pt.assignVertexDescription(vd); + + return new OGCPoint(pt, getEsriSpatialReference()); + } + + return OGCGeometry.createFromEsriGeometry(resultGeom, getEsriSpatialReference(), false); + } @Override public void setSpatialReference(SpatialReference esriSR_) { @@ -354,6 +478,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() { @@ -401,4 +539,420 @@ public int hashCode() { return hash; } + + @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) { + // 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; + } + } + } + + return minD; + } + + // + //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()) + 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(j); + if (!g1.disjoint(g2)) + return false; + } + } + + return true; + } + + @Override + public boolean contains(OGCGeometry another) { + if (isEmpty() || another.isEmpty()) + return false; + + if (this == another) + return true; + + return another.difference(this).isEmpty(); + } + + @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; + // 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(); + if (n != gc2.numGeometries()) { + return false; + } + + for (int i = 0; i < n; ++i) { + if (!gc1.geometryN(i).Equals(gc2.geometryN(i))) { + return false; + } + } + + 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) { + 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(); + for (Geometry geometry : geometries) { + for (Geometry otherGeometry : otherGeometries) { + if (geometry.getDimension() > otherGeometry.getDimension()) { + continue; //subtracting lower dimension has no effect. + } + + geometry = OperatorDifference.local().execute(geometry, otherGeometry, esriSR, null); + if (geometry.isEmpty()) { + break; + } + } + + if (!geometry.isEmpty()) { + result.add(OGCGeometry.createFromEsriGeometry(geometry, esriSR)); + } + } + + if (result.size() == 1) { + return result.get(0).reduceFromMulti(); + } + + return new OGCConcreteGeometryCollection(result, esriSR).flattenAndRemoveOverlaps(); + } + + @Override + public OGCGeometry intersection(OGCGeometry another) { + if (isEmpty() || another.isEmpty()) { + return new OGCConcreteGeometryCollection(esriSR); + } + + List geometries = toList(prepare_for_ops_(toGeometryCollection(this))); + List otherGeometries = toList(prepare_for_ops_(toGeometryCollection(another))); + + List result = new ArrayList(); + 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); + } + } + } + + if (result.size() == 1) { + return result.get(0).reduceFromMulti(); + } + + return new OGCConcreteGeometryCollection(result, esriSR).flattenAndRemoveOverlaps(); + } + + @Override + public OGCGeometry symDifference(OGCGeometry another) { + //TODO + throw new UnsupportedOperationException(); + } + + /** + * 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; + + int dimension = -1; + 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; + + //check strict order of geometry dimensions + int d = g.dimension(); + if (d <= dimension) + return false; + + dimension = d; + } + + return true; + } + + /** + * Flattens Geometry Collection. + * The result collection contains up to three geometries: + * an OGCMultiPoint, an OGCMultilineString, and an OGCMultiPolygon (in that order). + * @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. + * + * 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() { + + //flatten and crack/cluster + GeometryCursor cursor = OGCStructureInternal.prepare_for_ops_(flatten().getEsriGeometryCursor(), esriSR); + + //make sure geometries don't overlap + return new OGCConcreteGeometryCollection(removeOverlapsHelper_(toList(cursor)), esriSR); + } + + 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()) + continue; + + 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()) + break; + } + + if (current.isEmpty()) + continue; + + result.add(current); + } + + return new SimpleGeometryCursor(result); + } + + 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 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/main/java/com/esri/core/geometry/ogc/OGCCurve.java b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java index 2cad67f7..dd229e5e 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java @@ -1,7 +1,30 @@ +/* + 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; -import com.esri.core.geometry.Point; public abstract class OGCCurve extends OGCGeometry { public abstract double length(); @@ -18,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 04b2df77..a6fdeaa9 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java @@ -1,14 +1,28 @@ -package com.esri.core.geometry.ogc; +/* + Copyright 1995-2018 Esri -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; + 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 -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.json.JSONException; + 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; import com.esri.core.geometry.Envelope1D; @@ -16,6 +30,7 @@ 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; @@ -23,9 +38,10 @@ 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.OperatorExportToWkb; 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; @@ -36,12 +52,17 @@ 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; import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.VertexDescription; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; + /** * OGC Simple Feature Access specification v.1.2.1 * @@ -65,6 +86,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; @@ -216,17 +248,36 @@ 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 !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); + } 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, @@ -238,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, @@ -245,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, @@ -252,13 +313,14 @@ 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) { + if (another.geometryType() == OGCConcreteGeometryCollection.TYPE) { + return new OGCConcreteGeometryCollection(this, esriSR).contains(another); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.contains(geom1, geom2, @@ -266,6 +328,11 @@ public boolean contains(OGCGeometry another) { } public boolean overlaps(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.overlaps(geom1, geom2, @@ -273,6 +340,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, @@ -285,6 +357,14 @@ 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); + } + com.esri.core.geometry.Geometry geom1 = getEsriGeometry(); com.esri.core.geometry.Geometry geom2 = another.getEsriGeometry(); return com.esri.core.geometry.GeometryEngine.distance(geom1, geom2, @@ -386,15 +466,43 @@ public OGCGeometry buffer(double distance) { return OGCGeometry.createFromEsriGeometry(cursor.next(), esriSR); } - public OGCGeometry convexHull() { - com.esri.core.geometry.OperatorConvexHull op = (OperatorConvexHull) OperatorFactoryLocal - .getInstance().getOperator(Operator.Type.ConvexHull); + 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 + // create a copy instead). + return this; + } + + double d[] = { distance }; com.esri.core.geometry.GeometryCursor cursor = op.execute( - getEsriGeometryCursor(), true, null); + getEsriGeometryCursor(), getEsriSpatialReference(), d, max_deviation, 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); + + 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.GeometryCursor cursor = OperatorConvexHull.local().execute( + getEsriGeometryCursor(), false, null); return OGCGeometry.createFromEsriCursor(cursor, esriSR); } 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( @@ -404,6 +512,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().reduceFromMulti(); + } + OperatorUnion op = (OperatorUnion) OperatorFactoryLocal.getInstance() .getOperator(Operator.Type.Union); GeometryCursorAppend ap = new GeometryCursorAppend( @@ -414,6 +534,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( @@ -422,6 +546,11 @@ public OGCGeometry difference(OGCGeometry another) { } public OGCGeometry symDifference(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 createFromEsriGeometry( @@ -493,18 +622,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); @@ -676,6 +800,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/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..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,3 +1,27 @@ +/* + 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.ogc; import com.esri.core.geometry.Geometry; @@ -10,9 +34,14 @@ 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 { + static public String TYPE = "LineString"; + /** * The number of Points in this LineString. */ @@ -54,6 +83,9 @@ public OGCPoint pointN(int n) { @Override public boolean isClosed() { + if (isEmpty()) + return false; + return multiPath.isClosedPathInXYPlane(0); } @@ -89,7 +121,13 @@ public OGCPoint endPoint() { @Override public String geometryType() { - return "LineString"; + return TYPE; + } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_LINE_STRING + (multiPath != null ? multiPath.estimateMemorySize() : 0); } @Override @@ -113,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/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..e0608f61 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-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.ogc; import com.esri.core.geometry.GeoJsonExportFlags; @@ -12,26 +36,37 @@ 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 { + 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, esriSR, getEsriGeometry()); + } + @Override public ByteBuffer asBinary() { OperatorExportToWkb op = (OperatorExportToWkb) OperatorFactoryLocal @@ -48,7 +83,13 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "MultiLineString"; + return TYPE; + } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_MULTI_LINE_STRING + (polyline != null ? polyline.estimateMemorySize() : 0); } @Override @@ -82,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 a57c3b4e..b1c70a02 100644 --- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java +++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java @@ -1,21 +1,47 @@ -package com.esri.core.geometry.ogc; +/* + Copyright 1995-2017 Esri -import java.nio.ByteBuffer; + 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; -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; 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 static String TYPE = "MultiPoint"; + public int numGeometries() { return multiPoint.getPointCount(); } @@ -41,7 +67,13 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "MultiPoint"; + return TYPE; + } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_MULTI_POINT + (multiPoint != null ? multiPoint.estimateMemorySize() : 0); } /** @@ -101,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 878ea168..941bc7c2 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-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.ogc; import com.esri.core.geometry.GeoJsonExportFlags; @@ -12,15 +36,24 @@ import com.esri.core.geometry.SpatialReference; import com.esri.core.geometry.WkbExportFlags; import com.esri.core.geometry.WktExportFlags; + import java.nio.ByteBuffer; -public class OGCMultiPolygon extends OGCMultiSurface { +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(), @@ -38,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() { @@ -62,7 +95,13 @@ public OGCGeometry geometryN(int n) { @Override public String geometryType() { - return "MultiPolygon"; + return TYPE; + } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_MULTI_POLYGON + (polygon != null ? polygon.estimateMemorySize() : 0); } @Override @@ -96,5 +135,19 @@ public OGCGeometry convertToMulti() return this; } + @Override + public OGCGeometry reduceFromMulti() { + int n = numGeometries(); + if (n == 0) { + return new OGCPolygon(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/OGCMultiSurface.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java index fbb71977..5a36dd0e 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 { @@ -5,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/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java index b6a8f9e0..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,8 +1,29 @@ -package com.esri.core.geometry.ogc; +/* + Copyright 1995-2018 Esri -import java.nio.ByteBuffer; + 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.GeometryCursor; import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.MultiPoint; import com.esri.core.geometry.Operator; @@ -13,7 +34,13 @@ 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 static String TYPE = "Point"; + public OGCPoint(Point pt, SpatialReference sr) { point = pt; esriSR = sr; @@ -51,7 +78,13 @@ public double M() { @Override public String geometryType() { - return "Point"; + return TYPE; + } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_POINT + (point != null ? point.estimateMemorySize() : 0); } @Override @@ -82,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 5a038d2a..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,3 +1,27 @@ +/* + 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.ogc; import com.esri.core.geometry.Geometry; @@ -10,9 +34,14 @@ 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 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++) { @@ -82,7 +111,13 @@ public OGCMultiCurve boundary() { @Override public String geometryType() { - return "Polygon"; + return TYPE; + } + + @Override + public long estimateMemorySize() + { + return SIZE_OF_OGC_POLYGON + (polygon != null ? polygon.estimateMemorySize() : 0); } @Override @@ -108,5 +143,10 @@ public OGCGeometry convertToMulti() return new OGCMultiPolygon(polygon, esriSR); } + @Override + public OGCGeometry reduceFromMulti() { + return this; + } + Polygon polygon; } 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..989dfec8 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 { @@ -5,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/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; diff --git a/src/test/java/com/esri/core/geometry/GeometryUtils.java b/src/test/java/com/esri/core/geometry/GeometryUtils.java index c1af6866..2734db7c 100644 --- a/src/test/java/com/esri/core/geometry/GeometryUtils.java +++ b/src/test/java/com/esri/core/geometry/GeometryUtils.java @@ -1,12 +1,33 @@ +/* + 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; 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 +50,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/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..e60145bb 100755 --- a/src/test/java/com/esri/core/geometry/TestBuffer.java +++ b/src/test/java/com/esri/core/geometry/TestBuffer.java @@ -1,8 +1,34 @@ +/* + 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; import org.junit.Test; +import com.esri.core.geometry.ogc.OGCGeometry; + public class TestBuffer extends TestCase { @Override protected void setUp() throws Exception { @@ -365,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); + } + + + } } 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..3065ec9e --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestCentroid.java @@ -0,0 +1,169 @@ +/* + 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)); + 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/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 420718d4..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; @@ -5,8 +29,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 +259,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..d6da4af7 100644 --- a/src/test/java/com/esri/core/geometry/TestContains.java +++ b/src/test/java/com/esri/core/geometry/TestContains.java @@ -1,12 +1,39 @@ +/* + 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 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 +46,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/TestConvexHull.java b/src/test/java/com/esri/core/geometry/TestConvexHull.java index 62c59c2f..ee9c764e 100644 --- a/src/test/java/com/esri/core/geometry/TestConvexHull.java +++ b/src/test/java/com/esri/core/geometry/TestConvexHull.java @@ -1,8 +1,34 @@ +/* + 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; import org.junit.Test; +import com.esri.core.geometry.ogc.OGCGeometry; + public class TestConvexHull extends TestCase { @Override protected void setUp() throws Exception { @@ -968,5 +994,79 @@ 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); + } + } + @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); + } + } } diff --git a/src/test/java/com/esri/core/geometry/TestCut.java b/src/test/java/com/esri/core/geometry/TestCut.java index f67a4d1f..a388ff01 100644 --- a/src/test/java/com/esri/core/geometry/TestCut.java +++ b/src/test/java/com/esri/core/geometry/TestCut.java @@ -1,520 +1,560 @@ -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; - } -} +/* + 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; +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); + + } + + private 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); + } + + private 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); + } + + private 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); + } + + private 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); + } + + private 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); + } + + private 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); + } + + private 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); + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private 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; + } + + private static Polyline makePolygonCutter9() { + Polyline poly = new Polyline(); + + poly.startPath(5, -1); + poly.lineTo(5, 51); + + 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); + } +} diff --git a/src/test/java/com/esri/core/geometry/TestDifference.java b/src/test/java/com/esri/core/geometry/TestDifference.java index 455877e6..2ea73ffc 100644 --- a/src/test/java/com/esri/core/geometry/TestDifference.java +++ b/src/test/java/com/esri/core/geometry/TestDifference.java @@ -1,7 +1,29 @@ +/* + 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 junit.framework.TestCase; @@ -480,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/TestDistance.java b/src/test/java/com/esri/core/geometry/TestDistance.java index b531bb17..50399967 100644 --- a/src/test/java/com/esri/core/geometry/TestDistance.java +++ b/src/test/java/com/esri/core/geometry/TestDistance.java @@ -1,10 +1,30 @@ +/* + 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 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 +166,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/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/TestEnvelope.java b/src/test/java/com/esri/core/geometry/TestEnvelope.java new file mode 100644 index 00000000..9ee34862 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestEnvelope.java @@ -0,0 +1,179 @@ +/* + * 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 + /**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)); + 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)); + } + + @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()); + } + +} + 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/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/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java new file mode 100644 index 00000000..b1b40b22 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java @@ -0,0 +1,193 @@ +/* + 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.Geometry.GeometryAccelerationDegree; +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); + 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) { + return ClassLayout.parseClass(clazz).instanceSize(); + } + + @Test + 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 testAcceleratedGeometry() { + testGeometry(parseWkt("LINESTRING (0 1, 2 3, 4 5)")); + } + + @Test + public void testEmptyLineString() { + testGeometry(parseWkt("LINESTRING EMPTY")); + } + + @Test + public void testMultiLineString() { + testAcceleratedGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))")); + } + + @Test + public void testEmptyMultiLineString() { + testGeometry(parseWkt("MULTILINESTRING EMPTY")); + } + + @Test + public void testPolygon() { + testAcceleratedGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))")); + } + + @Test + public void testEmptyPolygon() { + testGeometry(parseWkt("POLYGON EMPTY")); + } + + @Test + public void testMultiPolygon() { + testAcceleratedGeometry(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); + } + + 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); + return geometry; + } +} diff --git a/src/test/java/com/esri/core/geometry/TestFailed.java b/src/test/java/com/esri/core/geometry/TestFailed.java index 9c7a915d..05bede19 100644 --- a/src/test/java/com/esri/core/geometry/TestFailed.java +++ b/src/test/java/com/esri/core/geometry/TestFailed.java @@ -1,64 +1,88 @@ -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); - } -} +/* + 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; +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/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 8777ec19..93185af9 100644 --- a/src/test/java/com/esri/core/geometry/TestGeodetic.java +++ b/src/test/java/com/esri/core/geometry/TestGeodetic.java @@ -1,104 +1,129 @@ -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); - */ - } - } +/* + 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; + +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/TestGeomToGeoJson.java b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java index 5ef3157e..83271d5b 100644 --- a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java +++ b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java @@ -22,17 +22,10 @@ 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.OGCConcreteGeometryCollection; +import com.esri.core.geometry.ogc.*; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; 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; @@ -163,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(); @@ -228,10 +235,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); @@ -243,10 +250,27 @@ 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); + } + - @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); @@ -337,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); @@ -386,16 +433,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 +472,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..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,564 +1,589 @@ -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; - -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 - .createJsonParser(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.createJsonParser(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.createJsonParser(pointEmptyString); - } - - 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()); - if (!checkResultSpatialRef(pointWebMerc2MP, - spatialReferenceWebMerc2.getLatestID(), 0)) { - bAnswer = false; - } - - { - 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()); - 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.createJsonParser(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.createJsonParser(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.createJsonParser(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 - .createJsonParser(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 - .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()); - - 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 - .createJsonParser(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 - .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()); - - 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 - .createJsonParser(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 - .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()); - 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.createJsonParser(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.createJsonParser(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 - .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()); - - 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; - } -} +/* + 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 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/TestImportExport.java b/src/test/java/com/esri/core/geometry/TestImportExport.java index 1138c082..73faed01 100644 --- a/src/test/java/com/esri/core/geometry/TestImportExport.java +++ b/src/test/java/com/esri/core/geometry/TestImportExport.java @@ -1,11 +1,33 @@ +/* + 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; 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 { @@ -22,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); @@ -1228,7 +1241,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 +1318,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); @@ -1733,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); 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/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/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)); + } + +} diff --git a/src/test/java/com/esri/core/geometry/TestJSonGeometry.java b/src/test/java/com/esri/core/geometry/TestJSonGeometry.java index 571a103e..62342524 100644 --- a/src/test/java/com/esri/core/geometry/TestJSonGeometry.java +++ b/src/test/java/com/esri/core/geometry/TestJSonGeometry.java @@ -1,47 +1,72 @@ -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]]"); - } - }; -} +/* + 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; +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 243f7c26..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,123 +1,148 @@ -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; - -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.createJsonParser(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; - } -} +/* + 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 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 a2214e5e..96f6343c 100644 --- a/src/test/java/com/esri/core/geometry/TestJsonParser.java +++ b/src/test/java/com/esri/core/geometry/TestJsonParser.java @@ -1,664 +1,575 @@ -package com.esri.core.geometry; - -import java.util.Hashtable; -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; - -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.createJsonParser(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); - } -} +/* + 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; +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/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 5b2ef6b3..b68f2fcc 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-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 junit.framework.TestCase; @@ -13,7 +37,6 @@ import com.esri.core.geometry.ogc.OGCPolygon; import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection; -import org.codehaus.jackson.JsonParseException; import org.junit.Test; import java.io.IOException; @@ -58,28 +81,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); } } @@ -850,15 +881,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)))")); } @@ -902,4 +925,135 @@ 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); + } + } + + @Test + public void testUnionPointWithEmptyLineString() { + assertUnion("POINT (1 2)", "LINESTRING EMPTY", "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("MULTILINESTRING ((1 2, 3 4))", "POLYGON EMPTY", "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 (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()); + } + + @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)"))); + 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()); + } + + @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); + } + + @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)"); + } + } 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..a64c67b5 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCCentroid.java @@ -0,0 +1,106 @@ +/* + 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)); + //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"); + } + + @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)); + 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(((OGCPoint)centroid).X(), expectedCentroid.getX(), 1e-13); + Assert.assertEquals(((OGCPoint)centroid).Y(), expectedCentroid.getY(), 1e-13); + } + + private static void assertEmptyCentroid(String wkt) { + OGCGeometry geometry = OGCGeometry.fromText(wkt); + OGCGeometry centroid = geometry.centroid(); + Assert.assertEquals(centroid, new OGCPoint(new Point(), geometry.getEsriSpatialReference())); + } +} 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..04a328bf --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCContains.java @@ -0,0 +1,88 @@ +/* + * 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))"); + } + + @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); + + 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)); + } +} + 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/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/TestOGCGeometryCollection.java b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java new file mode 100644 index 00000000..53007166 --- /dev/null +++ b/src/test/java/com/esri/core/geometry/TestOGCGeometryCollection.java @@ -0,0 +1,237 @@ +/* + * 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()); + } + + @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)); + } + + @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)); + } + + @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()); + } +} 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..8a98d5d1 --- /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 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; + +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) 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); + } +} 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); + } +} 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..c30f612f 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; @@ -21,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(); } diff --git a/src/test/java/com/esri/core/geometry/TestPolygon.java b/src/test/java/com/esri/core/geometry/TestPolygon.java index e34a14b7..2c4b0b4f 100644 --- a/src/test/java/com/esri/core/geometry/TestPolygon.java +++ b/src/test/java/com/esri/core/geometry/TestPolygon.java @@ -1,10 +1,33 @@ +/* + 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 junit.framework.TestCase; -import org.json.JSONException; import org.junit.Test; import com.esri.core.geometry.ogc.OGCGeometry; @@ -1205,7 +1228,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 +1244,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 +1255,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 +1266,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/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 5c00d8ad..4ecbf514 100644 --- a/src/test/java/com/esri/core/geometry/TestRelation.java +++ b/src/test/java/com/esri/core/geometry/TestRelation.java @@ -1,10 +1,33 @@ +/* + 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 junit.framework.TestCase; -import org.codehaus.jackson.JsonParseException; import org.junit.Test; import com.esri.core.geometry.Geometry.GeometryAccelerationDegree; @@ -5498,7 +5521,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/TestSerialization.java b/src/test/java/com/esri/core/geometry/TestSerialization.java index 4d736a8c..5f3796a1 100644 --- a/src/test/java/com/esri/core/geometry/TestSerialization.java +++ b/src/test/java/com/esri/core/geometry/TestSerialization.java @@ -1,380 +1,496 @@ -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"); - } - } - -} +/* + 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.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +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"); + } + } + + 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"); + } + + } +} diff --git a/src/test/java/com/esri/core/geometry/TestSimplify.java b/src/test/java/com/esri/core/geometry/TestSimplify.java index bdc2be0f..944d271d 100644 --- a/src/test/java/com/esri/core/geometry/TestSimplify.java +++ b/src/test/java/com/esri/core/geometry/TestSimplify.java @@ -1,1346 +1,1368 @@ -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.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParseException; -import org.junit.Test; - -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() throws IOException { - 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(); - 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, - f.createJsonParser(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, - f.createJsonParser(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, - f.createJsonParser(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, - f.createJsonParser(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, - f.createJsonParser(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, - f.createJsonParser(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, - f.createJsonParser(s)).getGeometry(); - boolean res = simplifyOpOGC.isSimpleOGC(g, null, true, null, null); - assertTrue(!res); - } - - } - - @Test - public void testFillRule() throws JsonParseException, IOException { - //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); - } - -} +/* + 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; +//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/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..77032413 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; @@ -16,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 }; @@ -33,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)); } } diff --git a/src/test/java/com/esri/core/geometry/TestWKBSupport.java b/src/test/java/com/esri/core/geometry/TestWKBSupport.java index 196e5e1e..dfbaba16 100644 --- a/src/test/java/com/esri/core/geometry/TestWKBSupport.java +++ b/src/test/java/com/esri/core/geometry/TestWKBSupport.java @@ -1,99 +1,119 @@ -package com.esri.core.geometry; - -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; - -//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() { - 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) { - } - - } - - @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}}"; - - JsonFactory factory = new JsonFactory(); - JsonParser parser = factory.createJsonParser(strPolygon1); - parser.nextToken(); - MapGeometry mapGeom = GeometryEngine.jsonToGeometry(parser); - 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); - - } - } +/* + 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 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); + + } + + @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)); + } +} 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 {