/* * Copyright (c) 2016 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.util.geometry; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.concurrent.TimeUnit; import org.geotools.referencing.CRS; import org.junit.BeforeClass; import org.junit.Test; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; /** * TODO Type description * * @author Arun */ public class WindingOrderTest { private static Polygon clockWise1, clockWise2, clockWise2WOHoles; private static MultiPolygon clockWise3; private static GeometryCollection clockWise4; private static LinearRing r1, r2, h1, h2; private static final String code1 = "EPSG:4026"; private static final String code2 = "EPSG:25832"; private static CoordinateReferenceSystem crs1, crs2; private static final LoadingCache<String, CoordinateReferenceSystem> CRS_CACHE = CacheBuilder .newBuilder().maximumSize(100).expireAfterAccess(1, TimeUnit.HOURS) .build(new CacheLoader<String, CoordinateReferenceSystem>() { @Override public CoordinateReferenceSystem load(String code) throws Exception { return CRS.decode(code); } }); /** * Setup for different tests */ @BeforeClass public static void setUp() { GeometryFactory factory = new GeometryFactory(); r1 = factory.createLinearRing(new Coordinate[] { new Coordinate(10, 30), new Coordinate(20, 0), new Coordinate(0, 0), new Coordinate(10, 30) }); r2 = factory.createLinearRing(new Coordinate[] { new Coordinate(49.87445, 8.64729), new Coordinate(49.87582, 8.65441), new Coordinate(49.87095, 8.65694), new Coordinate(49.86978, 8.65032), new Coordinate(49.87197, 8.64758), new Coordinate(49.87341, 8.64688), new Coordinate(49.87445, 8.64729) }); h1 = factory.createLinearRing(new Coordinate[] { new Coordinate(49.87327, 8.64991), new Coordinate(49.8735, 8.6521), new Coordinate(49.87253, 8.65239), new Coordinate(49.8723, 8.65045), new Coordinate(49.87327, 8.64991) }); h2 = factory.createLinearRing(new Coordinate[] { new Coordinate(49.87203, 8.65208), new Coordinate(49.87209, 8.6531), new Coordinate(49.87156, 8.65312), new Coordinate(49.87145, 8.65227), new Coordinate(49.87203, 8.65208) }); clockWise1 = factory.createPolygon(r1); clockWise2 = factory.createPolygon(r2, new LinearRing[] { h1, h2 }); clockWise2WOHoles = factory.createPolygon(r2); clockWise3 = factory.createMultiPolygon(new Polygon[] { clockWise1, clockWise2 }); clockWise4 = factory.createGeometryCollection( new Geometry[] { clockWise2, clockWise2WOHoles, clockWise3, r2 }); if (crs1 == null) { try { crs1 = CRS_CACHE.get(code1); } catch (Exception e) { throw new IllegalStateException("Invalid CRS code", e); } } if (crs2 == null) { try { crs2 = CRS_CACHE.get(code2); } catch (Exception e) { throw new IllegalStateException("Invalid CRS code", e); } } } /** * Test of Flip state of CRS */ @Test public void testCRSFlipped() { // Flipped CRS assertTrue(WindingOrder.isCRSFlip(crs1)); // Normal CRS assertFalse(WindingOrder.isCRSFlip(crs2)); } /** * test geometry on normal CRS */ @Test public void testGeometryNormalOnCRS() { assertTrue(WindingOrder.isCounterClockwise(clockWise2.getExteriorRing())); assertFalse(WindingOrder.isCRSFlip(crs2)); Geometry result = WindingOrder.unifyWindingOrder(clockWise2, true, crs2); assertTrue(result instanceof Polygon); assertFalse(clockWise2.equalsExact(result)); assertTrue(WindingOrder.isCounterClockwise(((Polygon) result).getExteriorRing())); } /** * test geometry on Flipped CRS */ @Test public void testGeometryFlippedOnCRS() { assertTrue(WindingOrder.isCounterClockwise(clockWise2.getExteriorRing())); assertTrue(WindingOrder.isCRSFlip(crs1)); Geometry result = WindingOrder.unifyWindingOrder(clockWise2, true, crs1); assertTrue(result instanceof Polygon); assertFalse(clockWise2.equalsExact(result)); assertFalse(WindingOrder.isCounterClockwise(((Polygon) result).getExteriorRing())); } /** * test geometry flip on giving null CRS */ @Test public void testGeometryFlippedOnNULLCRS() { assertTrue(WindingOrder.isCounterClockwise(clockWise2.getExteriorRing())); Geometry result = WindingOrder.unifyWindingOrder(clockWise2, true, null); assertTrue(result instanceof Polygon); assertTrue(WindingOrder.isCounterClockwise(((Polygon) result).getExteriorRing())); } /** * Testing of Polygon without holes. */ @Test public void testUnifyWOHoles() { Geometry result = WindingOrder.unifyWindingOrder(clockWise2WOHoles, true, null); assertTrue(result instanceof Polygon); assertTrue(clockWise2WOHoles.equalsExact(result)); } /** * Test of holes of Polygon as Counter ClockWise */ @Test public void testOrderHolesCCW() { assertTrue(WindingOrder.isCounterClockwise(h1)); assertTrue(WindingOrder.isCounterClockwise(h2)); } /** * Test of winding order of hole which is already counter clockwise */ @Test public void testUnifyHoles() { assertTrue(WindingOrder.isCounterClockwise(h1)); Geometry result = WindingOrder.unifyWindingOrder(h1, true, null); assertTrue(WindingOrder.isCounterClockwise(result)); assertTrue(h1.equalsExact(result)); } /** * Test of winding order for an empty geometry. */ @Test public void testUnifyEmpty() { GeometryFactory fact = new GeometryFactory(); Polygon geom = fact.createPolygon(new Coordinate[0]); Geometry result = WindingOrder.unifyWindingOrder(geom, true, null); assertTrue(geom.equalsExact(result)); } /** * Test winding order of polygon as clockwise */ @Test public void testOrderClockwise() { assertFalse(WindingOrder.isCounterClockwise(clockWise1.getExteriorRing())); } /** * Test winding order of polygon as counter clockwise */ @Test public void testOrderCounterClockwise() { assertTrue(WindingOrder.isCounterClockwise(clockWise2.getExteriorRing())); } /** * Test winding order of simple polygon as counter clockwise */ @Test public void testUnifyCCWSimple() { Geometry result = WindingOrder.unifyWindingOrder(clockWise1, true, null); assertTrue(result instanceof Polygon); assertFalse(clockWise1.equalsExact(result)); assertTrue(WindingOrder.isCounterClockwise(((Polygon) result).getExteriorRing())); } /** * Test winding order of polygon with holes as counter clockwise * */ @Test public void testUnifyCCWWithHoles() { Geometry result = WindingOrder.unifyWindingOrder(clockWise2, true, null); assertTrue(result instanceof Polygon); assertFalse(clockWise2.equalsExact(result)); assertTrue(WindingOrder.isCounterClockwise(((Polygon) result).getExteriorRing())); assertFalse(WindingOrder.isCounterClockwise(((Polygon) result).getInteriorRingN(0))); assertTrue(WindingOrder.isCounterClockwise(clockWise2.getInteriorRingN(0)) != WindingOrder .isCounterClockwise(((Polygon) result).getInteriorRingN(0))); assertFalse( clockWise2.getInteriorRingN(0).equalsExact(((Polygon) result).getInteriorRingN(0))); } /** * Test winding order of MultiPolygon */ @Test public void testUnifyMultiPolygon() { Geometry result = WindingOrder.unifyWindingOrder(clockWise3, false, null); assertTrue(result instanceof MultiPolygon); assertFalse(clockWise3.equalsExact(result)); } /** * Test winding order of GeometryCollection */ @Test public void testUnifyGeometryCollection() { Geometry result = WindingOrder.unifyWindingOrder(clockWise4, true, null); assertTrue(result instanceof GeometryCollection); assertFalse(clockWise4.equalsExact(result)); assertTrue( ((GeometryCollection) result).getNumGeometries() == clockWise4.getNumGeometries()); } }