Last active
November 30, 2015 19:27
-
-
Save dbaston/6b32fcb8c70d4d58775b to your computer and use it in GitHub Desktop.
ParallelCascadedPolygonUnion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.vividsolutions.jts.geom.Geometry; | |
import com.vividsolutions.jts.geom.util.GeometryCombiner; | |
import com.vividsolutions.jts.index.strtree.STRtree; | |
import java.util.Collection; | |
import java.util.List; | |
import java.util.stream.Collectors; | |
public class ParallelCascadedPolygonUnion { | |
public static Geometry union(Collection<Geometry> geoms) { | |
// Construct an STRtree from the input geometries. If the number of geometries is | |
// small, we should probably skip this step or at least adjust the nodeCapacity. | |
int nodeCapacity = 16; | |
STRtree index = new STRtree(nodeCapacity); | |
geoms.forEach(g-> index.insert(g.getEnvelopeInternal(), g)); | |
index.build(); | |
// Pull out the internal representation of the tree (a list of lists) | |
// and perform the union operation. | |
return performUnion(index.itemsTree()); | |
} | |
private static Geometry unionTwoGeometries(Geometry g1, Geometry g2) { | |
// This handles our base case when this function is used in a | |
// stream::reduce context. | |
if (g1 == null) { | |
return g2; | |
} | |
// Avoid doing the union if the geometries cannot intersect. | |
if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) { | |
return GeometryCombiner.combine(g1, g2); | |
} | |
return g2.union(g1); | |
} | |
@SuppressWarnings("unchecked") | |
private static Geometry performUnion(List items) { | |
boolean isLeafNode = items.iterator().next() instanceof Geometry; | |
// If we're not on a leaf node, first perform the union operation in parallel on the child nodes. This will | |
// transform the current node into a leaf node of a shallower tree. | |
if (!isLeafNode) | |
items = ((List<List>) items).parallelStream().map(ParallelCascadedPolygonUnion::performUnion).collect(Collectors.toList()); | |
// Now, union the geometry stored in the child nodes | |
return ((List<Geometry>) items).parallelStream().reduce(null, ParallelCascadedPolygonUnion::unionTwoGeometries); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment