diff --git a/.gitignore b/.gitignore
index 7328fe5d..f2a3f602 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,8 @@
bin/
results/
javadoc/
+depfiles/
+DepFiles/
esri-geometry-api.jar
.project
.classpath
@@ -35,3 +37,6 @@ ehthumbs.db
Thumbs.db
target/*
/bin/
+/target/
+
+.metadata/
diff --git a/.travis.yml b/.travis.yml
index d1fa4fad..2113e3d7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,9 @@
language: java
jdk:
- - openjdk7
- - openjdk8
- - oraclejdk8
- - oraclejdk9
+ - openjdk9
+ - openjdk10
+ - openjdk14
+# - oraclejdk9
+ - oraclejdk11
notifications:
email: false
diff --git a/README.md b/README.md
index bcc099fe..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
- 2.1.0
+ 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-2018 Esri
+Copyright 2013-2019 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/build.xml b/build.xml
index a4bc51b1..49f70b58 100644
--- a/build.xml
+++ b/build.xml
@@ -14,7 +14,7 @@
-
+
@@ -86,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 0255ec18..b59ca4a4 100755
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
com.esri.geometry
esri-geometry-api
- 2.2.0-SNAPSHOT
+ 2.2.5-SNAPSHOT
jar
Esri Geometry API for Java
@@ -94,21 +94,30 @@
UTF-8
- 1.6
- 1.6
+ 1.7
+ 1.7
- 2.9.4
+ 2.9.6
4.12
0.9
+ 7.0.0
2.3.1
2.2.1
3.0.0-M1
+ 3.3.0
+ 6.4.0
+
+ org.osgi
+ osgi.annotation
+ ${osgi.core.version}
+ provided
+
com.fasterxml.jackson.core
jackson-core
@@ -123,6 +132,12 @@
${junit.version}
test
+
+ org.mockito
+ mockito-core
+ 3.12.4
+ test
+
org.openjdk.jol
jol-core
@@ -151,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
@@ -194,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/AttributeStreamOfDbl.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java
index 75d45a76..889121d2 100644
--- a/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java
+++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfDbl.java
@@ -352,7 +352,7 @@ public boolean equals(AttributeStreamBase other, int start, int end) {
end = size;
for (int i = start; i < end; i++)
- if (read(i) != _other.read(i))
+ if (!NumberUtils.isEqualNonIEEE(read(i), _other.read(i)))
return false;
return true;
diff --git a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java
index 1939bb0f..52d07517 100644
--- a/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java
+++ b/src/main/java/com/esri/core/geometry/AttributeStreamOfInt32.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -27,14 +27,20 @@
import com.esri.core.geometry.VertexDescription.Persistence;
+import java.io.IOException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
import java.util.Arrays;
import static com.esri.core.geometry.SizeOf.SIZE_OF_ATTRIBUTE_STREAM_OF_INT32;
import static com.esri.core.geometry.SizeOf.sizeOfIntArray;
-final class AttributeStreamOfInt32 extends AttributeStreamBase {
- private int[] m_buffer = null;
+final class AttributeStreamOfInt32 extends AttributeStreamBase implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ transient private int[] m_buffer = null;
private int m_size;
public void reserve(int reserve)
@@ -594,7 +600,6 @@ private void _selfWriteRangeImpl(int toElement, int count, int fromElement,
// reverse what we written
int j = toElement;
int offset = toElement + count - stride;
- int dj = stride;
for (int i = 0, n = count / 2; i < n; i++) {
for (int k = 0; k < stride; k++) {
int v = m_buffer[j + k];
@@ -728,4 +733,49 @@ void quicksort(int leftIn, int rightIn, IntComparator compare,
public void sort(int start, int end) {
Arrays.sort(m_buffer, start, end);
}
+
+ private void writeObject(java.io.ObjectOutputStream stream)
+ throws IOException {
+ stream.defaultWriteObject();
+ IntBuffer intBuf = null;
+ byte[] bytes = null;
+ for (int i = 0; i < m_size;) {
+ int n = Math.min(32, m_size - i);
+ if (bytes == null) {
+ bytes = new byte[n * 4]; //32 elements at a time
+ ByteBuffer buf = ByteBuffer.wrap(bytes);
+ intBuf = buf.asIntBuffer();
+ }
+ intBuf.rewind();
+ intBuf.put(m_buffer, i, n);
+ stream.write(bytes, 0, n * 4);
+ i += n;
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ m_buffer = new int[m_size];
+ IntBuffer intBuf = null;
+ byte[] bytes = null;
+ for (int i = 0; i < m_size;) {
+ int n = Math.min(32, m_size - i);
+ if (bytes == null) {
+ bytes = new byte[n * 4]; //32 elements at a time
+ ByteBuffer buf = ByteBuffer.wrap(bytes);
+ intBuf = buf.asIntBuffer();
+ }
+ stream.read(bytes, 0, n * 4);
+ intBuf.rewind();
+ intBuf.get(m_buffer, i, n);
+ i += n;
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private void readObjectNoData() throws ObjectStreamException {
+ m_buffer = new int[2];
+ m_size = 0;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/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/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)
@@ -645,7 +648,6 @@ void setAttributeAsDblImpl_(int end_point, int semantics, int ordinate,
throw new IllegalArgumentException();
addAttribute(semantics);
- _ensureAttributes();
int attribute_index = m_description.getAttributeIndex(semantics);
m_attributes[getEndPointOffset(m_description, end_point)
+ m_description.getPointAttributeOffset_(attribute_index) - 2
@@ -655,32 +657,17 @@ void setAttributeAsDblImpl_(int end_point, int semantics, int ordinate,
void _ensureAttributes() {
_touch();
if (m_attributes == null && m_description.getTotalComponentCount() > 2) {
- m_attributes = new double[(m_description.getTotalComponentCount() - 2) * 2];
+ int halfLength = m_description.getTotalComponentCount() - 2;
+ m_attributes = new double[halfLength * 2];
int offset0 = _getEndPointOffset(m_description, 0);
int offset1 = _getEndPointOffset(m_description, 1);
-
- int j = 0;
- for (int i = 1, n = m_description.getAttributeCount(); i < n; i++) {
- int semantics = m_description.getSemantics(i);
- int nords = VertexDescription.getComponentCount(semantics);
- double d = VertexDescription.getDefaultValue(semantics);
- for (int ord = 0; ord < nords; ord++)
- {
- m_attributes[offset0 + j] = d;
- m_attributes[offset1 + j] = d;
- j++;
- }
- }
+ System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, offset0, halfLength);
+ System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, offset1, halfLength);
}
}
@Override
protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
- if (m_attributes == null) {
- m_description = newDescription;
- return;
- }
-
if (newDescription.getTotalComponentCount() > 2) {
int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(newDescription, m_description);
@@ -734,8 +721,6 @@ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
throw new GeometryException(
"This operation was performed on an Empty Geometry.");
- // _ASSERT(endPoint == 0 || endPoint == 1);
-
if (semantics == Semantics.POSITION) {
if (endPoint != 0) {
return ordinate != 0 ? m_envelope.ymax : m_envelope.xmax;
@@ -750,7 +735,6 @@ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
int attributeIndex = m_description.getAttributeIndex(semantics);
if (attributeIndex >= 0) {
- _ensureAttributes();
return m_attributes[_getEndPointOffset(m_description, endPoint)
+ m_description._getPointAttributeOffset(attributeIndex)
- 2 + ordinate];
@@ -784,14 +768,10 @@ void _setAttributeAsDbl(int endPoint, int semantics, int ordinate,
throw new IndexOutOfBoundsException();
if (!hasAttribute(semantics)) {
- if (VertexDescription.isDefaultValue(semantics, value))
- return;
-
addAttribute(semantics);
}
int attributeIndex = m_description.getAttributeIndex(semantics);
- _ensureAttributes();
m_attributes[_getEndPointOffset(m_description, endPoint)
+ m_description._getPointAttributeOffset(attributeIndex) - 2
+ ordinate] = value;
@@ -1015,7 +995,7 @@ public boolean equals(Object _other) {
return false;
for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++)
- if (m_attributes[i] != other.m_attributes[i])
+ if (!NumberUtils.isEqualNonIEEE(m_attributes[i], other.m_attributes[i]))
return false;
return true;
@@ -1030,7 +1010,7 @@ public boolean equals(Object _other) {
public int hashCode() {
int hashCode = m_description.hashCode();
hashCode = NumberUtils.hash(hashCode, m_envelope.hashCode());
- if (!isEmpty() && m_attributes != null) {
+ if (!isEmpty()) {
for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++) {
hashCode = NumberUtils.hash(hashCode, m_attributes[i]);
}
diff --git a/src/main/java/com/esri/core/geometry/Envelope1D.java b/src/main/java/com/esri/core/geometry/Envelope1D.java
index c9d0d259..e000ef0a 100644
--- a/src/main/java/com/esri/core/geometry/Envelope1D.java
+++ b/src/main/java/com/esri/core/geometry/Envelope1D.java
@@ -225,7 +225,13 @@ public boolean equals(Object _other)
@Override
public int hashCode() {
- return NumberUtils.hash(NumberUtils.hash(vmin), vmax);
+ if (isEmpty()) {
+ return NumberUtils.hash(NumberUtils.TheNaN);
+ }
+
+ int hash = NumberUtils.hash(vmin);
+ hash = NumberUtils.hash(hash, vmax);
+ return hash;
}
}
diff --git a/src/main/java/com/esri/core/geometry/Envelope2D.java b/src/main/java/com/esri/core/geometry/Envelope2D.java
index 8e44dd33..5c8bebf5 100644
--- a/src/main/java/com/esri/core/geometry/Envelope2D.java
+++ b/src/main/java/com/esri/core/geometry/Envelope2D.java
@@ -321,8 +321,10 @@ public boolean isIntersecting(double xmin_, double ymin_, double xmax_, double y
* envelope to empty state and returns False.
*/
public boolean intersect(Envelope2D other) {
- if (isEmpty() || other.isEmpty())
+ if (isEmpty() || other.isEmpty()) {
+ setEmpty();
return false;
+ }
if (other.xmin > xmin)
xmin = other.xmin;
@@ -697,23 +699,14 @@ public boolean equals(Object _other) {
@Override
public int hashCode() {
-
- long bits = Double.doubleToLongBits(xmin);
- int hc = (int) (bits ^ (bits >>> 32));
-
- int hash = NumberUtils.hash(hc);
-
- bits = Double.doubleToLongBits(xmax);
- hc = (int) (bits ^ (bits >>> 32));
- hash = NumberUtils.hash(hash, hc);
-
- bits = Double.doubleToLongBits(ymin);
- hc = (int) (bits ^ (bits >>> 32));
- hash = NumberUtils.hash(hash, hc);
-
- bits = Double.doubleToLongBits(ymax);
- hc = (int) (bits ^ (bits >>> 32));
- hash = NumberUtils.hash(hash, hc);
+ if (isEmpty()) {
+ return NumberUtils.hash(NumberUtils.TheNaN);
+ }
+
+ int hash = NumberUtils.hash(xmin);
+ hash = NumberUtils.hash(hash, xmax);
+ hash = NumberUtils.hash(hash, ymin);
+ hash = NumberUtils.hash(hash, ymax);
return hash;
}
diff --git a/src/main/java/com/esri/core/geometry/Envelope3D.java b/src/main/java/com/esri/core/geometry/Envelope3D.java
index 3f64b053..6fa8b522 100644
--- a/src/main/java/com/esri/core/geometry/Envelope3D.java
+++ b/src/main/java/com/esri/core/geometry/Envelope3D.java
@@ -320,6 +320,22 @@ public boolean equals(Object _other) {
return true;
}
+
+ @Override
+ public int hashCode() {
+ if (isEmpty()) {
+ return NumberUtils.hash(NumberUtils.TheNaN);
+ }
+
+ int hash = NumberUtils.hash(xmin);
+ hash = NumberUtils.hash(hash, xmax);
+ hash = NumberUtils.hash(hash, ymin);
+ hash = NumberUtils.hash(hash, ymax);
+ hash = NumberUtils.hash(hash, zmin);
+ hash = NumberUtils.hash(hash, zmax);
+ return hash;
+ }
+
public void construct(Envelope1D xinterval, Envelope1D yinterval,
Envelope1D zinterval) {
if (xinterval.isEmpty() || yinterval.isEmpty()) {
diff --git a/src/main/java/com/esri/core/geometry/Geometry.java b/src/main/java/com/esri/core/geometry/Geometry.java
index 8a71a236..d108d328 100644
--- a/src/main/java/com/esri/core/geometry/Geometry.java
+++ b/src/main/java/com/esri/core/geometry/Geometry.java
@@ -456,7 +456,7 @@ public static int getDimensionFromType(int type) {
* @param type
* The integer value from geometry enumeration. You can use the
* method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry is a point.
+ * @return TRUE if the geometry is a point (a Point or a Multipoint).
*/
public static boolean isPoint(int type) {
return (type & 0x20) != 0;
diff --git a/src/main/java/com/esri/core/geometry/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 99466fd2..2ba61cf4 100644
--- a/src/main/java/com/esri/core/geometry/GeometryEngine.java
+++ b/src/main/java/com/esri/core/geometry/GeometryEngine.java
@@ -44,6 +44,7 @@ public class GeometryEngine {
/**
+ * @deprecated Use jsonToGeometry(String)
* Imports the MapGeometry from its JSON representation. M and Z values are
* not imported from JSON representation.
*
@@ -55,6 +56,7 @@ public class GeometryEngine {
* @return The MapGeometry instance containing the imported geometry and its
* spatial reference.
*/
+ @Deprecated
public static MapGeometry jsonToGeometry(JsonParser json) {
MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, new JsonParserReader(json));
return geom;
@@ -95,11 +97,11 @@ public static MapGeometry jsonToGeometry(String json) {
}
/**
- * Exports the specified geometry instance to it's JSON representation.
+ * Exports the specified geometry instance to its JSON representation.
*
* See OperatorExportToJson.
*
- * @see GeometryEngine#geometryToJson(SpatialReference spatialiReference,
+ * @see GeometryEngine#geometryToJson(SpatialReference spatialReference,
* Geometry geometry)
* @param wkid
* The spatial reference Well Known ID to be used for the JSON
@@ -114,7 +116,7 @@ public static String geometryToJson(int wkid, Geometry geometry) {
}
/**
- * Exports the specified geometry instance to it's JSON representation. M
+ * Exports the specified geometry instance to its JSON representation. M
* and Z values are not imported from JSON representation.
*
* See OperatorExportToJson.
@@ -177,7 +179,7 @@ public static String geometryToGeoJson(int wkid, Geometry geometry) {
}
/**
- * Exports the specified geometry instance to it's JSON representation.
+ * Exports the specified geometry instance to its JSON representation.
*
* See OperatorImportFromGeoJson.
*
diff --git a/src/main/java/com/esri/core/geometry/JsonParserReader.java b/src/main/java/com/esri/core/geometry/JsonParserReader.java
index 90427c63..5313c0ab 100644
--- a/src/main/java/com/esri/core/geometry/JsonParserReader.java
+++ b/src/main/java/com/esri/core/geometry/JsonParserReader.java
@@ -27,9 +27,10 @@
import com.fasterxml.jackson.core.*;
/**
- * A throw in JsonReader built around the Jackson JsonParser.
- *
+ * @deprecated Intended for internal use by geometry-api-java only.
+ * A throw-in JsonReader built around Jackson.
*/
+@Deprecated
public class JsonParserReader implements JsonReader {
private JsonParser m_jsonParser;
@@ -46,7 +47,7 @@ public static JsonReader createFromString(String str) {
try {
JsonFactory factory = new JsonFactory();
JsonParser jsonParser = factory.createParser(str);
-
+
jsonParser.nextToken();
return new JsonParserReader(jsonParser);
}
@@ -168,4 +169,3 @@ else if (t == Token.VALUE_FALSE)
throw new JsonGeometryException("Not a boolean");
}
}
-
diff --git a/src/main/java/com/esri/core/geometry/JsonReaderCursor.java b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java
index 94f72a30..8e0f16de 100644
--- a/src/main/java/com/esri/core/geometry/JsonReaderCursor.java
+++ b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java
@@ -19,21 +19,6 @@
380 New York Street
Redlands, California, USA 92373
- email: contracts@esri.com
- */
-/*
- COPYRIGHT 1995-2017 ESRI
-
- TRADE SECRETS: ESRI PROPRIETARY AND CONFIDENTIAL
- Unpublished material - all rights reserved under the
- Copyright Laws of the United States.
-
- For additional information, contact:
- Environmental Systems Research Institute, Inc.
- Attn: Contracts Dept
- 380 New York Street
- Redlands, California, USA 92373
-
email: contracts@esri.com
*/
diff --git a/src/main/java/com/esri/core/geometry/Line.java b/src/main/java/com/esri/core/geometry/Line.java
index 90b08561..ce7b7b23 100644
--- a/src/main/java/com/esri/core/geometry/Line.java
+++ b/src/main/java/com/esri/core/geometry/Line.java
@@ -548,6 +548,11 @@ public boolean equals(Object other) {
return _equalsImpl((Segment)other);
}
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
boolean equals(Line other) {
if (other == this)
return true;
diff --git a/src/main/java/com/esri/core/geometry/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 54ec0a5d..d70e5c5d 100644
--- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java
+++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java
@@ -66,8 +66,8 @@ public long estimateMemorySize()
+ (m_envelope != null ? m_envelope.estimateMemorySize() : 0)
+ (m_moveToPoint != null ? m_moveToPoint.estimateMemorySize() : 0)
+ (m_cachedRingAreas2D != null ? m_cachedRingAreas2D.estimateMemorySize() : 0)
- + m_paths.estimateMemorySize()
- + m_pathFlags.estimateMemorySize()
+ + (m_paths != null ? m_paths.estimateMemorySize() : 0)
+ + (m_pathFlags != null ? m_pathFlags.estimateMemorySize() : 0)
+ (m_segmentFlags != null ? m_segmentFlags.estimateMemorySize() : 0)
+ (m_segmentParamIndex != null ? m_segmentParamIndex.estimateMemorySize() : 0)
+ (m_segmentParams != null ? m_segmentParams.estimateMemorySize() : 0);
@@ -77,6 +77,11 @@ public long estimateMemorySize()
size += m_vertexAttributes[i].estimateMemorySize();
}
}
+
+ if (m_accelerators != null) {
+ size += m_accelerators.estimateMemorySize();
+ }
+
return size;
}
@@ -2128,27 +2133,34 @@ int getOGCPolygonCount() {
protected void _updateOGCFlags() {
if (_hasDirtyFlag(DirtyFlags.DirtyOGCFlags)) {
_updateRingAreas2D();
-
- int pathCount = getPathCount();
- if (pathCount > 0 && (m_pathFlags == null || m_pathFlags.size() < pathCount))
- m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
- .createByteStream(pathCount + 1);
-
- int firstSign = 1;
- for (int ipath = 0; ipath < pathCount; ipath++) {
- double area = m_cachedRingAreas2D.read(ipath);
- if (ipath == 0)
- firstSign = area > 0 ? 1 : -1;
- if (area * firstSign > 0.0)
- m_pathFlags.setBits(ipath,
- (byte) PathFlags.enumOGCStartPolygon);
- else
- m_pathFlags.clearBits(ipath,
- (byte) PathFlags.enumOGCStartPolygon);
- }
+ _updateOGCFlagsHelper();
_setDirtyFlag(DirtyFlags.DirtyOGCFlags, false);
}
}
+
+ private void _updateOGCFlagsHelper() {
+ int pathCount = getPathCount();
+ if (pathCount > 0 && (m_pathFlags == null || m_pathFlags.size() < pathCount))
+ m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase.createByteStream(pathCount + 1);
+
+ // firstSign is the sign of first ring.
+ // a first ring with non zero area defines the
+ // value. First zero area rings are written out as enumOGCStartPolygon.
+ int firstSign = 0;
+ for (int ipath = 0; ipath < pathCount; ipath++) {
+ double area = m_cachedRingAreas2D.read(ipath);
+ if (firstSign == 0) {
+ // if the first ring is inverted we assume that the
+ // whole polygon is inverted.
+ firstSign = MathUtils.sign(area);
+ }
+
+ if (area * firstSign > 0.0 || firstSign == 0)
+ m_pathFlags.setBits(ipath, (byte) PathFlags.enumOGCStartPolygon);
+ else
+ m_pathFlags.clearBits(ipath, (byte) PathFlags.enumOGCStartPolygon);
+ }
+ }
public int getPathIndexFromPointIndex(int pointIndex) {
int positionHint = m_currentPathIndex;// in case of multithreading
diff --git a/src/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) {
}
+ finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
MapGeometry mapGeom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, jsonString);
return mapGeom;
@@ -275,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/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 a421400f..cc5b7042 100644
--- a/src/main/java/com/esri/core/geometry/Point.java
+++ b/src/main/java/com/esri/core/geometry/Point.java
@@ -39,19 +39,24 @@ public class Point extends Geometry implements Serializable {
//We are using writeReplace instead.
//private static final long serialVersionUID = 2L;
- double[] m_attributes; // use doubles to store everything (long are bitcast)
+ private double m_x;
+ private double m_y;
+ private double[] m_attributes; // use doubles to store everything (long are bitcast)
/**
* Creates an empty 2D point.
*/
public Point() {
m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
+ m_x = NumberUtils.TheNaN;
+ m_y = NumberUtils.TheNaN;
}
public Point(VertexDescription vd) {
if (vd == null)
throw new IllegalArgumentException();
m_description = vd;
+ _setToDefault();
}
/**
@@ -68,6 +73,7 @@ public Point(double x, double y) {
m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
setXY(x, y);
}
+
public Point(Point2D pt) {
m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
setXY(pt);
@@ -91,19 +97,14 @@ public Point(double x, double y, double z) {
Point3D pt = new Point3D();
pt.setCoords(x, y, z);
setXYZ(pt);
-
}
/**
* Returns XY coordinates of this point.
*/
public final Point2D getXY() {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation should not be performed on an empty geometry.");
-
Point2D pt = new Point2D();
- pt.setCoords(m_attributes[0], m_attributes[1]);
+ pt.setCoords(m_x, m_y);
return pt;
}
@@ -111,11 +112,7 @@ public final Point2D getXY() {
* Returns XY coordinates of this point.
*/
public final void getXY(Point2D pt) {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation should not be performed on an empty geometry.");
-
- pt.setCoords(m_attributes[0], m_attributes[1]);
+ pt.setCoords(m_x, m_y);
}
/**
@@ -131,17 +128,10 @@ public final void setXY(Point2D pt) {
* Returns XYZ coordinates of the point. Z will be set to 0 if Z is missing.
*/
public Point3D getXYZ() {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation should not be performed on an empty geometry.");
-
Point3D pt = new Point3D();
- pt.x = m_attributes[0];
- pt.y = m_attributes[1];
- if (m_description.hasZ())
- pt.z = m_attributes[2];
- else
- pt.z = VertexDescription.getDefaultValue(Semantics.Z);
+ pt.x = m_x;
+ pt.y = m_y;
+ pt.z = hasZ() ? m_attributes[0] : VertexDescription.getDefaultValue(VertexDescription.Semantics.Z);
return pt;
}
@@ -154,39 +144,17 @@ public Point3D getXYZ() {
*/
public void setXYZ(Point3D pt) {
_touch();
- boolean bHasZ = hasAttribute(Semantics.Z);
- if (!bHasZ && !VertexDescription.isDefaultValue(Semantics.Z, pt.z)) {// add
- // Z
- // only
- // if
- // pt.z
- // is
- // not
- // a
- // default
- // value.
- addAttribute(Semantics.Z);
- bHasZ = true;
- }
-
- if (m_attributes == null)
- _setToDefault();
-
- m_attributes[0] = pt.x;
- m_attributes[1] = pt.y;
- if (bHasZ)
- m_attributes[2] = pt.z;
+ addAttribute(Semantics.Z);
+ m_x = pt.x;
+ m_y = pt.y;
+ m_attributes[0] = pt.z;
}
/**
* Returns the X coordinate of the point.
*/
public final double getX() {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation should not be performed on an empty geometry.");
-
- return m_attributes[0];
+ return m_x;
}
/**
@@ -196,18 +164,14 @@ public final double getX() {
* The X coordinate to be set for this point.
*/
public void setX(double x) {
- setAttribute(Semantics.POSITION, 0, x);
+ m_x = x;
}
/**
* Returns the Y coordinate of this point.
*/
public final double getY() {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation should not be performed on an empty geometry.");
-
- return m_attributes[1];
+ return m_y;
}
/**
@@ -217,14 +181,14 @@ public final double getY() {
* The Y coordinate to be set for this point.
*/
public void setY(double y) {
- setAttribute(Semantics.POSITION, 1, y);
+ m_y = y;
}
/**
* Returns the Z coordinate of this point.
*/
public double getZ() {
- return getAttributeAsDbl(Semantics.Z, 0);
+ return hasZ() ? m_attributes[0] : VertexDescription.getDefaultValue(VertexDescription.Semantics.Z);
}
/**
@@ -282,10 +246,18 @@ public void setID(int id) {
* @return The ordinate as double value.
*/
public double getAttributeAsDbl(int semantics, int ordinate) {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation was performed on an Empty Geometry.");
-
+ if (semantics == VertexDescription.Semantics.POSITION) {
+ if (ordinate == 0) {
+ return m_x;
+ }
+ else if (ordinate == 1) {
+ return m_y;
+ }
+ else {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
int ncomps = VertexDescription.getComponentCount(semantics);
if (ordinate >= ncomps)
throw new IndexOutOfBoundsException();
@@ -293,7 +265,7 @@ public double getAttributeAsDbl(int semantics, int ordinate) {
int attributeIndex = m_description.getAttributeIndex(semantics);
if (attributeIndex >= 0)
return m_attributes[m_description
- ._getPointAttributeOffset(attributeIndex) + ordinate];
+ ._getPointAttributeOffset(attributeIndex) - 2 + ordinate];
else
return VertexDescription.getDefaultValue(semantics);
}
@@ -310,20 +282,7 @@ public double getAttributeAsDbl(int semantics, int ordinate) {
* @return The ordinate value truncated to a 32 bit integer value.
*/
public int getAttributeAsInt(int semantics, int ordinate) {
- if (isEmptyImpl())
- throw new GeometryException(
- "This operation was performed on an Empty Geometry.");
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- if (ordinate >= ncomps)
- throw new IndexOutOfBoundsException();
-
- int attributeIndex = m_description.getAttributeIndex(semantics);
- if (attributeIndex >= 0)
- return (int) m_attributes[m_description
- ._getPointAttributeOffset(attributeIndex) + ordinate];
- else
- return (int) VertexDescription.getDefaultValue(semantics);
+ return (int)getAttributeAsDbl(semantics, ordinate);
}
/**
@@ -340,6 +299,19 @@ public int getAttributeAsInt(int semantics, int ordinate) {
*/
public void setAttribute(int semantics, int ordinate, double value) {
_touch();
+ if (semantics == VertexDescription.Semantics.POSITION) {
+ if (ordinate == 0) {
+ m_x = value;
+ }
+ else if (ordinate == 1) {
+ m_y = value;
+ }
+ else {
+ throw new IndexOutOfBoundsException();
+ }
+ return;
+ }
+
int ncomps = VertexDescription.getComponentCount(semantics);
if (ncomps < ordinate)
throw new IndexOutOfBoundsException();
@@ -350,10 +322,7 @@ public void setAttribute(int semantics, int ordinate, double value) {
attributeIndex = m_description.getAttributeIndex(semantics);
}
- if (m_attributes == null)
- _setToDefault();
-
- m_attributes[m_description._getPointAttributeOffset(attributeIndex)
+ m_attributes[m_description._getPointAttributeOffset(attributeIndex) - 2
+ ordinate] = value;
}
@@ -380,62 +349,70 @@ public long estimateMemorySize()
@Override
public void setEmpty() {
_touch();
- if (m_attributes != null) {
- m_attributes[0] = NumberUtils.NaN();
- m_attributes[1] = NumberUtils.NaN();
- }
+ _setToDefault();
}
@Override
protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
- if (m_attributes == null) {
- m_description = newDescription;
- return;
- }
-
int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(newDescription, m_description);
- double[] newAttributes = new double[newDescription.getTotalComponentCount()];
-
- int j = 0;
- for (int i = 0, n = newDescription.getAttributeCount(); i < n; i++) {
- int semantics = newDescription.getSemantics(i);
- int nords = VertexDescription.getComponentCount(semantics);
- if (mapping[i] == -1)
- {
- double d = VertexDescription.getDefaultValue(semantics);
- for (int ord = 0; ord < nords; ord++)
+ int newLen = newDescription.getTotalComponentCount() - 2;
+ if (newLen > 0) {
+ double[] newAttributes = new double[newLen];
+
+ int j = 0;
+ for (int i = 1, n = newDescription.getAttributeCount(); i < n; i++) {
+ int semantics = newDescription.getSemantics(i);
+ int nords = VertexDescription.getComponentCount(semantics);
+ if (mapping[i] == -1)
{
- newAttributes[j] = d;
- j++;
+ double d = VertexDescription.getDefaultValue(semantics);
+ for (int ord = 0; ord < nords; ord++)
+ {
+ newAttributes[j] = d;
+ j++;
+ }
}
- }
- else {
- int m = mapping[i];
- int offset = m_description._getPointAttributeOffset(m);
- for (int ord = 0; ord < nords; ord++)
- {
- newAttributes[j] = m_attributes[offset];
- j++;
- offset++;
+ else {
+ int m = mapping[i];
+ int offset = m_description._getPointAttributeOffset(m) - 2;
+ for (int ord = 0; ord < nords; ord++)
+ {
+ newAttributes[j] = m_attributes[offset];
+ j++;
+ offset++;
+ }
}
+
}
-
+
+ m_attributes = newAttributes;
}
-
- m_attributes = newAttributes;
+ else {
+ m_attributes = null;
+ }
+
m_description = newDescription;
}
/**
- * Sets the Point to a default, non-empty state.
+ * Sets to a default empty state.
*/
- void _setToDefault() {
- resizeAttributes(m_description.getTotalComponentCount());
- Point.attributeCopy(m_description._getDefaultPointAttributes(),
- m_attributes, m_description.getTotalComponentCount());
- m_attributes[0] = NumberUtils.NaN();
- m_attributes[1] = NumberUtils.NaN();
+ private void _setToDefault() {
+ int len = m_description.getTotalComponentCount() - 2;
+ if (len != 0) {
+ if (m_attributes == null || m_attributes.length != len) {
+ m_attributes = new double[len];
+ }
+
+ System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, 0, len);
+ }
+ else {
+ m_attributes = null;
+ }
+
+ m_x = NumberUtils.TheNaN;
+ m_y = NumberUtils.TheNaN;
}
@Override
@@ -449,7 +426,7 @@ public void applyTransformation(Transformation2D transform) {
}
@Override
- void applyTransformation(Transformation3D transform) {
+ public void applyTransformation(Transformation3D transform) {
if (isEmptyImpl())
return;
@@ -462,20 +439,27 @@ void applyTransformation(Transformation3D transform) {
public void copyTo(Geometry dst) {
if (dst.getType() != Type.Point)
throw new IllegalArgumentException();
-
- Point pointDst = (Point) dst;
+
+ if (this == dst)
+ return;
+
dst._touch();
- if (m_attributes == null) {
- pointDst.setEmpty();
+ Point pointDst = (Point) dst;
+ dst.m_description = m_description;
+ pointDst.m_x = m_x;
+ pointDst.m_y = m_y;
+ int attrLen = m_description.getTotalComponentCount() - 2;
+ if (attrLen == 0) {
pointDst.m_attributes = null;
- pointDst.assignVertexDescription(m_description);
- } else {
- pointDst.assignVertexDescription(m_description);
- pointDst.resizeAttributes(m_description.getTotalComponentCount());
- attributeCopy(m_attributes, pointDst.m_attributes,
- m_description.getTotalComponentCount());
+ return;
+ }
+
+ if (pointDst.m_attributes == null || pointDst.m_attributes.length != attrLen) {
+ pointDst.m_attributes = new double[attrLen];
}
+
+ System.arraycopy(m_attributes, 0, pointDst.m_attributes, 0, attrLen);
}
@Override
@@ -490,30 +474,29 @@ public boolean isEmpty() {
}
final boolean isEmptyImpl() {
- return ((m_attributes == null) || NumberUtils.isNaN(m_attributes[0]) || NumberUtils
- .isNaN(m_attributes[1]));
+ return NumberUtils.isNaN(m_x) || NumberUtils.isNaN(m_y);
}
@Override
public void queryEnvelope(Envelope env) {
- env.setEmpty();
if (m_description != env.m_description)
env.assignVertexDescription(m_description);
+
+ env.setEmpty();
env.merge(this);
}
@Override
public void queryEnvelope2D(Envelope2D env) {
-
if (isEmptyImpl()) {
env.setEmpty();
return;
}
- env.xmin = m_attributes[0];
- env.ymin = m_attributes[1];
- env.xmax = m_attributes[0];
- env.ymax = m_attributes[1];
+ env.xmin = m_x;
+ env.ymin = m_y;
+ env.xmax = m_x;
+ env.ymax = m_y;
}
@Override
@@ -523,13 +506,13 @@ void queryEnvelope3D(Envelope3D env) {
return;
}
- Point3D pt = getXYZ();
- env.xmin = pt.x;
- env.ymin = pt.y;
- env.zmin = pt.z;
- env.xmax = pt.x;
- env.ymax = pt.y;
- env.zmax = pt.z;
+ env.xmin = m_x;
+ env.ymin = m_y;
+ env.xmax = m_x;
+ env.ymax = m_y;
+ double z = getZ();
+ env.zmin = z;
+ env.zmax = z;
}
@Override
@@ -546,21 +529,6 @@ public Envelope1D queryInterval(int semantics, int ordinate) {
return env;
}
- private void resizeAttributes(int newSize) {
- if (m_attributes == null) {
- m_attributes = new double[newSize];
- } else if (m_attributes.length < newSize) {
- double[] newbuffer = new double[newSize];
- System.arraycopy(m_attributes, 0, newbuffer, 0, m_attributes.length);
- m_attributes = newbuffer;
- }
- }
-
- static void attributeCopy(double[] src, double[] dst, int count) {
- if (count > 0)
- System.arraycopy(src, 0, dst, 0, count);
- }
-
/**
* Set the X and Y coordinate of the point.
*
@@ -572,11 +540,8 @@ static void attributeCopy(double[] src, double[] dst, int count) {
public void setXY(double x, double y) {
_touch();
- if (m_attributes == null)
- _setToDefault();
-
- m_attributes[0] = x;
- m_attributes[1] = y;
+ m_x = x;
+ m_y = y;
}
/**
@@ -596,15 +561,21 @@ public boolean equals(Object _other) {
if (m_description != otherPt.m_description)
return false;
- if (isEmptyImpl())
+ if (isEmptyImpl()) {
if (otherPt.isEmptyImpl())
return true;
else
return false;
+ }
+
+ if (m_x != otherPt.m_x || m_y != otherPt.m_y) {
+ return false;
+ }
- for (int i = 0, n = m_description.getTotalComponentCount(); i < n; i++)
- if (m_attributes[i] != otherPt.m_attributes[i])
+ for (int i = 0, n = m_description.getTotalComponentCount() - 2; i < n; i++) {
+ if (!NumberUtils.isEqualNonIEEE(m_attributes[i], otherPt.m_attributes[i]))
return false;
+ }
return true;
}
@@ -617,12 +588,15 @@ public boolean equals(Object _other) {
public int hashCode() {
int hashCode = m_description.hashCode();
if (!isEmptyImpl()) {
- for (int i = 0, n = m_description.getTotalComponentCount(); i < n; i++) {
+ hashCode = NumberUtils.hash(hashCode, m_x);
+ hashCode = NumberUtils.hash(hashCode, m_y);
+ for (int i = 0, n = m_description.getTotalComponentCount() - 2; i < n; i++) {
long bits = Double.doubleToLongBits(m_attributes[i]);
int hc = (int) (bits ^ (bits >>> 32));
hashCode = NumberUtils.hash(hashCode, hc);
}
}
+
return hashCode;
}
diff --git a/src/main/java/com/esri/core/geometry/Point2D.java b/src/main/java/com/esri/core/geometry/Point2D.java
index 90cc1e46..95a46c66 100644
--- a/src/main/java/com/esri/core/geometry/Point2D.java
+++ b/src/main/java/com/esri/core/geometry/Point2D.java
@@ -94,6 +94,12 @@ public boolean equals(Object other) {
return x == v.x && y == v.y;
}
+
+ @Override
+ public int hashCode() {
+ return NumberUtils.hash(NumberUtils.hash(x), y);
+ }
+
public void sub(Point2D other) {
x -= other.x;
@@ -751,11 +757,6 @@ static Point2D calculateCircleCenterFromThreePoints(Point2D from, Point2D mid_po
}
}
- @Override
- public int hashCode() {
- return NumberUtils.hash(NumberUtils.hash(x), y);
- }
-
double getAxis(int ordinate) {
assert(ordinate == 0 || ordinate == 1);
return (ordinate == 0 ? x : y);
diff --git a/src/main/java/com/esri/core/geometry/Point3D.java b/src/main/java/com/esri/core/geometry/Point3D.java
index 849b00e1..71cbfdba 100644
--- a/src/main/java/com/esri/core/geometry/Point3D.java
+++ b/src/main/java/com/esri/core/geometry/Point3D.java
@@ -132,4 +132,31 @@ boolean _isNan() {
return NumberUtils.isNaN(x) || NumberUtils.isNaN(y) || NumberUtils.isNaN(z);
}
+ public boolean equals(Point3D other) {
+ //note that for nan value this returns false.
+ //this is by design for this class.
+ return x == other.x && y == other.y && z == other.z;
+ }
+
+ @Override
+ public boolean equals(Object other_) {
+ if (other_ == this)
+ return true;
+
+ if (!(other_ instanceof Point3D))
+ return false;
+
+ Point3D other = (Point3D)other_;
+ //note that for nan value this returns false.
+ //this is by design for this class.
+ return x == other.x && y == other.y && z == other.z;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = NumberUtils.hash(x);
+ hash = NumberUtils.hash(hash, y);
+ hash = NumberUtils.hash(hash, z);
+ return hash;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/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..34fdd216 100644
--- a/src/main/java/com/esri/core/geometry/RelationalOperations.java
+++ b/src/main/java/com/esri/core/geometry/RelationalOperations.java
@@ -1609,7 +1609,7 @@ private static boolean polylineDisjointPolyline_(Polyline polyline_a,
PairwiseIntersectorImpl intersector_paths = new PairwiseIntersectorImpl(multi_path_impl_a, multi_path_impl_b, tolerance, true);
if (!intersector_paths.next())
- return false;
+ return true;
return !linearPathIntersectsLinearPath_(polyline_a, polyline_b,
tolerance);
@@ -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/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
index 31460366..8d9f4c77 100644
--- a/src/main/java/com/esri/core/geometry/SizeOf.java
+++ b/src/main/java/com/esri/core/geometry/SizeOf.java
@@ -36,6 +36,8 @@
import static sun.misc.Unsafe.ARRAY_INT_INDEX_SCALE;
import static sun.misc.Unsafe.ARRAY_LONG_BASE_OFFSET;
import static sun.misc.Unsafe.ARRAY_LONG_INDEX_SCALE;
+import static sun.misc.Unsafe.ARRAY_OBJECT_BASE_OFFSET;
+import static sun.misc.Unsafe.ARRAY_OBJECT_INDEX_SCALE;
import static sun.misc.Unsafe.ARRAY_SHORT_BASE_OFFSET;
import static sun.misc.Unsafe.ARRAY_SHORT_INDEX_SCALE;
@@ -66,7 +68,7 @@ public final class SizeOf {
public static final int SIZE_OF_MULTI_POINT_IMPL = 56;
- public static final int SIZE_OF_POINT = 24;
+ public static final int SIZE_OF_POINT = 40;
public static final int SIZE_OF_POLYGON = 24;
@@ -88,6 +90,22 @@ public final class SizeOf {
public static final int SIZE_OF_MAPGEOMETRY = 24;
+ public static final int SIZE_OF_RASTERIZED_GEOMETRY_2D_IMPL = 112;
+
+ public static final int SIZE_OF_SCAN_CALLBACK_IMPL = 32;
+
+ public static final int SIZE_OF_TRANSFORMATION_2D = 64;
+
+ public static final int SIZE_OF_SIMPLE_RASTERIZER = 64;
+
+ public static final int SIZE_OF_EDGE = 48;
+
+ public static final int SIZE_OF_QUAD_TREE_IMPL = 48;
+
+ public static final int SIZE_OF_DATA = 24;
+
+ public static final int SIZE_OF_STRIDED_INDEX_TYPE_COLLECTION = 48;
+
public static long sizeOfByteArray(int length) {
return ARRAY_BYTE_BASE_OFFSET + (((long) ARRAY_BYTE_INDEX_SCALE) * length);
}
@@ -116,6 +134,11 @@ public static long sizeOfDoubleArray(int length) {
return ARRAY_DOUBLE_BASE_OFFSET + (((long) ARRAY_DOUBLE_INDEX_SCALE) * length);
}
+ public static long sizeOfObjectArray(int length)
+ {
+ return ARRAY_OBJECT_BASE_OFFSET + (((long) ARRAY_OBJECT_INDEX_SCALE) * length);
+ }
+
private SizeOf() {
}
}
diff --git a/src/main/java/com/esri/core/geometry/SpatialReference.java b/src/main/java/com/esri/core/geometry/SpatialReference.java
index 4c337e27..26e6c562 100644
--- a/src/main/java/com/esri/core/geometry/SpatialReference.java
+++ b/src/main/java/com/esri/core/geometry/SpatialReference.java
@@ -74,6 +74,7 @@ boolean isLocal() {
}
/**
+ * @deprecated Use fromJson(String)
* Returns spatial reference from the JsonParser.
*
* @param parser
@@ -83,6 +84,7 @@ boolean isLocal() {
* @throws Exception
* if parsing has failed
*/
+ @Deprecated
public static SpatialReference fromJson(JsonParser parser) throws Exception {
return fromJson(new JsonParserReader(parser));
}
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 51e171e7..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,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -25,13 +25,26 @@
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;
@@ -41,11 +54,26 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_CONCRETE_GEOMETRY_COLLECTION;
public class OGCConcreteGeometryCollection extends OGCGeometryCollection {
+ static public String TYPE = "GeometryCollection";
+
+ List geometries;
+
public OGCConcreteGeometryCollection(List geoms,
SpatialReference sr) {
geometries = geoms;
esriSR = sr;
}
+
+ public OGCConcreteGeometryCollection(GeometryCursor geoms,
+ SpatialReference sr) {
+ List ogcGeoms = new ArrayList(10);
+ for (Geometry g = geoms.next(); g != null; g = geoms.next()) {
+ ogcGeoms.add(createFromEsriGeometry(g, sr));
+ }
+
+ geometries = ogcGeoms;
+ esriSR = sr;
+ }
public OGCConcreteGeometryCollection(OGCGeometry geom, SpatialReference sr) {
geometries = new ArrayList(1);
@@ -53,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;
@@ -104,7 +137,7 @@ public OGCGeometry geometryN(int n) {
@Override
public String geometryType() {
- return "GeometryCollection";
+ return TYPE;
}
@Override
@@ -267,6 +300,7 @@ public boolean isSimple() {
for (int i = 0, n = numGeometries(); i < n; i++)
if (!geometryN(i).isSimple())
return false;
+
return true;
}
@@ -328,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;
@@ -377,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_) {
@@ -393,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() {
@@ -440,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 0755dc2e..dd229e5e 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCCurve.java
@@ -41,6 +41,9 @@ public boolean isRing() {
@Override
public OGCGeometry boundary() {
+ if (isEmpty())
+ return new OGCMultiPoint(this.getEsriSpatialReference());
+
if (isClosed())
return new OGCMultiPoint(new MultiPoint(getEsriGeometry()
.getDescription()), esriSR);// return empty multipoint;
diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java
index a3f60a6d..a6fdeaa9 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java
@@ -38,6 +38,7 @@
import com.esri.core.geometry.OGCStructure;
import com.esri.core.geometry.Operator;
import com.esri.core.geometry.OperatorBuffer;
+import com.esri.core.geometry.OperatorCentroid2D;
import com.esri.core.geometry.OperatorConvexHull;
import com.esri.core.geometry.OperatorExportToGeoJson;
import com.esri.core.geometry.OperatorExportToWkb;
@@ -51,6 +52,7 @@
import com.esri.core.geometry.OperatorSimplifyOGC;
import com.esri.core.geometry.OperatorUnion;
import com.esri.core.geometry.Point;
+import com.esri.core.geometry.Point2D;
import com.esri.core.geometry.Polygon;
import com.esri.core.geometry.Polyline;
import com.esri.core.geometry.SimpleGeometryCursor;
@@ -251,23 +253,31 @@ public boolean isMeasured() {
*/
public boolean Equals(OGCGeometry another) {
if (this == another)
- return true;
+ 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,
@@ -279,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,
@@ -286,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,
@@ -293,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,
@@ -307,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,
@@ -314,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,
@@ -326,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,
@@ -427,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(
@@ -445,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(
@@ -455,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(
@@ -463,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(
@@ -712,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/OGCLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java
index 464b9a7c..f044128d 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCLineString.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -40,7 +40,8 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_LINE_STRING;
public class OGCLineString extends OGCCurve {
-
+ static public String TYPE = "LineString";
+
/**
* The number of Points in this LineString.
*/
@@ -82,6 +83,9 @@ public OGCPoint pointN(int n) {
@Override
public boolean isClosed() {
+ if (isEmpty())
+ return false;
+
return multiPath.isClosedPathInXYPlane(0);
}
@@ -117,7 +121,7 @@ public OGCPoint endPoint() {
@Override
public String geometryType() {
- return "LineString";
+ return TYPE;
}
@Override
@@ -147,5 +151,10 @@ public OGCGeometry convertToMulti()
return new OGCMultiLineString((Polyline)multiPath, esriSR);
}
+ @Override
+ public OGCGeometry reduceFromMulti() {
+ return this;
+ }
+
MultiPath multiPath;
}
diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java b/src/main/java/com/esri/core/geometry/ogc/OGCMultiLineString.java
index 8fa020c8..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,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -42,22 +42,31 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_LINE_STRING;
public class OGCMultiLineString extends OGCMultiCurve {
+ static public String TYPE = "MultiLineString";
+
public OGCMultiLineString(Polyline poly, SpatialReference sr) {
polyline = poly;
esriSR = sr;
}
+ public OGCMultiLineString(SpatialReference sr) {
+ polyline = new Polyline();
+ esriSR = sr;
+ }
+
@Override
public String asText() {
return GeometryEngine.geometryToWkt(getEsriGeometry(),
WktExportFlags.wktExportMultiLineString);
}
+
@Override
- public String asGeoJson() {
- OperatorExportToGeoJson op = (OperatorExportToGeoJson) OperatorFactoryLocal
- .getInstance().getOperator(Operator.Type.ExportToGeoJson);
- return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, null, getEsriGeometry());
- }
+ public String asGeoJson() {
+ OperatorExportToGeoJson op = (OperatorExportToGeoJson) OperatorFactoryLocal.getInstance()
+ .getOperator(Operator.Type.ExportToGeoJson);
+ return op.execute(GeoJsonExportFlags.geoJsonExportPreferMultiGeometry, esriSR, getEsriGeometry());
+ }
+
@Override
public ByteBuffer asBinary() {
OperatorExportToWkb op = (OperatorExportToWkb) OperatorFactoryLocal
@@ -74,7 +83,7 @@ public OGCGeometry geometryN(int n) {
@Override
public String geometryType() {
- return "MultiLineString";
+ return TYPE;
}
@Override
@@ -114,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 b25a948a..b1c70a02 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiPoint.java
@@ -40,6 +40,8 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_POINT;
public class OGCMultiPoint extends OGCGeometryCollection {
+ public static String TYPE = "MultiPoint";
+
public int numGeometries() {
return multiPoint.getPointCount();
}
@@ -65,7 +67,7 @@ public OGCGeometry geometryN(int n) {
@Override
public String geometryType() {
- return "MultiPoint";
+ return TYPE;
}
@Override
@@ -131,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 bed0e114..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,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -42,12 +42,18 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_MULTI_POLYGON;
public class OGCMultiPolygon extends OGCMultiSurface {
-
+ static public String TYPE = "MultiPolygon";
+
public OGCMultiPolygon(Polygon src, SpatialReference sr) {
polygon = src;
esriSR = sr;
}
+ public OGCMultiPolygon(SpatialReference sr) {
+ polygon = new Polygon();
+ esriSR = sr;
+ }
+
@Override
public String asText() {
return GeometryEngine.geometryToWkt(getEsriGeometry(),
@@ -65,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() {
@@ -89,7 +95,7 @@ public OGCGeometry geometryN(int n) {
@Override
public String geometryType() {
- return "MultiPolygon";
+ return TYPE;
}
@Override
@@ -129,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 1c98be92..5a36dd0e 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCMultiSurface.java
@@ -29,11 +29,6 @@ public double area() {
return getEsriGeometry().calculateArea2D();
}
- public OGCPoint centroid() {
- // TODO
- throw new UnsupportedOperationException();
- }
-
public OGCPoint pointOnSurface() {
// TODO
throw new UnsupportedOperationException();
diff --git a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java
index 9db01268..d0fba6e7 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCPoint.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -39,6 +39,8 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_POINT;
public final class OGCPoint extends OGCGeometry {
+ public static String TYPE = "Point";
+
public OGCPoint(Point pt, SpatialReference sr) {
point = pt;
esriSR = sr;
@@ -76,7 +78,7 @@ public double M() {
@Override
public String geometryType() {
- return "Point";
+ return TYPE;
}
@Override
@@ -113,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 6f7a74f2..4c95250a 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCPolygon.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -40,6 +40,8 @@
import static com.esri.core.geometry.SizeOf.SIZE_OF_OGC_POLYGON;
public class OGCPolygon extends OGCSurface {
+ public static String TYPE = "Polygon";
+
public OGCPolygon(Polygon src, int exteriorRing, SpatialReference sr) {
polygon = new Polygon();
for (int i = exteriorRing, n = src.getPathCount(); i < n; i++) {
@@ -109,7 +111,7 @@ public OGCMultiCurve boundary() {
@Override
public String geometryType() {
- return "Polygon";
+ return TYPE;
}
@Override
@@ -141,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 43d192e6..989dfec8 100644
--- a/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java
+++ b/src/main/java/com/esri/core/geometry/ogc/OGCSurface.java
@@ -29,11 +29,6 @@ public double area() {
return getEsriGeometry().calculateArea2D();
}
- public OGCPoint centroid() {
- // TODO: implement me;
- throw new UnsupportedOperationException();
- }
-
public OGCPoint pointOnSurface() {
// TODO: support this (need to port OperatorLabelPoint)
throw new UnsupportedOperationException();
diff --git a/src/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/TestBuffer.java b/src/test/java/com/esri/core/geometry/TestBuffer.java
index 341751f5..e60145bb 100755
--- a/src/test/java/com/esri/core/geometry/TestBuffer.java
+++ b/src/test/java/com/esri/core/geometry/TestBuffer.java
@@ -27,6 +27,8 @@
import junit.framework.TestCase;
import org.junit.Test;
+import com.esri.core.geometry.ogc.OGCGeometry;
+
public class TestBuffer extends TestCase {
@Override
protected void setUp() throws Exception {
@@ -389,4 +391,27 @@ public void testBufferPolygon() {
assertTrue(simplify.isSimpleAsFeature(result, sr, null));
}
}
+
+ @Test
+ public static void testTinyBufferOfPoint() {
+ {
+ Geometry result1 = OperatorBuffer.local().execute(new Point(0, 0), SpatialReference.create(4326), 1e-9, null);
+ assertTrue(result1 != null);
+ assertTrue(result1.isEmpty());
+ Geometry geom1 = OperatorImportFromWkt.local().execute(0, Geometry.Type.Unknown, "POLYGON ((177.0 64.0, 177.0000000001 64.0, 177.0000000001 64.0000000001, 177.0 64.0000000001, 177.0 64.0))", null);
+ Geometry result2 = OperatorBuffer.local().execute(geom1, SpatialReference.create(4326), 0.01, null);
+ assertTrue(result2 != null);
+ assertTrue(result2.isEmpty());
+
+ }
+
+ {
+ OGCGeometry p = OGCGeometry.fromText(
+ "POLYGON ((177.0 64.0, 177.0000000001 64.0, 177.0000000001 64.0000000001, 177.0 64.0000000001, 177.0 64.0))");
+ OGCGeometry buffered = p.buffer(0.01);
+ assertTrue(buffered != null);
+ }
+
+
+ }
}
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/TestConvexHull.java b/src/test/java/com/esri/core/geometry/TestConvexHull.java
index b2e2d59e..ee9c764e 100644
--- a/src/test/java/com/esri/core/geometry/TestConvexHull.java
+++ b/src/test/java/com/esri/core/geometry/TestConvexHull.java
@@ -27,6 +27,8 @@
import junit.framework.TestCase;
import org.junit.Test;
+import com.esri.core.geometry.ogc.OGCGeometry;
+
public class TestConvexHull extends TestCase {
@Override
protected void setUp() throws Exception {
@@ -992,5 +994,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 456973cd..a388ff01 100644
--- a/src/test/java/com/esri/core/geometry/TestCut.java
+++ b/src/test/java/com/esri/core/geometry/TestCut.java
@@ -51,7 +51,7 @@ public static void testCut4326() {
}
- public static void testConsiderTouch1(SpatialReference spatialReference) {
+ private static void testConsiderTouch1(SpatialReference spatialReference) {
OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance();
OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut);
@@ -101,7 +101,7 @@ public static void testConsiderTouch1(SpatialReference spatialReference) {
assertTrue(cut == null);
}
- public static void testConsiderTouch2(SpatialReference spatialReference) {
+ private static void testConsiderTouch2(SpatialReference spatialReference) {
OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance();
OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut);
@@ -167,7 +167,7 @@ public static void testConsiderTouch2(SpatialReference spatialReference) {
assertTrue(cut == null);
}
- public static void testPolygon5(SpatialReference spatialReference) {
+ private static void testPolygon5(SpatialReference spatialReference) {
OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance();
OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut);
@@ -201,7 +201,7 @@ public static void testPolygon5(SpatialReference spatialReference) {
assertTrue(cut == null);
}
- public static void testPolygon7(SpatialReference spatialReference) {
+ private static void testPolygon7(SpatialReference spatialReference) {
OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance();
OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut);
@@ -238,7 +238,7 @@ public static void testPolygon7(SpatialReference spatialReference) {
assertTrue(cut == null);
}
- public static void testPolygon8(SpatialReference spatialReference) {
+ private static void testPolygon8(SpatialReference spatialReference) {
OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance();
OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut);
@@ -275,7 +275,7 @@ public static void testPolygon8(SpatialReference spatialReference) {
assertTrue(cut == null);
}
- public static void testPolygon9(SpatialReference spatialReference) {
+ private static void testPolygon9(SpatialReference spatialReference) {
OperatorFactoryLocal engine = OperatorFactoryLocal.getInstance();
OperatorCut opCut = (OperatorCut) engine.getOperator(Operator.Type.Cut);
@@ -309,7 +309,7 @@ public static void testPolygon9(SpatialReference spatialReference) {
assertTrue(cut == null);
}
- public static void testEngine(SpatialReference spatialReference) {
+ private static void testEngine(SpatialReference spatialReference) {
Polygon polygon8 = makePolygon8();
Polyline cutter8 = makePolygonCutter8();
@@ -337,7 +337,7 @@ public static void testEngine(SpatialReference spatialReference) {
assertTrue(area == 800);
}
- public static Polyline makePolyline1() {
+ private static Polyline makePolyline1() {
Polyline poly = new Polyline();
poly.startPath(0, 0);
@@ -355,7 +355,7 @@ public static Polyline makePolyline1() {
return poly;
}
- public static Polyline makePolylineCutter1() {
+ private static Polyline makePolylineCutter1() {
Polyline poly = new Polyline();
poly.startPath(1, 0);
@@ -395,7 +395,7 @@ public static Polyline makePolylineCutter1() {
return poly;
}
- public static Polyline makePolyline2() {
+ private static Polyline makePolyline2() {
Polyline poly = new Polyline();
poly.startPath(-2, 0);
@@ -410,7 +410,7 @@ public static Polyline makePolyline2() {
return poly;
}
- public static Polyline makePolylineCutter2() {
+ private static Polyline makePolylineCutter2() {
Polyline poly = new Polyline();
poly.startPath(-1.5, 0);
@@ -443,7 +443,7 @@ public static Polyline makePolylineCutter2() {
return poly;
}
- public static Polygon makePolygon5() {
+ private static Polygon makePolygon5() {
Polygon poly = new Polygon();
poly.startPath(0, 0);
@@ -454,7 +454,7 @@ public static Polygon makePolygon5() {
return poly;
}
- public static Polyline makePolygonCutter5() {
+ private static Polyline makePolygonCutter5() {
Polyline poly = new Polyline();
poly.startPath(15, 0);
@@ -466,7 +466,7 @@ public static Polyline makePolygonCutter5() {
return poly;
}
- public static Polygon makePolygon7() {
+ private static Polygon makePolygon7() {
Polygon poly = new Polygon();
poly.startPath(0, 0);
@@ -477,7 +477,7 @@ public static Polygon makePolygon7() {
return poly;
}
- public static Polyline makePolygonCutter7() {
+ private static Polyline makePolygonCutter7() {
Polyline poly = new Polyline();
poly.startPath(10, 10);
@@ -489,7 +489,7 @@ public static Polyline makePolygonCutter7() {
return poly;
}
- public static Polygon makePolygon8() {
+ private static Polygon makePolygon8() {
Polygon poly = new Polygon();
poly.startPath(0, 0);
@@ -500,7 +500,7 @@ public static Polygon makePolygon8() {
return poly;
}
- public static Polyline makePolygonCutter8() {
+ private static Polyline makePolygonCutter8() {
Polyline poly = new Polyline();
poly.startPath(10, 10);
@@ -512,7 +512,7 @@ public static Polyline makePolygonCutter8() {
return poly;
}
- public static Polygon makePolygon9() {
+ private static Polygon makePolygon9() {
Polygon poly = new Polygon();
poly.startPath(0, 0);
@@ -533,7 +533,7 @@ public static Polygon makePolygon9() {
return poly;
}
- public static Polyline makePolygonCutter9() {
+ private static Polyline makePolygonCutter9() {
Polyline poly = new Polyline();
poly.startPath(5, -1);
@@ -541,4 +541,20 @@ public static Polyline makePolygonCutter9() {
return poly;
}
+
+ @Test
+ public void testGithubIssue253() {
+ //https://github.com/Esri/geometry-api-java/issues/253
+ SpatialReference spatialReference = SpatialReference.create(3857);
+ Polyline poly1 = new Polyline();
+ poly1.startPath(610, 552);
+ poly1.lineTo(610, 552);
+ Polyline poly2 = new Polyline();
+ poly2.startPath(610, 552);
+ poly2.lineTo(610, 552);
+ GeometryCursor cursor = OperatorCut.local().execute(true, poly1, poly2, spatialReference, null);
+
+ Geometry res = cursor.next();
+ assertTrue(res == null);
+ }
}
diff --git a/src/test/java/com/esri/core/geometry/TestDifference.java b/src/test/java/com/esri/core/geometry/TestDifference.java
index c6f22321..2ea73ffc 100644
--- a/src/test/java/com/esri/core/geometry/TestDifference.java
+++ b/src/test/java/com/esri/core/geometry/TestDifference.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -24,8 +24,6 @@
package com.esri.core.geometry;
-import java.util.ArrayList;
-import java.util.List;
import junit.framework.TestCase;
@@ -504,6 +502,14 @@ public static void testDifferenceOnPolyline() {
assertEquals(5, pointCountDiffPolyline);
}
+
+ @Test
+ public static void testDifferencePolylineAlongPolygonBoundary() {
+ Polyline polyline = (Polyline)GeometryEngine.geometryFromWkt("LINESTRING(0 0, 0 5, -2 5)", 0, Geometry.Type.Unknown);
+ Polygon polygon = (Polygon)GeometryEngine.geometryFromWkt("POLYGON((0 0, 5 0, 5 5, 0 5, 0 0))", 0, Geometry.Type.Unknown);
+ Geometry result = OperatorDifference.local().execute(polyline, polygon, null, null);
+ assertEquals(GeometryEngine.geometryToJson(null, result), "{\"paths\":[[[0,5],[-2,5]]]}");
+ }
public static Polygon makePolygon1() {
Polygon poly = new Polygon();
diff --git a/src/test/java/com/esri/core/geometry/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/TestEstimateMemorySize.java b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java
index e4195c58..b1b40b22 100644
--- a/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java
+++ b/src/test/java/com/esri/core/geometry/TestEstimateMemorySize.java
@@ -24,6 +24,7 @@
package com.esri.core.geometry;
+import com.esri.core.geometry.Geometry.GeometryAccelerationDegree;
import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection;
import com.esri.core.geometry.ogc.OGCGeometry;
import com.esri.core.geometry.ogc.OGCLineString;
@@ -66,6 +67,14 @@ public void testInstanceSizes() {
assertEquals(getInstanceSize(OGCMultiPolygon.class), SizeOf.SIZE_OF_OGC_MULTI_POLYGON);
assertEquals(getInstanceSize(OGCPoint.class), SizeOf.SIZE_OF_OGC_POINT);
assertEquals(getInstanceSize(OGCPolygon.class), SizeOf.SIZE_OF_OGC_POLYGON);
+ assertEquals(getInstanceSize(RasterizedGeometry2DImpl.class), SizeOf.SIZE_OF_RASTERIZED_GEOMETRY_2D_IMPL);
+ assertEquals(getInstanceSize(RasterizedGeometry2DImpl.ScanCallbackImpl.class), SizeOf.SIZE_OF_SCAN_CALLBACK_IMPL);
+ assertEquals(getInstanceSize(Transformation2D.class), SizeOf.SIZE_OF_TRANSFORMATION_2D);
+ assertEquals(getInstanceSize(SimpleRasterizer.class), SizeOf.SIZE_OF_SIMPLE_RASTERIZER);
+ assertEquals(getInstanceSize(SimpleRasterizer.Edge.class), SizeOf.SIZE_OF_EDGE);
+ assertEquals(getInstanceSize(QuadTreeImpl.class), SizeOf.SIZE_OF_QUAD_TREE_IMPL);
+ assertEquals(getInstanceSize(QuadTreeImpl.Data.class), SizeOf.SIZE_OF_DATA);
+ assertEquals(getInstanceSize(StridedIndexTypeCollection.class), SizeOf.SIZE_OF_STRIDED_INDEX_TYPE_COLLECTION);
}
private static long getInstanceSize(Class clazz) {
@@ -77,29 +86,59 @@ 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 testLineString() {
+ 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() {
- testGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))"));
+ testAcceleratedGeometry(parseWkt("MULTILINESTRING ((0 1, 2 3, 4 5), (1 1, 2 2))"));
+ }
+
+ @Test
+ public void testEmptyMultiLineString() {
+ testGeometry(parseWkt("MULTILINESTRING EMPTY"));
}
@Test
public void testPolygon() {
- testGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))"));
+ testAcceleratedGeometry(parseWkt("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))"));
+ }
+
+ @Test
+ public void testEmptyPolygon() {
+ testGeometry(parseWkt("POLYGON EMPTY"));
}
@Test
public void testMultiPolygon() {
- testGeometry(parseWkt("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)), ((15 5, 40 10, 10 20, 5 10, 15 5)))"));
+ 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
@@ -107,10 +146,45 @@ 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);
diff --git a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java
index aa480b26..83271d5b 100644
--- a/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java
+++ b/src/test/java/com/esri/core/geometry/TestGeomToGeoJson.java
@@ -22,14 +22,9 @@
package com.esri.core.geometry;
-import com.esri.core.geometry.ogc.OGCGeometry;
-import com.esri.core.geometry.ogc.OGCPoint;
-import com.esri.core.geometry.ogc.OGCMultiPoint;
-import com.esri.core.geometry.ogc.OGCLineString;
-import com.esri.core.geometry.ogc.OGCPolygon;
+import com.esri.core.geometry.ogc.*;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
-import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection;
import junit.framework.TestCase;
import org.junit.Test;
@@ -161,6 +156,20 @@ public void testOGCLineString() {
assertEquals("{\"type\":\"LineString\",\"coordinates\":[[100,0],[101,0],[101,1],[100,1]],\"crs\":null}", result);
}
+ @Test
+ public void testOGCMultiLineStringCRS() throws IOException {
+ Polyline p = new Polyline();
+ p.startPath(100.0, 0.0);
+ p.lineTo(101.0, 0.0);
+ p.lineTo(101.0, 1.0);
+ p.lineTo(100.0, 1.0);
+
+ OGCMultiLineString multiLineString = new OGCMultiLineString(p, SpatialReference.create(4326));
+
+ String result = multiLineString.asGeoJson();
+ assertEquals("{\"type\":\"MultiLineString\",\"coordinates\":[[[100,0],[101,0],[101,1],[100,1]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", result);
+ }
+
@Test
public void testPolygon() {
Polygon p = new Polygon();
@@ -241,6 +250,24 @@ public void testMultiPolygon() throws IOException {
assertEquals("{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-100,-100],[100,-100],[100,100],[-100,100],[-100,-100]],[[-90,-90],[90,-90],[-90,90],[90,90],[-90,-90]]],[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]]}", result);
}
+ @Test
+ public void testOGCMultiPolygonCRS() throws IOException {
+ JsonFactory jsonFactory = new JsonFactory();
+
+ String esriJsonPolygon = "{\"rings\": [[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[-90, -90], [90, 90], [-90, 90], [90, -90], [-90, -90]], [[-10, -10], [-10, 10], [10, 10], [10, -10], [-10, -10]]]}";
+
+ JsonParser parser = jsonFactory.createParser(esriJsonPolygon);
+ MapGeometry parsedPoly = GeometryEngine.jsonToGeometry(parser);
+
+ parsedPoly.setSpatialReference(SpatialReference.create(4326));
+ Polygon poly = (Polygon) parsedPoly.getGeometry();
+ OGCMultiPolygon multiPolygon = new OGCMultiPolygon(poly, parsedPoly.getSpatialReference());
+
+
+ String result = multiPolygon.asGeoJson();
+ assertEquals("{\"type\":\"MultiPolygon\",\"coordinates\":[[[[-100,-100],[100,-100],[100,100],[-100,100],[-100,-100]],[[-90,-90],[90,-90],[-90,90],[90,90],[-90,-90]]],[[[-10,-10],[10,-10],[10,10],[-10,10],[-10,-10]]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", result);
+ }
+
@Test
public void testEmptyPolygon() {
@@ -334,6 +361,29 @@ public void testOGCPolygonWithHole() {
assertEquals("{\"type\":\"Polygon\",\"coordinates\":[[[100,0],[101,0],[101,1],[100,1],[100,0]],[[100.2,0.2],[100.2,0.8],[100.8,0.8],[100.8,0.2],[100.2,0.2]]],\"crs\":null}", result);
}
+ @Test
+ public void testOGCPolygonWithHoleCRS() {
+ Polygon p = new Polygon();
+
+ p.startPath(100.0, 0.0);
+ p.lineTo(100.0, 1.0);
+ p.lineTo(101.0, 1.0);
+ p.lineTo(101.0, 0.0);
+ p.closePathWithLine();
+
+ p.startPath(100.2, 0.2);
+ p.lineTo(100.8, 0.2);
+ p.lineTo(100.8, 0.8);
+ p.lineTo(100.2, 0.8);
+ p.closePathWithLine();
+
+ SpatialReference sr = SpatialReference.create(4326);
+
+ OGCPolygon ogcPolygon = new OGCPolygon(p, sr);
+ String result = ogcPolygon.asGeoJson();
+ assertEquals("{\"type\":\"Polygon\",\"coordinates\":[[[100,0],[101,0],[101,1],[100,1],[100,0]],[[100.2,0.2],[100.2,0.8],[100.8,0.8],[100.8,0.2],[100.2,0.2]]],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}}", result);
+ }
+
@Test
public void testGeometryCollection() {
SpatialReference sr = SpatialReference.create(4326);
diff --git a/src/test/java/com/esri/core/geometry/TestImportExport.java b/src/test/java/com/esri/core/geometry/TestImportExport.java
index 0b9e2bc8..73faed01 100644
--- a/src/test/java/com/esri/core/geometry/TestImportExport.java
+++ b/src/test/java/com/esri/core/geometry/TestImportExport.java
@@ -44,15 +44,6 @@ protected void tearDown() throws Exception {
@Test
public static void testImportExportShapePolygon() {
-// {
-// String s = "MULTIPOLYGON (((-1.4337158203098852 53.42590083930004, -1.4346462383651897 53.42590083930004, -1.4349713164114632 53.42426406667512, -1.4344808816770183 53.42391134176576, -1.4337158203098852 53.424339319373516, -1.4337158203098852 53.42590083930004, -1.4282226562499147 53.42590083930004, -1.4282226562499147 53.42262754610009, -1.423659941537096 53.42262754610009, -1.4227294921872726 53.42418897437618, -1.4199829101572732 53.42265258737483, -1.4172363281222147 53.42418897437334, -1.4144897460898278 53.42265258737625, -1.4144897460898278 53.42099079900008, -1.4117431640598568 53.42099079712516, -1.4117431640598568 53.41849780932388, -1.4112778948070286 53.41771711805022, -1.4114404909237805 53.41689867267529, -1.411277890108579 53.416080187950215, -1.4117431640598568 53.4152995338453, -1.4117431657531654 53.40953184824072, -1.41723632610001 53.40953184402311, -1.4172363281199125 53.406257299700044, -1.4227294921899158 53.406257299700044, -1.4227294921899158 53.40789459668797, -1.4254760767598498 53.40789460061099, -1.4262193642339867 53.40914148401417, -1.4273828468095076 53.409531853100034, -1.4337158203098852 53.409531790075235, -1.4337158203098852 53.41280609140024, -1.4392089843723568 53.41280609140024, -1.439208984371362 53.41608014067522, -1.441160015802268 53.41935368587538, -1.4427511170075604 53.41935368587538, -1.4447021484373863 53.42099064750012, -1.4501953124999432 53.42099064750012, -1.4501953124999432 53.43214683850347, -1.4513643355446106 53.434108816701794, -1.4502702625278232 53.43636597733034, -1.4494587195580948 53.437354845300334, -1.4431075935937656 53.437354845300334, -1.4372459179209045 53.43244635455021, -1.433996276212838 53.42917388040006, -1.4337158203098852 53.42917388040006, -1.4337158203098852 53.42590083930004)))";
-// Geometry g = OperatorImportFromWkt.local().execute(0, Geometry.Type.Unknown, s, null);
-// boolean result1 = OperatorSimplify.local().isSimpleAsFeature(g, null, null);
-// boolean result2 = OperatorSimplifyOGC.local().isSimpleOGC(g, null, true, null, null);
-// Geometry simple = OperatorSimplifyOGC.local().execute(g, null, true, null);
-// OperatorFactoryLocal.saveToWKTFileDbg("c:/temp/simplifiedeeee", simple, null);
-// int i = 0;
-// }
OperatorExportToESRIShape exporterShape = (OperatorExportToESRIShape) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.ExportToESRIShape);
OperatorImportFromESRIShape importerShape = (OperatorImportFromESRIShape) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.ImportFromESRIShape);
@@ -1754,6 +1745,20 @@ public static void testImportGeoJsonSpatialReference() throws Exception {
assertTrue(mapGeometry4326.getGeometry().equals(mapGeometry3857.getGeometry()));
}
+ @Test
+ public void testZeroRingWkb() {
+ //https://github.com/Esri/geometry-api-java/issues/275
+ Polygon poly = new Polygon();
+ poly.startPath(0, 0);
+ poly.lineTo(0, 10);
+ poly.lineTo(0, 10);
+ poly.addEnvelope(new Envelope(1, 1, 3, 3), false);
+
+ ByteBuffer bb = OperatorExportToWkb.local().execute(0, poly, null);
+ Geometry res = OperatorImportFromWkb.local().execute(0, Geometry.Type.Unknown, bb, null);
+ assertTrue(res.equals(poly));
+ }
+
public static Polygon makePolygon() {
Polygon poly = new Polygon();
poly.startPath(0, 0);
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/TestIntersect2.java b/src/test/java/com/esri/core/geometry/TestIntersect2.java
index 36860635..0254dcb8 100644
--- a/src/test/java/com/esri/core/geometry/TestIntersect2.java
+++ b/src/test/java/com/esri/core/geometry/TestIntersect2.java
@@ -25,6 +25,7 @@
package com.esri.core.geometry;
import com.esri.core.geometry.Geometry.Type;
+import com.esri.core.geometry.ogc.OGCGeometry;
import junit.framework.TestCase;
import org.junit.Test;
@@ -39,6 +40,16 @@ protected void tearDown() throws Exception {
super.tearDown();
}
+ @Test
+ public void testIntersectsLinestringAndMultilinestring() {
+ // https://github.com/Esri/geometry-api-java/issues/326
+ OGCGeometry line = OGCGeometry.fromText("LINESTRING(1 0, 1 1)");
+ OGCGeometry multiLine = OGCGeometry.fromText("MULTILINESTRING((0 0, 0 1), (2 0, 2 1))");
+
+ assertFalse(line.intersects(multiLine));
+ assertFalse(multiLine.intersects(line));
+ }
+
@Test
/**
* Intersect
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/TestOGC.java b/src/test/java/com/esri/core/geometry/TestOGC.java
index ca2bcf6d..b68f2fcc 100644
--- a/src/test/java/com/esri/core/geometry/TestOGC.java
+++ b/src/test/java/com/esri/core/geometry/TestOGC.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -35,7 +35,6 @@
import com.esri.core.geometry.ogc.OGCMultiPolygon;
import com.esri.core.geometry.ogc.OGCPoint;
import com.esri.core.geometry.ogc.OGCPolygon;
-import com.fasterxml.jackson.core.JsonParseException;
import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection;
import org.junit.Test;
@@ -926,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/TestPoint.java b/src/test/java/com/esri/core/geometry/TestPoint.java
index c2e8bd2f..c30f612f 100644
--- a/src/test/java/com/esri/core/geometry/TestPoint.java
+++ b/src/test/java/com/esri/core/geometry/TestPoint.java
@@ -45,9 +45,35 @@ protected void tearDown() throws Exception {
public void testPt() {
Point pt = new Point();
assertTrue(pt.isEmpty());
+ assertTrue(Double.isNaN(pt.getX()));
+ assertTrue(Double.isNaN(pt.getY()));
+ assertTrue(Double.isNaN(pt.getM()));
+ assertTrue(pt.getZ() == 0);
+ Point pt1 = new Point();
+ assertTrue(pt.equals(pt1));
+ int hash1 = pt.hashCode();
pt.setXY(10, 2);
assertFalse(pt.isEmpty());
-
+ assertTrue(pt.getX() == 10);
+ assertTrue(pt.getY() == 2);
+ assertTrue(pt.getXY().equals(new Point2D(10, 2)));
+ assertTrue(pt.getXYZ().x == 10);
+ assertTrue(pt.getXYZ().y == 2);
+ assertTrue(pt.getXYZ().z == 0);
+ assertFalse(pt.equals(pt1));
+ pt.copyTo(pt1);
+ assertTrue(pt.equals(pt1));
+ int hash2 = pt.hashCode();
+ assertFalse(hash1 == hash2);
+ pt.setZ(5);
+ assertFalse(pt.equals(pt1));
+ pt.copyTo(pt1);
+ assertTrue(pt.equals(pt1));
+ assertFalse(hash1 == pt.hashCode());
+ assertFalse(hash2 == pt.hashCode());
+ assertTrue(pt.hasZ());
+ assertTrue(pt.getZ() == 5);
+ assertTrue(pt.hasAttribute(VertexDescription.Semantics.Z));
pt.toString();
}
diff --git a/src/test/java/com/esri/core/geometry/TestSerialization.java b/src/test/java/com/esri/core/geometry/TestSerialization.java
index 8cdb4ad9..5f3796a1 100644
--- a/src/test/java/com/esri/core/geometry/TestSerialization.java
+++ b/src/test/java/com/esri/core/geometry/TestSerialization.java
@@ -1,5 +1,5 @@
/*
- Copyright 1995-2017 Esri
+ Copyright 1995-2018 Esri
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -401,4 +400,97 @@ public void testSerializeEnvelope2D() {
}
}
+ public void testAttributeStreamOfInt32() {
+ AttributeStreamOfInt32 a = new AttributeStreamOfInt32(0);
+ for (int i = 0; i < 100; i++)
+ a.add(i);
+
+ try {
+ // serialize
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(baos);
+ os.writeObject(a);
+ os.close();
+ baos.close();
+
+ // deserialize
+ ByteArrayInputStream bais = new ByteArrayInputStream(
+ baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ AttributeStreamOfInt32 aOut = (AttributeStreamOfInt32) in.readObject();
+ in.close();
+ bais.close();
+
+ assertTrue(aOut.size() == a.size());
+ for (int i = 0; i < 100; i++)
+ assertTrue(aOut.get(i) == a.get(i));
+
+ } catch (Exception e) {
+ fail("AttributeStreamOfInt32 serialization failure");
+ }
+
+ }
+
+ @Test
+ public void testQuadTree() {
+ MultiPoint mp = new MultiPoint();
+ int r = 124124;
+ for (int i = 0; i < 100; ++i) {
+ r = NumberUtils.nextRand(r);
+ int x = r;
+ r = NumberUtils.nextRand(r);
+ int y = r;
+ mp.add(x, y);
+ }
+
+ Envelope2D extent = new Envelope2D();
+ mp.queryEnvelope2D(extent);
+ QuadTree quadTree = new QuadTree(extent, 8);
+ Envelope2D boundingbox = new Envelope2D();
+ Point2D pt;
+
+ for (int i = 0; i < mp.getPointCount(); i++) {
+ pt = mp.getXY(i);
+ boundingbox.setCoords(pt.x, pt.y, pt.x, pt.y);
+ quadTree.insert(i, boundingbox, -1);
+ }
+
+ try {
+ // serialize
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream os = new ObjectOutputStream(baos);
+ os.writeObject(quadTree);
+ os.close();
+ baos.close();
+
+ // deserialize
+ ByteArrayInputStream bais = new ByteArrayInputStream(
+ baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ QuadTree qOut = (QuadTree) in.readObject();
+ in.close();
+ bais.close();
+
+ assertTrue(quadTree.getElementCount() == qOut.getElementCount());
+ QuadTree.QuadTreeIterator iter1 = quadTree.getIterator();
+ QuadTree.QuadTreeIterator iter2 = qOut.getIterator();
+ int h1 = iter1.next();
+ int h2 = iter2.next();
+ for (; h1 != -1 && h2 != -1; h1 = iter1.next(), h2 = iter2.next()) {
+ assertTrue(quadTree.getElement(h1) == qOut.getElement(h2));
+ assertTrue(quadTree.getElementExtent(h1).equals(qOut.getElementExtent(h2)));
+ assertTrue(quadTree.getExtent(quadTree.getQuad(h1)).equals(qOut.getExtent(qOut.getQuad(h2))));
+ int c1 = quadTree.getSubTreeElementCount(quadTree.getQuad(h1));
+ int c2 = qOut.getSubTreeElementCount(qOut.getQuad(h2));
+ assertTrue(c1 == c2);
+ }
+
+ assertTrue(h1 == -1 && h2 == -1);
+
+ assertTrue(quadTree.getDataExtent().equals(qOut.getDataExtent()));
+ } catch (Exception e) {
+ fail("QuadTree serialization failure");
+ }
+
+ }
}
diff --git a/src/test/java/com/esri/core/geometry/TestUnion.java b/src/test/java/com/esri/core/geometry/TestUnion.java
index 55392e39..77032413 100644
--- a/src/test/java/com/esri/core/geometry/TestUnion.java
+++ b/src/test/java/com/esri/core/geometry/TestUnion.java
@@ -40,11 +40,6 @@ protected void tearDown() throws Exception {
@Test
public static void testUnion() {
- Point pt = new Point(10, 20);
-
- Point pt2 = new Point();
- pt2.setXY(10, 10);
-
Envelope env1 = new Envelope(10, 10, 30, 50);
Envelope env2 = new Envelope(30, 10, 60, 50);
Geometry[] geomArray = new Geometry[] { env1, env2 };
@@ -57,5 +52,129 @@ public static void testUnion() {
GeometryCursor outputCursor = union.execute(inputGeometries, sr, null);
Geometry result = outputCursor.next();
+
+ MultiPath path = (MultiPath)result;
+ assertEquals(1, path.getPathCount());
+ assertEquals(6, path.getPathEnd(0));
+ assertEquals(new Point2D(10, 10), path.getXY(0));
+ assertEquals(new Point2D(10, 50), path.getXY(1));
+ assertEquals(new Point2D(30, 50), path.getXY(2));
+ assertEquals(new Point2D(60, 50), path.getXY(3));
+ assertEquals(new Point2D(60, 10), path.getXY(4));
+ assertEquals(new Point2D(30, 10), path.getXY(5));
+ }
+
+ @Test
+ public static void testUnionDistinctGeometries() {
+ Envelope env = new Envelope(1, 5, 3, 10);
+
+ Polygon polygon = new Polygon();
+ polygon.startPath(new Point(4, 3));
+ polygon.lineTo(new Point(7, 6));
+ polygon.lineTo(new Point(6, 8));
+ polygon.lineTo(new Point(4, 3));
+
+ Geometry[] geomArray = new Geometry[] { env, polygon };
+ SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor(
+ geomArray);
+ OperatorUnion union = (OperatorUnion) OperatorFactoryLocal
+ .getInstance().getOperator(Operator.Type.Union);
+ SpatialReference sr = SpatialReference.create(4326);
+
+ GeometryCursor outputCursor = union.execute(inputGeometries, sr, null);
+ Geometry result = outputCursor.next();
+
+ MultiPath path = (MultiPath)result;
+ assertEquals(2, path.getPathCount());
+
+ assertEquals(3, path.getPathEnd(0));
+ assertEquals(7, path.getPathEnd(1));
+ // from polygon
+ assertEquals(new Point2D(4, 3), path.getXY(0));
+ assertEquals(new Point2D(6, 8), path.getXY(1));
+ assertEquals(new Point2D(7, 6), path.getXY(2));
+ // from envelope
+ assertEquals(new Point2D(1, 5), path.getXY(3));
+ assertEquals(new Point2D(1, 10), path.getXY(4));
+ assertEquals(new Point2D(3, 10), path.getXY(5));
+ assertEquals(new Point2D(3, 5), path.getXY(6));
+ }
+
+ @Test
+ public static void testUnionCoincidentPolygons() {
+ Polygon polygon1 = new Polygon();
+ polygon1.startPath(new Point(3, 2));
+ polygon1.lineTo(new Point(1, 2));
+ polygon1.lineTo(new Point(1, 4));
+ polygon1.lineTo(new Point(3, 4));
+ polygon1.lineTo(new Point(3, 2));
+
+ Polygon polygon2 = new Polygon();
+ polygon2.startPath(new Point(1, 2));
+ polygon2.lineTo(new Point(1, 4));
+ polygon2.lineTo(new Point(3, 4));
+ polygon2.lineTo(new Point(3, 2));
+ polygon2.lineTo(new Point(1, 2));
+
+ Geometry[] geomArray = new Geometry[] { polygon1, polygon2 };
+ SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor(
+ geomArray);
+ OperatorUnion union = (OperatorUnion) OperatorFactoryLocal
+ .getInstance().getOperator(Operator.Type.Union);
+ SpatialReference sr = SpatialReference.create(4326);
+
+ GeometryCursor outputCursor = union.execute(inputGeometries, sr, null);
+ Geometry result = outputCursor.next();
+
+ MultiPath path = (MultiPath)result;
+ assertEquals(1, path.getPathCount());
+ assertEquals(4, path.getPathEnd(0));
+ assertEquals(new Point2D(1, 2), path.getXY(0));
+ assertEquals(new Point2D(1, 4), path.getXY(1));
+ assertEquals(new Point2D(3, 4), path.getXY(2));
+ assertEquals(new Point2D(3, 2), path.getXY(3));
+ }
+
+ @Test
+ public static void testUnionCoincidentPolygonsWithReverseWinding() {
+ // Input polygons have CCW winding, result is always CW
+ Polygon polygon1 = new Polygon();
+ polygon1.startPath(new Point(3, 2));
+ polygon1.lineTo(new Point(3, 4));
+ polygon1.lineTo(new Point(1, 4));
+ polygon1.lineTo(new Point(1, 2));
+ polygon1.lineTo(new Point(3, 2));
+
+ Polygon polygon2 = new Polygon();
+ polygon2.startPath(new Point(1, 2));
+ polygon2.lineTo(new Point(3, 2));
+ polygon2.lineTo(new Point(3, 4));
+ polygon2.lineTo(new Point(1, 4));
+ polygon2.lineTo(new Point(1, 2));
+
+ Polygon expectedPolygon = new Polygon();
+ expectedPolygon.startPath(new Point(1, 2));
+ expectedPolygon.lineTo(new Point(1, 4));
+ expectedPolygon.lineTo(new Point(3, 4));
+ expectedPolygon.lineTo(new Point(3, 2));
+ expectedPolygon.lineTo(new Point(1, 2));
+
+ Geometry[] geomArray = new Geometry[] { polygon1, polygon2 };
+ SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor(
+ geomArray);
+ OperatorUnion union = (OperatorUnion) OperatorFactoryLocal
+ .getInstance().getOperator(Operator.Type.Union);
+ SpatialReference sr = SpatialReference.create(4326);
+
+ GeometryCursor outputCursor = union.execute(inputGeometries, sr, null);
+ Geometry result = outputCursor.next();
+
+ MultiPath path = (MultiPath)result;
+ assertEquals(1, path.getPathCount());
+ assertEquals(4, path.getPathEnd(0));
+ assertEquals(new Point2D(1, 2), path.getXY(0));
+ assertEquals(new Point2D(1, 4), path.getXY(1));
+ assertEquals(new Point2D(3, 4), path.getXY(2));
+ assertEquals(new Point2D(3, 2), path.getXY(3));
}
}
diff --git a/src/test/java/com/esri/core/geometry/TestWKBSupport.java b/src/test/java/com/esri/core/geometry/TestWKBSupport.java
index a55252fb..dfbaba16 100644
--- a/src/test/java/com/esri/core/geometry/TestWKBSupport.java
+++ b/src/test/java/com/esri/core/geometry/TestWKBSupport.java
@@ -24,6 +24,7 @@
package com.esri.core.geometry;
+import com.esri.core.geometry.ogc.OGCGeometry;
import java.io.IOException;
import java.nio.ByteBuffer;
import junit.framework.TestCase;
@@ -107,4 +108,12 @@ public void testWKB2() throws Exception {
}
+ @Test
+ public void testWKB3() throws Exception {
+ String multiPointWKT = "MULTIPOINT ZM(10 40 1 23, 40 30 2 45)";
+ OGCGeometry geometry = OGCGeometry.fromText(multiPointWKT);
+ ByteBuffer byteBuffer = geometry.asBinary();
+ OGCGeometry geomFromBinary = OGCGeometry.fromBinary(byteBuffer);
+ assertTrue(geometry.Equals(geomFromBinary));
+ }
}