Skip to content

Commit bbfe1d3

Browse files
authored
Stolstov/issue 172 (#174)
1 parent f68c241 commit bbfe1d3

7 files changed

Lines changed: 177 additions & 10 deletions

File tree

src/main/java/com/esri/core/geometry/ConvexHull.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,13 @@ private ConvexHull(Point2D[] points, int n) {
5252

5353
/**
5454
* Adds a geometry to the current bounding geometry using an incremental algorithm for dynamic insertion.
55-
* \param geometry The geometry to add to the bounding geometry.
55+
* @param geometry The geometry to add to the bounding geometry.
5656
*/
5757

5858
void addGeometry(Geometry geometry) {
59+
if (geometry.isEmpty())
60+
return;
61+
5962
int type = geometry.getType().value();
6063

6164
if (MultiVertexGeometry.isMultiVertex(type))
@@ -80,6 +83,9 @@ Geometry getBoundingGeometry() {
8083
Point point = new Point();
8184
int first = m_tree_hull.getFirst(-1);
8285
Polygon hull = new Polygon(m_shape.getVertexDescription());
86+
if (m_tree_hull.size(-1) == 0)
87+
return hull;
88+
8389
m_shape.queryPoint(m_tree_hull.getElement(first), point);
8490
hull.startPath(point);
8591

src/main/java/com/esri/core/geometry/ogc/OGCConcreteGeometryCollection.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,19 @@
2727
import com.esri.core.geometry.Envelope;
2828
import com.esri.core.geometry.Geometry;
2929
import com.esri.core.geometry.GeometryCursor;
30+
import com.esri.core.geometry.GeometryException;
31+
import com.esri.core.geometry.MultiPath;
32+
import com.esri.core.geometry.MultiPoint;
33+
import com.esri.core.geometry.MultiVertexGeometry;
3034
import com.esri.core.geometry.NumberUtils;
35+
import com.esri.core.geometry.OperatorConvexHull;
3136
import com.esri.core.geometry.Polygon;
37+
import com.esri.core.geometry.SimpleGeometryCursor;
3238
import com.esri.core.geometry.SpatialReference;
39+
import com.esri.core.geometry.VertexDescription;
3340
import com.esri.core.geometry.GeoJsonExportFlags;
3441
import com.esri.core.geometry.OperatorExportToGeoJson;
42+
import com.esri.core.geometry.Point;
3543

3644
import java.nio.ByteBuffer;
3745
import java.nio.ByteOrder;
@@ -377,6 +385,59 @@ public int getGeometryID() {
377385
}
378386

379387
}
388+
389+
@Override
390+
public OGCGeometry convexHull() {
391+
GeometryCursor cursor = OperatorConvexHull.local().execute(
392+
getEsriGeometryCursor(), false, null);
393+
MultiPoint mp = new MultiPoint();
394+
Polygon polygon = new Polygon();
395+
VertexDescription vd = null;
396+
for (Geometry geom = cursor.next(); geom != null; geom = cursor.next()) {
397+
vd = geom.getDescription();
398+
if (geom.isEmpty())
399+
continue;
400+
401+
if (geom.getType() == Geometry.Type.Polygon) {
402+
polygon.add((MultiPath) geom, false);
403+
}
404+
else if (geom.getType() == Geometry.Type.Polyline) {
405+
mp.add((MultiVertexGeometry) geom, 0, -1);
406+
}
407+
else if (geom.getType() == Geometry.Type.Point) {
408+
mp.add((Point) geom);
409+
}
410+
else {
411+
throw new GeometryException("internal error");
412+
}
413+
}
414+
415+
Geometry resultGeom = null;
416+
if (!mp.isEmpty()) {
417+
resultGeom = OperatorConvexHull.local().execute(mp, null);
418+
}
419+
420+
if (!polygon.isEmpty()) {
421+
if (!resultGeom.isEmpty()) {
422+
Geometry[] geoms = { resultGeom, polygon };
423+
resultGeom = OperatorConvexHull.local().execute(
424+
new SimpleGeometryCursor(geoms), true, null).next();
425+
}
426+
else {
427+
resultGeom = polygon;
428+
}
429+
}
430+
431+
if (resultGeom == null) {
432+
Point pt = new Point();
433+
if (vd != null)
434+
pt.assignVertexDescription(vd);
435+
436+
return new OGCPoint(pt, getEsriSpatialReference());
437+
}
438+
439+
return OGCGeometry.createFromEsriGeometry(resultGeom, getEsriSpatialReference(), false);
440+
}
380441

381442
List<OGCGeometry> geometries;
382443

src/main/java/com/esri/core/geometry/ogc/OGCCurve.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public boolean isRing() {
4141

4242
@Override
4343
public OGCGeometry boundary() {
44+
if (isEmpty())
45+
return new OGCMultiPoint(this.getEsriSpatialReference());
46+
4447
if (isClosed())
4548
return new OGCMultiPoint(new MultiPoint(getEsriGeometry()
4649
.getDescription()), esriSR);// return empty multipoint;

src/main/java/com/esri/core/geometry/ogc/OGCGeometry.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -433,18 +433,16 @@ public OGCGeometry centroid() {
433433
OperatorCentroid2D op = (OperatorCentroid2D) OperatorFactoryLocal.getInstance()
434434
.getOperator(Operator.Type.Centroid2D);
435435

436-
Point2D centroid = op.execute(getEsriGeometry(), null);
437-
if (centroid == null) {
438-
return OGCGeometry.createFromEsriGeometry(new Point(), esriSR);
439-
}
440-
return OGCGeometry.createFromEsriGeometry(new Point(centroid), esriSR);
436+
Point2D centroid = op.execute(getEsriGeometry(), null);
437+
if (centroid == null) {
438+
return OGCGeometry.createFromEsriGeometry(new Point(), esriSR);
439+
}
440+
return OGCGeometry.createFromEsriGeometry(new Point(centroid), esriSR);
441441
}
442442

443443
public OGCGeometry convexHull() {
444-
com.esri.core.geometry.OperatorConvexHull op = (OperatorConvexHull) OperatorFactoryLocal
445-
.getInstance().getOperator(Operator.Type.ConvexHull);
446-
com.esri.core.geometry.GeometryCursor cursor = op.execute(
447-
getEsriGeometryCursor(), true, null);
444+
com.esri.core.geometry.GeometryCursor cursor = OperatorConvexHull.local().execute(
445+
getEsriGeometryCursor(), false, null);
448446
return OGCGeometry.createFromEsriCursor(cursor, esriSR);
449447
}
450448

src/main/java/com/esri/core/geometry/ogc/OGCLineString.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public OGCPoint pointN(int n) {
8282

8383
@Override
8484
public boolean isClosed() {
85+
if (isEmpty())
86+
return false;
87+
8588
return multiPath.isClosedPathInXYPlane(0);
8689
}
8790

src/test/java/com/esri/core/geometry/TestConvexHull.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import junit.framework.TestCase;
2828
import org.junit.Test;
2929

30+
import com.esri.core.geometry.ogc.OGCGeometry;
31+
3032
public class TestConvexHull extends TestCase {
3133
@Override
3234
protected void setUp() throws Exception {
@@ -992,5 +994,69 @@ public void testHullTickTock() {
992994
assertTrue(p5.x == -5.0 && p5.y == 1.25);
993995
assertTrue(p6.x == 0.0 && p6.y == 10.0);
994996
}
997+
998+
@Test
999+
public void testHullIssueGithub172() {
1000+
{
1001+
//empty
1002+
OGCGeometry geom = OGCGeometry.fromText("MULTIPOINT EMPTY");
1003+
OGCGeometry result = geom.convexHull();
1004+
String text = result.asText();
1005+
assertTrue(text.compareTo("POINT EMPTY") == 0);
1006+
}
1007+
{
1008+
//Point
1009+
OGCGeometry geom = OGCGeometry.fromText("POINT (1 2)");
1010+
OGCGeometry result = geom.convexHull();
1011+
String text = result.asText();
1012+
assertTrue(text.compareTo("POINT (1 2)") == 0);
1013+
}
1014+
{
1015+
//line
1016+
OGCGeometry geom = OGCGeometry.fromText("MULTIPOINT (1 1, 2 2)");
1017+
OGCGeometry result = geom.convexHull();
1018+
String text = result.asText();
1019+
assertTrue(text.compareTo("LINESTRING (1 1, 2 2)") == 0);
1020+
}
1021+
{
1022+
//empty
1023+
OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION EMPTY");
1024+
OGCGeometry result = geom.convexHull();
1025+
String text = result.asText();
1026+
assertTrue(text.compareTo("POINT EMPTY") == 0);
1027+
}
1028+
1029+
{
1030+
//empty
1031+
OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION (POINT (1 2))");
1032+
OGCGeometry result = geom.convexHull();
1033+
String text = result.asText();
1034+
assertTrue(text.compareTo("POINT (1 2)") == 0);
1035+
}
1036+
1037+
{
1038+
//empty
1039+
OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION(POLYGON EMPTY, POINT(1 1), LINESTRING EMPTY, MULTIPOLYGON EMPTY, MULTILINESTRING EMPTY)");
1040+
OGCGeometry result = geom.convexHull();
1041+
String text = result.asText();
1042+
assertTrue(text.compareTo("POINT (1 1)") == 0);
1043+
}
1044+
1045+
{
1046+
//empty
1047+
OGCGeometry geom = OGCGeometry.fromText("GEOMETRYCOLLECTION(POLYGON EMPTY, LINESTRING (1 1, 2 2), POINT(3 3), LINESTRING EMPTY, MULTIPOLYGON EMPTY, MULTILINESTRING EMPTY)");
1048+
OGCGeometry result = geom.convexHull();
1049+
String text = result.asText();
1050+
assertTrue(text.compareTo("LINESTRING (1 1, 3 3)") == 0);
1051+
}
1052+
1053+
{
1054+
//empty
1055+
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)))");
1056+
OGCGeometry result = geom.convexHull();
1057+
String text = result.asText();
1058+
assertTrue(text.compareTo("POLYGON ((-10 -10, 10 -10, 10 10, -10 10, -10 -10))") == 0);
1059+
}
1060+
}
9951061

9961062
}

src/test/java/com/esri/core/geometry/TestOGC.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,4 +926,34 @@ public void testPolylineSimplifyIssueGithub52() throws Exception {
926926
}
927927
}
928928

929+
@Test
930+
public void testEmptyBoundary() throws Exception {
931+
{
932+
OGCGeometry g = OGCGeometry.fromText("POINT EMPTY");
933+
OGCGeometry b = g.boundary();
934+
assertTrue(b.asText().compareTo("MULTIPOINT EMPTY") == 0);
935+
}
936+
{
937+
OGCGeometry g = OGCGeometry.fromText("MULTIPOINT EMPTY");
938+
OGCGeometry b = g.boundary();
939+
assertTrue(b.asText().compareTo("MULTIPOINT EMPTY") == 0);
940+
}
941+
{
942+
OGCGeometry g = OGCGeometry.fromText("LINESTRING EMPTY");
943+
OGCGeometry b = g.boundary();
944+
assertTrue(b.asText().compareTo("MULTIPOINT EMPTY") == 0);
945+
}
946+
{
947+
OGCGeometry g = OGCGeometry.fromText("POLYGON EMPTY");
948+
OGCGeometry b = g.boundary();
949+
assertTrue(b.asText().compareTo("MULTILINESTRING EMPTY") == 0);
950+
}
951+
{
952+
OGCGeometry g = OGCGeometry.fromText("MULTIPOLYGON EMPTY");
953+
OGCGeometry b = g.boundary();
954+
assertTrue(b.asText().compareTo("MULTILINESTRING EMPTY") == 0);
955+
}
956+
}
957+
958+
929959
}

0 commit comments

Comments
 (0)