/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.geofence.services.rest.utils;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
import jaitools.jts.Utils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
*
* @author ETj (etj at geo-solutions.it)
*/
public class MultiPolygonUtils
{
private static final Logger LOGGER = LogManager.getLogger(MultiPolygonUtils.class);
/**
* Simplifies a MultiPolygon.
* <BR/><BR/>
* Simplification is performed by first removing collinear points, then
* by applying DouglasPeucker simplification.
* <BR/>Order <B>is</B> important, since it's more likely to have collinear
* points before applying any other simplification.
*/
public static MultiPolygon simplifyMultiPolygon(final MultiPolygon mp)
{
final Polygon[] simpPolys = new Polygon[mp.getNumGeometries()];
for (int i = 0; i < mp.getNumGeometries(); i++)
{
Polygon p = (Polygon) mp.getGeometryN(i);
Polygon s1 = Utils.removeCollinearVertices(p);
TopologyPreservingSimplifier tps = new TopologyPreservingSimplifier(s1);
Polygon s2 = (Polygon) tps.getResultGeometry();
simpPolys[i] = s2;
if (LOGGER.isInfoEnabled())
{
LOGGER.info("RCV: simplified poly " + getPoints(p) +
" --> " + getPoints(s1) +
" --> " + getPoints(s2));
}
}
// reuse existing factory
final GeometryFactory gf = mp.getFactory();
return gf.createMultiPolygon(simpPolys);
}
/**
* Return the number of points of a polygon in the format
* E+I0+I1+...+In
* where E is the number of points of the exterior ring and I0..In are
* the number of points of the Internal rings.
*/
public static String getPoints(final Polygon p)
{
final StringBuilder sb = new StringBuilder();
sb.append(p.getExteriorRing().getNumPoints());
for (int i = 0; i < p.getNumInteriorRing(); i++)
{
LineString ir = p.getInteriorRingN(i);
sb.append('+').append(ir.getNumPoints());
}
return sb.toString();
}
}