/*************************************************** * * cismet GmbH, Saarbruecken, Germany * * ... and it just works. * ****************************************************/ package de.cismet.cismap.commons.features; import com.vividsolutions.jts.geom.*; import java.util.Arrays; import java.util.Collection; import de.cismet.tools.collections.TypeSafeCollections; /** * DOCUMENT ME! * * @author srichter * @version $Revision$, $Date$ */ public final class FeatureGroups { //~ Static fields/initializers --------------------------------------------- private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(FeatureGroups.class); public static final boolean SHOW_GROUPING_ENABLED = false; public static final boolean SHOW_GROUPS_AS_ENVELOPES = false; //~ Constructors ----------------------------------------------------------- /** * Creates a new FeatureGroups object. * * @throws AssertionError DOCUMENT ME! */ private FeatureGroups() { throw new AssertionError(); } //~ Methods ---------------------------------------------------------------- /** * DOCUMENT ME! * * @param fg DOCUMENT ME! * * @return DOCUMENT ME! */ public static boolean hasSubFeatures(final FeatureGroup fg) { final Collection<? extends Feature> subFeatures = fg.getFeatures(); if ((subFeatures == null) || (subFeatures.size() == 0)) { return false; } else { return true; } } /** * DOCUMENT ME! * * @param featureGroup DOCUMENT ME! * @param includeGroups DOCUMENT ME! * * @return DOCUMENT ME! */ public static Collection<? extends Feature> expand(final FeatureGroup featureGroup, final boolean includeGroups) { final Collection<Feature> result = TypeSafeCollections.newArrayList(); final Collection<? extends Feature> subFeatures = featureGroup.getFeatures(); if (subFeatures != null) { for (final Feature f : featureGroup) { if (f instanceof FeatureGroup) { result.addAll(expand((FeatureGroup)f, includeGroups)); } else { result.add(f); } } } if (includeGroups || (result.size() == 0)) { result.add(featureGroup); } return result; } /** * DOCUMENT ME! * * @param fg DOCUMENT ME! * * @return DOCUMENT ME! */ public static Collection<? extends Feature> expandAll(final FeatureGroup fg) { return expand(fg, true); } /** * DOCUMENT ME! * * @param fg DOCUMENT ME! * * @return DOCUMENT ME! */ public static Collection<? extends Feature> expandToLeafs(final FeatureGroup fg) { return expand(fg, false); } /** * DOCUMENT ME! * * @param group DOCUMENT ME! * * @return DOCUMENT ME! */ public static Geometry getEnclosingGeometry(final FeatureGroup group) { return getEnclosingGeometry(group.getFeatures()); } /** * DOCUMENT ME! * * @param featureCollection DOCUMENT ME! * * @return DOCUMENT ME! */ public static Geometry getEnclosingGeometry(final Collection<? extends Feature> featureCollection) { boolean hasLinestringOrPoints = false; Geometry union = null; final Geometry[] array = new Geometry[featureCollection.size()]; int i = 0; try { for (final Feature f : featureCollection) { final Geometry newGeom = f.getGeometry(); if (!hasLinestringOrPoints && !((newGeom instanceof Polygon) || (newGeom instanceof MultiPolygon))) { hasLinestringOrPoints = true; } if (newGeom != null) { if (FeatureGroups.SHOW_GROUPS_AS_ENVELOPES) { array[i++] = newGeom.getEnvelope(); } else { array[i++] = newGeom; } } } int srid = 0; if (array.length > 0) { srid = array[0].getSRID(); } final GeometryFactory factory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), srid); if (!hasLinestringOrPoints) { // The following two lines are more efficient then the union method. // See http://www.vividsolutions.com/JTS/bin/JTS%20Developer%20Guide.pdf // But buffer(0) handles LineStrings and Points as empty polygons, so it can only be used, // if only polygons should be unioned. final GeometryCollection collection = factory.createGeometryCollection(array); union = collection.buffer(0); } else { union = factory.buildGeometry(Arrays.asList(array)); if (union instanceof GeometryCollection) { union = ((GeometryCollection)union).union(); } } return union; } catch (Exception e) { log.error("Error during creation of enclosing geom", e); } return null; } /** * DOCUMENT ME! * * @param hierarchyMember DOCUMENT ME! * * @return DOCUMENT ME! */ public static FeatureGroup getRootFeature(FeatureGroup hierarchyMember) { while (hierarchyMember.getParentFeature() != null) { hierarchyMember = hierarchyMember.getParentFeature(); } return hierarchyMember; } /** * DOCUMENT ME! * * @param hierarchyMember DOCUMENT ME! * * @return DOCUMENT ME! */ public static Feature getRootFeature(SubFeature hierarchyMember) { while (hierarchyMember.getParentFeature() != null) { hierarchyMember = hierarchyMember.getParentFeature(); } return hierarchyMember; } }