From cdca4e75e845cc60e0898d2c5eae2255aebbc16b Mon Sep 17 00:00:00 2001 From: Carlos Palma Date: Fri, 7 Feb 2020 13:49:19 +0100 Subject: [PATCH 1/2] Added methods for checking orientation and if ring is exterior or interior in ExteriorRingOrientation and InteriorRingOrientation from validation package --- .../event/ExteriorRingOrientation.java | 54 +++++++++++++++++++ .../event/InteriorRingOrientation.java | 54 +++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java index 0af1c350a1..200674e484 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java @@ -40,6 +40,9 @@ import org.deegree.geometry.primitive.Ring; import org.deegree.geometry.primitive.patches.PolygonPatch; +import org.deegree.cs.coordinatesystems.ICRS; +import org.deegree.cs.components.Axis; + /** * {@link GeometryValidationEvent} that indicates the orientation of an exterior {@link Ring} of a {@link PolygonPatch}. * @@ -87,5 +90,56 @@ public PolygonPatch getPatch() { public boolean isClockwise() { return isClockwise; } + + /** + * Returns true if the geometry has a left handed CRS. + * + * @return true if geometry has a left handed CRS, false if CRS is right handed + */ + public boolean hasLeftHandedSrs() { + ICRS crs = patch.getExteriorRing().getCoordinateSystem(); + + // get number of dimensions (it should be 2) + if ( crs.getDimension() == 2 ) { + int axis1 = crs.getAxis()[0].getOrientation(); + int axis2 = crs.getAxis()[1].getOrientation(); + + // check if CRS is left handed + if ( axis1 == Axis.AO_EAST || axis1 == Axis.AO_WEST ) { + if ( axis1 == Axis.AO_EAST && ( axis2 == Axis.AO_SOUTH || axis2 == Axis.AO_DOWN ) ) { + return true; + } + else if ( axis1 == Axis.AO_WEST && ( axis2 == Axis.AO_NORTH || axis2 == Axis.AO_UP ) ) { + return true; + } + } + else { + if ( ( axis1 == Axis.AO_SOUTH || axis1 == Axis.AO_DOWN ) && axis2 == Axis.AO_WEST ) { + return true; + } + else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_EAST ) { + return true; + } + } + } + + // return false in any other case + return false; + } + + /** + * Returns true if the geometry is an exterior boundary. + * + * @return true if geometry is an exterior boundary, false if it's interior + */ + public boolean isExterior() { + boolean isExterior = !isClockwise; + + if ( hasLeftHandedSrs() ) { + isExterior = !isExterior; + } + + return isExterior; + } } diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java index a3a051caa1..6c8edc2374 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java @@ -40,6 +40,9 @@ import org.deegree.geometry.primitive.Ring; import org.deegree.geometry.primitive.patches.PolygonPatch; +import org.deegree.cs.coordinatesystems.ICRS; +import org.deegree.cs.components.Axis; + /** * {@link GeometryValidationEvent} that indicates the orientation of an interior {@link Ring} of a {@link PolygonPatch}. * @@ -102,5 +105,56 @@ public int getRingIdx() { public boolean isClockwise() { return isClockwise; } + + /** + * Returns true if the geometry has a left handed CRS. + * + * @return true if geometry has a left handed CRS, false if CRS is right handed + */ + public boolean hasLeftHandedSrs() { + ICRS crs = patch.getInteriorRings().get( ringIdx ).getCoordinateSystem(); + + // get number of dimensions (it should be 2) + if ( crs.getDimension() == 2 ) { + int axis1 = crs.getAxis()[0].getOrientation(); + int axis2 = crs.getAxis()[1].getOrientation(); + + // check if CRS is left handed + if ( axis1 == Axis.AO_EAST || axis1 == Axis.AO_WEST ) { + if ( axis1 == Axis.AO_EAST && ( axis2 == Axis.AO_SOUTH || axis2 == Axis.AO_DOWN ) ) { + return true; + } + else if ( axis1 == Axis.AO_WEST && ( axis2 == Axis.AO_NORTH || axis2 == Axis.AO_UP ) ) { + return true; + } + } + else { + if ( ( axis1 == Axis.AO_SOUTH || axis1 == Axis.AO_DOWN ) && axis2 == Axis.AO_WEST ) { + return true; + } + else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_EAST ) { + return true; + } + } + } + + // return false in any other case + return false; + } + + /** + * Returns true if the geometry is an interior boundary. + * + * @return true if geometry is an interior boundary, false if it's exterior + */ + public boolean isInterior() { + boolean isInterior = isClockwise; + + if ( hasLeftHandedSrs() ) { + isInterior = !isInterior; + } + + return isInterior; + } } From d0b59ac4e62f5066123b6ba12cba6ccf68467a24 Mon Sep 17 00:00:00 2001 From: Carlos Palma Date: Thu, 5 Mar 2020 13:51:30 +0100 Subject: [PATCH 2/2] Included method in AbstractGeometryValidationEvent to be reused by ExteriorRingOrientation and ExteriorRingOrientation classes. Added test for ring orientation using left-handed and right-handed CRS. --- .../validation/GeometryValidatorTest.java | 34 +++++++++++++++ .../AbstractGeometryValidationEvent.java | 37 +++++++++++++++++ .../event/ExteriorRingOrientation.java | 41 +------------------ .../event/InteriorRingOrientation.java | 41 +------------------ 4 files changed, 73 insertions(+), 80 deletions(-) diff --git a/deegree-core/deegree-core-base/src/test/java/org/deegree/geometry/validation/GeometryValidatorTest.java b/deegree-core/deegree-core-base/src/test/java/org/deegree/geometry/validation/GeometryValidatorTest.java index 6b3c8c2c80..47e962f259 100644 --- a/deegree-core/deegree-core-base/src/test/java/org/deegree/geometry/validation/GeometryValidatorTest.java +++ b/deegree-core/deegree-core-base/src/test/java/org/deegree/geometry/validation/GeometryValidatorTest.java @@ -49,7 +49,9 @@ import junit.framework.Assert; import org.deegree.commons.xml.XMLParsingException; +import org.deegree.cs.coordinatesystems.ICRS; import org.deegree.cs.exceptions.UnknownCRSException; +import org.deegree.cs.persistence.CRSManager; import org.deegree.geometry.Geometry; import org.deegree.geometry.validation.event.CurveDiscontinuity; import org.deegree.geometry.validation.event.CurveSelfIntersection; @@ -160,6 +162,38 @@ public void validatePolygon() Assert.assertTrue( ( (InteriorRingOrientation) eventHandler.getEvents().get( 2 ) ).isClockwise() ); } + @Test + public void validatePolygonExteriorAndInterior() + throws XMLStreamException, FactoryConfigurationError, IOException, XMLParsingException, + UnknownCRSException { + DummyValidationEventHandler eventHandler = new DummyValidationEventHandler(); + GeometryValidator validator = new GeometryValidator( eventHandler ); + Geometry geom = parseGeometry( "Polygon.gml" ); + Assert.assertTrue( validator.validateGeometry( geom ) ); + Assert.assertEquals( 3, eventHandler.getEvents().size() ); + + // get rings + ExteriorRingOrientation exterior = (ExteriorRingOrientation) eventHandler.getEvents().get( 0 ); + InteriorRingOrientation interior1 = (InteriorRingOrientation) eventHandler.getEvents().get( 1 ); + InteriorRingOrientation interior2 = (InteriorRingOrientation) eventHandler.getEvents().get( 2 ); + + // check for exterior and interior rings with a right handed CRS + Assert.assertTrue( exterior.isExterior() ); + Assert.assertTrue( interior1.isInterior() ); + Assert.assertTrue( interior2.isInterior() ); + + // substitute original right handed CRS for a new left handed one, maintaining polygon orientation + ICRS leftHandedCrs = CRSManager.getCRSRef( "urn:ogc:def:crs:epsg::4326" ); + exterior.getPatch().getExteriorRing().setCoordinateSystem( leftHandedCrs ); + interior1.getPatch().getInteriorRings().get( 0 ).setCoordinateSystem( leftHandedCrs ); + interior2.getPatch().getInteriorRings().get( 1 ).setCoordinateSystem( leftHandedCrs ); + + // check for exterior and interior rings with a left handed CRS + Assert.assertFalse( exterior.isExterior() ); + Assert.assertFalse( interior1.isInterior() ); + Assert.assertFalse( interior2.isInterior() ); + } + @Test public void validatePolygonExteriorClockwise() throws XMLStreamException, FactoryConfigurationError, IOException, XMLParsingException, diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/AbstractGeometryValidationEvent.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/AbstractGeometryValidationEvent.java index b514254164..dd1e8830bb 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/AbstractGeometryValidationEvent.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/AbstractGeometryValidationEvent.java @@ -37,6 +37,9 @@ import java.util.List; +import org.deegree.cs.coordinatesystems.ICRS; +import org.deegree.cs.components.Axis; + /** * Abstract base class for {@link GeometryValidationEvent} implementations. * @@ -65,4 +68,38 @@ public List getGeometryParticleHierarchy() { return geometryParticleHierachy; } + /** + * Returns true if the geometry has a left handed CRS. + * + * @return true if geometry has a left handed CRS, false if CRS is right handed + */ + protected boolean isLeftHanded( ICRS crs ) { + // get number of dimensions (it should be 2) + if ( crs.getDimension() == 2 ) { + int axis1 = crs.getAxis()[0].getOrientation(); + int axis2 = crs.getAxis()[1].getOrientation(); + + // check if CRS is left handed + if ( axis1 == Axis.AO_EAST || axis1 == Axis.AO_WEST ) { + if ( axis1 == Axis.AO_EAST && ( axis2 == Axis.AO_SOUTH || axis2 == Axis.AO_DOWN ) ) { + return true; + } + else if ( axis1 == Axis.AO_WEST && ( axis2 == Axis.AO_NORTH || axis2 == Axis.AO_UP ) ) { + return true; + } + } + else { + if ( ( axis1 == Axis.AO_SOUTH || axis1 == Axis.AO_DOWN ) && axis2 == Axis.AO_WEST ) { + return true; + } + else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_EAST ) { + return true; + } + } + } + + // return false in any other case + return false; + } + } diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java index 200674e484..675021a862 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/ExteriorRingOrientation.java @@ -40,9 +40,6 @@ import org.deegree.geometry.primitive.Ring; import org.deegree.geometry.primitive.patches.PolygonPatch; -import org.deegree.cs.coordinatesystems.ICRS; -import org.deegree.cs.components.Axis; - /** * {@link GeometryValidationEvent} that indicates the orientation of an exterior {@link Ring} of a {@link PolygonPatch}. * @@ -90,42 +87,6 @@ public PolygonPatch getPatch() { public boolean isClockwise() { return isClockwise; } - - /** - * Returns true if the geometry has a left handed CRS. - * - * @return true if geometry has a left handed CRS, false if CRS is right handed - */ - public boolean hasLeftHandedSrs() { - ICRS crs = patch.getExteriorRing().getCoordinateSystem(); - - // get number of dimensions (it should be 2) - if ( crs.getDimension() == 2 ) { - int axis1 = crs.getAxis()[0].getOrientation(); - int axis2 = crs.getAxis()[1].getOrientation(); - - // check if CRS is left handed - if ( axis1 == Axis.AO_EAST || axis1 == Axis.AO_WEST ) { - if ( axis1 == Axis.AO_EAST && ( axis2 == Axis.AO_SOUTH || axis2 == Axis.AO_DOWN ) ) { - return true; - } - else if ( axis1 == Axis.AO_WEST && ( axis2 == Axis.AO_NORTH || axis2 == Axis.AO_UP ) ) { - return true; - } - } - else { - if ( ( axis1 == Axis.AO_SOUTH || axis1 == Axis.AO_DOWN ) && axis2 == Axis.AO_WEST ) { - return true; - } - else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_EAST ) { - return true; - } - } - } - - // return false in any other case - return false; - } /** * Returns true if the geometry is an exterior boundary. @@ -135,7 +96,7 @@ else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_ public boolean isExterior() { boolean isExterior = !isClockwise; - if ( hasLeftHandedSrs() ) { + if ( isLeftHanded( patch.getExteriorRing().getCoordinateSystem() ) ) { isExterior = !isExterior; } diff --git a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java index 6c8edc2374..b32528e5d8 100644 --- a/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java +++ b/deegree-core/deegree-core-geometry/src/main/java/org/deegree/geometry/validation/event/InteriorRingOrientation.java @@ -40,9 +40,6 @@ import org.deegree.geometry.primitive.Ring; import org.deegree.geometry.primitive.patches.PolygonPatch; -import org.deegree.cs.coordinatesystems.ICRS; -import org.deegree.cs.components.Axis; - /** * {@link GeometryValidationEvent} that indicates the orientation of an interior {@link Ring} of a {@link PolygonPatch}. * @@ -105,42 +102,6 @@ public int getRingIdx() { public boolean isClockwise() { return isClockwise; } - - /** - * Returns true if the geometry has a left handed CRS. - * - * @return true if geometry has a left handed CRS, false if CRS is right handed - */ - public boolean hasLeftHandedSrs() { - ICRS crs = patch.getInteriorRings().get( ringIdx ).getCoordinateSystem(); - - // get number of dimensions (it should be 2) - if ( crs.getDimension() == 2 ) { - int axis1 = crs.getAxis()[0].getOrientation(); - int axis2 = crs.getAxis()[1].getOrientation(); - - // check if CRS is left handed - if ( axis1 == Axis.AO_EAST || axis1 == Axis.AO_WEST ) { - if ( axis1 == Axis.AO_EAST && ( axis2 == Axis.AO_SOUTH || axis2 == Axis.AO_DOWN ) ) { - return true; - } - else if ( axis1 == Axis.AO_WEST && ( axis2 == Axis.AO_NORTH || axis2 == Axis.AO_UP ) ) { - return true; - } - } - else { - if ( ( axis1 == Axis.AO_SOUTH || axis1 == Axis.AO_DOWN ) && axis2 == Axis.AO_WEST ) { - return true; - } - else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_EAST ) { - return true; - } - } - } - - // return false in any other case - return false; - } /** * Returns true if the geometry is an interior boundary. @@ -150,7 +111,7 @@ else if ( ( axis1 == Axis.AO_NORTH || axis1 == Axis.AO_UP ) && axis2 == Axis.AO_ public boolean isInterior() { boolean isInterior = isClockwise; - if ( hasLeftHandedSrs() ) { + if ( isLeftHanded( patch.getInteriorRings().get( ringIdx ).getCoordinateSystem() ) ) { isInterior = !isInterior; }