Skip to content

Commit 492404c

Browse files
committed
added "public" to Envelope2D, added comments "in development" to OperatorSimplifyOGC.execute
1 parent a4d7efb commit 492404c

4 files changed

Lines changed: 188 additions & 26 deletions

File tree

src/com/esri/core/geometry/Envelope2D.java

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
/**
2828
* A class that represents axis parallel 2D rectangle.
2929
*/
30-
final class Envelope2D {
30+
public final class Envelope2D {
3131

3232
private final int XLESSXMIN = 1;
3333
// private final int XGREATERXMAX = 2;
@@ -36,13 +36,13 @@ final class Envelope2D {
3636
private final int XMASK = 3;
3737
private final int YMASK = 12;
3838

39-
public double xmin;
39+
double xmin;
4040

41-
public double ymin;
41+
double ymin;
4242

43-
public double xmax;
43+
double xmax;
4444

45-
public double ymax;
45+
double ymax;
4646

4747
public static Envelope2D construct(double _xmin, double _ymin,
4848
double _xmax, double _ymax) {
@@ -88,7 +88,7 @@ public void setCoords(Point2D center, double width, double height) {
8888
normalize();
8989
}
9090

91-
void setCoords(Point2D pt) {
91+
public void setCoords(Point2D pt) {
9292
xmin = pt.x;
9393
ymin = pt.y;
9494
xmax = pt.x;
@@ -99,7 +99,7 @@ public void setCoords(Envelope2D envSrc) {
9999
setCoords(envSrc.xmin, envSrc.ymin, envSrc.xmax, envSrc.ymax);
100100
}
101101

102-
Envelope2D getInflated(double dx, double dy) {
102+
public Envelope2D getInflated(double dx, double dy) {
103103
Envelope2D env = new Envelope2D();
104104
env.setCoords(this.xmin, this.ymin, this.xmax, this.ymax);
105105
env.inflate(dx, dy);
@@ -110,8 +110,6 @@ Envelope2D getInflated(double dx, double dy) {
110110
* Sets the envelope from the array of points. The envelope will be set to
111111
* empty if the array is null.
112112
*/
113-
// TODO This should either call setFromPoints(points, int count) or vice
114-
// versa
115113
public void setFromPoints(Point2D[] points) {
116114
if (points == null || points.length == 0) {
117115
setEmpty();
@@ -270,7 +268,6 @@ public boolean isIntersectingNE(Envelope2D other) {
270268
* Intersects this envelope with the other. Returns True if the result is
271269
* not empty.
272270
*/
273-
274271
public boolean intersect(Envelope2D other) {
275272
if (isEmpty() || other.isEmpty())
276273
return false;
@@ -416,11 +413,6 @@ public double getHeight() {
416413
return ymax - ymin;
417414
}
418415

419-
// public Envelope2D getCopy() {
420-
// Envelope2D ret = new Envelope2D(xmin, ymin, xmax, ymax);
421-
// return ret;
422-
// }
423-
424416
/**
425417
* Moves the Envelope by given distance.
426418
*/
@@ -437,7 +429,7 @@ public void centerAt(double x, double y) {
437429
move(x - getCenterX(), y - getCenterY());
438430
}
439431

440-
public void centerAt(Point2D pt) {
432+
void centerAt(Point2D pt) {
441433
centerAt(pt.x, pt.y);
442434
}
443435

@@ -462,19 +454,19 @@ public void normalize() {
462454
ymax = max;
463455
}
464456

465-
void queryLowerLeft(Point2D pt) {
457+
public void queryLowerLeft(Point2D pt) {
466458
pt.setCoords(xmin, ymin);
467459
}
468460

469-
void queryLowerRight(Point2D pt) {
461+
public void queryLowerRight(Point2D pt) {
470462
pt.setCoords(xmax, ymin);
471463
}
472464

473-
void queryUpperLeft(Point2D pt) {
465+
public void queryUpperLeft(Point2D pt) {
474466
pt.setCoords(xmin, ymax);
475467
}
476468

477-
void queryUpperRight(Point2D pt) {
469+
public void queryUpperRight(Point2D pt) {
478470
pt.setCoords(xmax, ymax);
479471
}
480472

@@ -664,7 +656,7 @@ else if (p.y > ymax)
664656
// boundary,
665657
// it is more efficient to perform ProjectToBoundary before using this
666658
// function).
667-
public double _boundaryDistance(Point2D pt) {
659+
double _boundaryDistance(Point2D pt) {
668660
if (isEmpty())
669661
return NumberUtils.NaN();
670662

@@ -687,7 +679,7 @@ public double _boundaryDistance(Point2D pt) {
687679
}
688680

689681
// returns 0,..3 depending on which side pt lies.
690-
public int _envelopeSide(Point2D pt) {
682+
int _envelopeSide(Point2D pt) {
691683

692684
if (isEmpty())
693685
return -1;
@@ -715,7 +707,7 @@ public int _envelopeSide(Point2D pt) {
715707
// 100.0;
716708
}
717709

718-
int clipLine(Point2D p1, Point2D p2)
710+
public int clipLine(Point2D p1, Point2D p2)
719711
// Modified Cohen-Sutherland Line-Clipping Algorithm
720712
// returns:
721713
// 0 - the segment is outside of the clipping window

src/com/esri/core/geometry/OperatorSimplifyOGC.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
package com.esri.core.geometry;
2525

2626
/**
27-
* Simplifies geometry or determines if geometry is simple. Tries to follow OGC specification.
27+
* Simplifies geometry or determines if geometry is simple. Tries to follow OGC specification 1.2.1.
2828
* Uses tolerance to determine equal vertices or points of intersection.
2929
*
3030
*/
@@ -35,7 +35,7 @@ public Operator.Type getType() {
3535
}
3636

3737
/**
38-
*Tests if the Geometry is simple for OGC spec.
38+
*Tests if the Geometry is simple for OGC spec 1.2.1.
3939
*@param geom The Geometry to be tested.
4040
*@param bForceTest When True, the Geometry will be tested regardless of the IsKnownSimple flag.
4141
*
@@ -47,6 +47,8 @@ public abstract boolean isSimpleOGC(Geometry geom,
4747
NonSimpleResult result, ProgressTracker progressTracker);
4848

4949
/**
50+
* This method is still in development. Use Operator_simplify for now.
51+
*
5052
*Performs the Simplify operation on the geometry set.
5153
*@return Returns a GeometryCursor of simplified geometries.
5254
*/
@@ -55,7 +57,9 @@ public abstract GeometryCursor execute(GeometryCursor geoms,
5557
ProgressTracker progressTracker);
5658

5759
/**
58-
*Performs the Simplify operation on a Geometry
60+
* This method is still in development. Use Operator_simplify for now.
61+
*
62+
*Performs the Simplify operation on a Geometry.
5963
*@return Returns a simple Geometry.
6064
*/
6165
public abstract Geometry execute(Geometry geom, SpatialReference sr,

src/com/esri/core/geometry/TopologicalOperations.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ private void collectPolygonPathsPreservingFrom_(int geometryFrom,
150150
int vertex = first_vertex;
151151
int cluster = m_topo_graph.getClusterFromVertex(vertex);
152152
int dir = 1;
153+
//Walk the chain of half edges, preferably selecting vertices that belong to the
154+
//polygon path we have started from.
153155
do {
154156
int vertex_dominant = getVertexByID_(vertex, geometry_dominant);
155157
shape.addVertex(newPath, vertex_dominant);

unittest/com/esri/core/geometry/TestOGC.java

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import junit.framework.TestCase;
44

55
import com.esri.core.geometry.ogc.OGCGeometry;
6+
import com.esri.core.geometry.ogc.OGCGeometryCollection;
67
import com.esri.core.geometry.ogc.OGCLineString;
78
import com.esri.core.geometry.ogc.OGCMultiPoint;
9+
import com.esri.core.geometry.ogc.OGCMultiPolygon;
810
import com.esri.core.geometry.ogc.OGCPoint;
911
import com.esri.core.geometry.ogc.OGCPolygon;
1012
import com.esri.core.geometry.ogc.OGCConcreteGeometryCollection;
@@ -362,6 +364,168 @@ public void test_polygon_is_simple_for_OGC() {
362364
}
363365
}
364366

367+
/*
368+
This will fail
369+
public void test_polygon_simplify_for_OGC() {
370+
try {
371+
{
372+
String s = "{\"rings\":[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]}";
373+
OGCGeometry g = OGCGeometry.fromJson(s);
374+
boolean res = g.isSimple();
375+
assertTrue(res);
376+
assertTrue(g.isSimpleRelaxed());
377+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
378+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
379+
assertTrue(og.geometryType().equals("Polygon"));
380+
assertTrue(((OGCPolygon)og).numInteriorRing() == 0);
381+
}
382+
383+
{// exterior ring is self-tangent
384+
String s = "{\"rings\":[[[0, 0], [0, 10], [5, 5], [10, 10], [10, 0], [5, 5], [0, 0]]]}";
385+
OGCGeometry g = OGCGeometry.fromJson(s);
386+
boolean res = g.isSimple();
387+
assertTrue(!res);
388+
assertTrue(g.isSimpleRelaxed());
389+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
390+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
391+
res = og.isSimple();
392+
assertTrue(res);
393+
assertTrue(og.geometryType().equals("MultiPolygon"));
394+
assertTrue(((OGCGeometryCollection)og).numGeometries() == 2);
395+
}
396+
397+
{// ring orientation (hole is cw)
398+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[0, 0], [5, 5], [10, 0], [0, 0]]]}";
399+
OGCGeometry g = OGCGeometry.fromJson(s);
400+
boolean res = g.isSimple();
401+
assertTrue(!res);
402+
assertTrue(!g.isSimpleRelaxed());
403+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
404+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
405+
res = og.isSimple();
406+
assertTrue(res);
407+
assertTrue(og.geometryType().equals("Polygon"));
408+
assertTrue(((OGCPolygon)og).numInteriorRing() == 1);
409+
}
410+
411+
{// ring order
412+
String s = "{\"rings\":[[[0, 0], [10, 0], [5, 5], [0, 0]], [[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]]]}";
413+
OGCGeometry g = OGCGeometry.fromJson(s);
414+
boolean res = g.isSimple();
415+
assertTrue(!res);
416+
assertTrue(g.isSimpleRelaxed());
417+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
418+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
419+
res = og.isSimple();
420+
assertTrue(res);
421+
assertTrue(og.geometryType().equals("Polygon"));
422+
}
423+
424+
{
425+
// hole is self tangent
426+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[0, 0], [5, 5], [10, 0], [10, 10], [5, 5], [0, 10], [0, 0]]]}";
427+
OGCGeometry g = OGCGeometry.fromJson(s);
428+
boolean res = g.isSimple();
429+
assertTrue(!res);
430+
assertTrue(g.isSimpleRelaxed());
431+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
432+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
433+
res = og.isSimple();
434+
assertTrue(res);
435+
assertTrue(og.geometryType().equals("Polygon"));
436+
assertTrue(((OGCPolygon)og).numInteriorRing() == 2);
437+
}
438+
{
439+
// two holes touch
440+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[0, 0], [10, 0], [5, 5], [0, 0]], [[10, 10], [0, 10], [5, 5], [10, 10]]]}";
441+
OGCGeometry g = OGCGeometry.fromJson(s);
442+
boolean res = g.isSimple();
443+
assertTrue(res);
444+
assertTrue(g.isSimpleRelaxed());
445+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
446+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
447+
assertTrue(og.geometryType().equals("Polygon"));
448+
assertTrue(((OGCPolygon)og).numInteriorRing() == 2);
449+
}
450+
{
451+
// two holes touch, bad orientation
452+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [100, 100], [100, -100], [-100, -100]], [[0, 0], [5, 5], [10, 0], [0, 0]], [[10, 10], [0, 10], [5, 5], [10, 10]]]}";
453+
OGCGeometry g = OGCGeometry.fromJson(s);
454+
boolean res = g.isSimple();
455+
assertTrue(!res);
456+
assertTrue(!g.isSimpleRelaxed());
457+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
458+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
459+
assertTrue(og.geometryType().equals("Polygon"));
460+
assertTrue(((OGCPolygon)og).numInteriorRing() == 2);
461+
}
462+
463+
{
464+
// hole touches exterior in two spots
465+
//OperatorSimplifyOGC produces a multipolygon with two polygons without holes.
466+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [0, 100], [100, 100], [100, -100], [0, -100], [-100, -100]], [[0, -100], [10, 0], [0, 100], [-10, 0], [0, -100]]]}";
467+
OGCGeometry g = OGCGeometry.fromJson(s);
468+
boolean res = g.isSimple();
469+
assertTrue(!res);
470+
assertTrue(g.isSimpleRelaxed());
471+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
472+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
473+
assertTrue(og.geometryType().equals("MultiPolygon"));
474+
assertTrue(((OGCMultiPolygon)og).numGeometries() == 2);
475+
assertTrue(((OGCPolygon)((OGCMultiPolygon)og).geometryN(0)).numInteriorRing() == 0);
476+
assertTrue(((OGCPolygon)((OGCMultiPolygon)og).geometryN(1)).numInteriorRing() == 0);
477+
}
478+
479+
{
480+
// hole touches exterior in one spot
481+
//OperatorSimplifyOGC produces a polygons with a hole.
482+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [0, 100], [100, 100], [100, -100], [0, -100], [-100, -100]], [[0, -100], [10, 0], [0, 90], [-10, 0], [0, -100]]]}";
483+
OGCGeometry g = OGCGeometry.fromJson(s);
484+
boolean res = g.isSimple();
485+
assertTrue(res);
486+
assertTrue(g.isSimpleRelaxed());
487+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
488+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
489+
assertTrue(og.geometryType().equals("Polygon"));
490+
assertTrue(((OGCPolygon)og).numInteriorRing() == 1);
491+
}
492+
493+
{
494+
// exterior has inversion (non simple for OGC)
495+
//OperatorSimplifyOGC produces a polygons with a hole.
496+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [0, 100], [100, 100], [100, -100], [0, -100], [10, 0], [0, 90], [-10, 0], [0, -100], [-100, -100]]]}";
497+
OGCGeometry g = OGCGeometry.fromJson(s);
498+
boolean res = g.isSimple();
499+
assertTrue(!res);
500+
assertTrue(g.isSimpleRelaxed());
501+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
502+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
503+
assertTrue(og.geometryType().equals("Polygon"));
504+
assertTrue(((OGCPolygon)og).numInteriorRing() == 1);
505+
}
506+
507+
{
508+
// two holes touch in one spot, and they also touch exterior in
509+
// two spots, producing disconnected interior
510+
//OperatorSimplifyOGC produces two polygons with no holes.
511+
String s = "{\"rings\":[[[-100, -100], [-100, 100], [0, 100], [100, 100], [100, -100], [0, -100], [-100, -100]], [[0, -100], [10, -50], [0, 0], [-10, -50], [0, -100]], [[0, 0], [10, 50], [0, 100], [-10, 50], [0, 0]]]}";
512+
OGCGeometry g = OGCGeometry.fromJson(s);
513+
boolean res = g.isSimple();
514+
assertTrue(!res);
515+
assertTrue(g.isSimpleRelaxed());
516+
Geometry resg = OperatorSimplifyOGC.local().execute(g.getEsriGeometry(), null, true, null);
517+
OGCGeometry og = OGCGeometry.createFromEsriGeometry(resg, null);
518+
assertTrue(og.geometryType().equals("MultiPolygon"));
519+
assertTrue(((OGCMultiPolygon)og).numGeometries() == 2);
520+
assertTrue(((OGCPolygon)((OGCMultiPolygon)og).geometryN(0)).numInteriorRing() == 0);
521+
assertTrue(((OGCPolygon)((OGCMultiPolygon)og).geometryN(1)).numInteriorRing() == 0);
522+
}
523+
} catch (Exception ex) {
524+
assertTrue(false);
525+
}
526+
}
527+
*/
528+
365529
public void test_polyline_is_simple_for_OGC() {
366530
try {
367531
{

0 commit comments

Comments
 (0)