eu.europa.ec.eurostat.jgiscotools.algo.base.Union Maven / Gradle / Ivy
package eu.europa.ec.eurostat.jgiscotools.algo.base;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.MultiLineString;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.operation.linemerge.LineMerger;
import org.locationtech.jts.operation.union.CascadedPolygonUnion;
/**
* Efficient union of polygons.
*
* @author julien Perret (from GeOxygene project http://sourceforge.net/projects/oxygene-project/)
*
*/
public class Union {
private final static Logger LOGGER = LogManager.getLogger(Union.class.getName());
public static Geometry getLineUnion(Collection geoms) {
return getLine( union_(geoms) );
}
public static Geometry getPolygonUnion(Collection geoms) {
return getPolygon( union_(geoms) );
}
private static ArrayList union_(Collection geoms) {
ArrayList geoms_ = new ArrayList();
geoms_.addAll(geoms);
final int cellSize = 1 + (int)Math.sqrt(geoms_.size());
Comparator comparator = new Comparator(){
public int compare(Geometry geom1, Geometry geom2) {
if (geom1==null || geom2==null) return 0;
Envelope env1 = geom1.getEnvelopeInternal();
Envelope env2 = geom2.getEnvelopeInternal();
double i1 = env1.getMinX() / cellSize + cellSize*( (int)env1.getMinY() / cellSize );
double i2 = env2.getMinX() / cellSize + cellSize*( (int)env2.getMinY() / cellSize );
return i1>=i2? 1 : i1 treeSet;
while (geoms_.size() > 1) {
i++;
if(LOGGER.isTraceEnabled()) LOGGER.trace("Union (" + (i-1) + "/" + nb + ")");
//System.out.println( "Union (" + (i-1) + "/" + nb + ")" );
treeSet = new TreeSet(comparator);
treeSet.addAll(geoms_);
geoms_ = union(treeSet, 4);
}
return geoms_;
}
private static ArrayList union(TreeSet treeSet, int groupSize) {
ArrayList unions = new ArrayList();
Geometry union = null;
int i=0;
for (Geometry geom : treeSet) {
if ((union==null)||(i%groupSize==0)) union = geom;
else {
union = union.union(geom);
if (groupSize-i%groupSize==1) unions.add(union);
}
i++;
if(LOGGER.isTraceEnabled()) LOGGER.trace(" " + i + " - " + treeSet.size() + " geometries");
}
if (groupSize-i%groupSize!=0) unions.add(union);
return unions;
}
private static Geometry getPolygon(ArrayList geoms_) {
List polys = new ArrayList();
for (Geometry geom : geoms_) {
if (geom instanceof Polygon) polys.add((Polygon) geom);
else if (geom instanceof MultiPolygon) {
MultiPolygon mp = (MultiPolygon) geom;
for (int k=0; k geoms_) {
List ls = new ArrayList();
for (Geometry geom : geoms_) {
if (geom instanceof LineString) ls.add((LineString) geom);
else if (geom instanceof MultiLineString) {
MultiLineString mls = (MultiLineString) geom;
for (int k=0; k polys){
CascadedPolygonUnion cpu = new CascadedPolygonUnion(polys);
return cpu.union();
}
public static LineString getUnionAsLineString(Collection geoms) {
LineMerger lm = new LineMerger();
lm.add(geoms);
Collection> ls = lm.getMergedLineStrings();
if(ls.size()!=1)
LOGGER.warn("Problem when merging lines into a single LineString: Unexpected number of lines: " + ls.size() + " Around: "+((LineString)ls.iterator().next()).getCoordinate());
return (LineString)ls.iterator().next();
}
public static Geometry polygonsUnionAll(Collection polys) {
Geometry union = null;
try {
if(LOGGER.isTraceEnabled()) LOGGER.trace("Try union with CascadedPolygonUnion");
union = CascadedPolygonUnion.union(polys);
} catch (Exception e) {
try {
if(LOGGER.isTraceEnabled()) LOGGER.trace("Try union with PolygonUnion");
union = Union.getPolygonUnion(polys);
} catch (Exception e1) {
try {
if(LOGGER.isTraceEnabled()) LOGGER.trace("Try buffer(0)");
GeometryCollection gc = new GeometryFactory().createGeometryCollection(polys.toArray(new Geometry[polys.size()]));
union = gc.buffer(0);
} catch (Exception e2) {
if(LOGGER.isTraceEnabled()) LOGGER.trace("Try iterative union");
for(Geometry poly : polys)
union = union==null? poly : union.union(poly);
}
}
}
return union;
}
}