/*
* The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
* for visualizing and manipulating spatial features with geometry and attributes.
*
* JUMP is Copyright (C) 2003 Vivid Solutions
*
* This program implements extensions to JUMP and is
* Copyright (C) 2007 Integrated Systems Analysts, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* For more information, contact:
*
* Integrated Systems Analysts, Inc.
* 630C Anchors St., Suite 101
* Fort Walton Beach, Florida
* USA
*
* (850)862-7321
*/package org.openjump.core.ui.plugin.layer;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JPopupMenu;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPoint;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.feature.Feature;
import com.vividsolutions.jump.feature.FeatureCollection;
import com.vividsolutions.jump.feature.FeatureDataset;
import com.vividsolutions.jump.feature.FeatureSchema;
import com.vividsolutions.jump.workbench.WorkbenchContext;
import com.vividsolutions.jump.workbench.model.Layer;
import com.vividsolutions.jump.workbench.model.LayerManager;
import com.vividsolutions.jump.workbench.model.StandardCategoryNames;
import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.ui.MenuNames;
import com.vividsolutions.jump.workbench.ui.images.IconLoader;
import com.vividsolutions.jump.workbench.ui.plugin.FeatureInstaller;
/**
* This plugin split a layer into several layers when its features have
* different geometry dimensions.
* It can produce a maximum of 4 layers
* <ul>
* <li>Empty geometries</li>
* <li>Punctual geometries</li>
* <li>Linear geometries</li>
* <li>Polygonal geometries</li>
* </ul>
* Rules followed to spread features into the 4 layers :
* <ul>
* <li>Empty GeometryCollection's are copied into empty-geometries layer</li>
* <li>Non-empty GeometryCollections are exploded into simple geometry features</li>
* <li>Empty simple features are copied into the layer corresponding to their dimension</li>
* <li>Non-empty simple features are copied into the layer corresponding to their dimension</li>
* </ul>
*/
public class ExtractLayersByGeometry extends AbstractPlugIn {
private final static String EXTRACT_LAYERS_BY_GEOMETRY_TYPE =
I18N.get("org.openjump.core.ui.plugin.layer.ExtractLayersByGeometry.Extract-Layers-by-Geometry-Type");
private final static String ONLY_ONE_GEOMETRY_TYPE_FOUND =
I18N.get("org.openjump.core.ui.plugin.layer.ExtractLayersByGeometry.Only-one-geometry-type-found");
private final static String EMPTY =
I18N.get("org.openjump.core.ui.plugin.layer.ExtractLayersByGeometry.empty");
private final static String POINT =
I18N.get("org.openjump.core.ui.plugin.layer.ExtractLayersByGeometry.point");
private final static String LINE =
I18N.get("org.openjump.core.ui.plugin.layer.ExtractLayersByGeometry.line");
private final static String AREA =
I18N.get("org.openjump.core.ui.plugin.layer.ExtractLayersByGeometry.area");
public ExtractLayersByGeometry() {
}
public void initialize(PlugInContext context) throws Exception {
WorkbenchContext workbenchContext = context.getWorkbenchContext();
FeatureInstaller featureInstaller = new FeatureInstaller(
workbenchContext);
/*
JPopupMenu layerNamePopupMenu = workbenchContext.getWorkbench()
.getFrame().getLayerNamePopupMenu();
featureInstaller.addPopupMenuItem(layerNamePopupMenu, this, getName(),
false, ICON, createEnableCheck(workbenchContext));
*/
//-- [sstein] this shouldn't be here, but as we try to use now the
// default-plugins.xml for configuration, we need to add the submenu init
// in the first loaded submenu function
featureInstaller.addMenuSeparator(MenuNames.EDIT);
FeatureInstaller.addMainMenu(featureInstaller, new String[] {
MenuNames.EDIT
}, MenuNames.EXTRACT, 14);
//--
context.getFeatureInstaller().addMainMenuItemWithJava14Fix(this,
new String[]
{MenuNames.EDIT, MenuNames.EXTRACT},
getName(),
false,
ICON,
createEnableCheck(context.getWorkbenchContext()));
}
public static MultiEnableCheck createEnableCheck(WorkbenchContext workbenchContext) {
EnableCheckFactory checkFactory = new EnableCheckFactory(workbenchContext);
return new MultiEnableCheck()
.add(checkFactory.createWindowWithSelectionManagerMustBeActiveCheck())
.add(checkFactory.createExactlyNLayersMustBeSelectedCheck(1));
}
public boolean execute(PlugInContext context) throws Exception {
Layer[] layers = context.getWorkbenchContext().getLayerNamePanel().getSelectedLayers();
if (layers.length > 0){
Layer layer = layers[0];
if (!compatibleFeatures(layer))
splitLayer(context, layer);
else
context.getWorkbenchFrame().warnUser(ONLY_ONE_GEOMETRY_TYPE_FOUND);
return true;
} else
return false;
}
public String getName() {
return EXTRACT_LAYERS_BY_GEOMETRY_TYPE;
}
public static final ImageIcon ICON = IconLoader.icon("extract.gif");
private List splitLayer(PlugInContext context, Layer layer)
{
ArrayList newLayers = new ArrayList();
ArrayList emptyFeatures = new ArrayList();
ArrayList pointFeatures = new ArrayList();
ArrayList lineFeatures = new ArrayList();
ArrayList polyFeatures = new ArrayList();
FeatureCollection featureCollection = layer.getFeatureCollectionWrapper();
List featureList = featureCollection.getFeatures();
FeatureSchema featureSchema = featureCollection.getFeatureSchema();
Collection selectedCategories = context.getLayerNamePanel().getSelectedCategories();
for (Iterator i = featureList.iterator(); i.hasNext();) {
Feature feature = (Feature) i.next();
Geometry geo = feature.getGeometry();
BitSet currFeatureBit = new BitSet();
currFeatureBit = setBit(currFeatureBit, geo);
if (geo instanceof GeometryCollection) {
explodeGeometryCollection(featureSchema, emptyFeatures, pointFeatures,
lineFeatures, polyFeatures, (GeometryCollection) geo, feature);
} else if (currFeatureBit.get(pointBit)) {
pointFeatures.add(feature.clone(true));
} else if (currFeatureBit.get(lineBit)) {
lineFeatures.add(feature.clone(true));
} else if (currFeatureBit.get(polyBit)) {
polyFeatures.add(feature.clone(true));
}
}
if (emptyFeatures.size() > 0) {
Layer emptyLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.RESULT
: selectedCategories.iterator().next().toString(), layer.getName() + "_" + EMPTY,
new FeatureDataset(featureSchema));
emptyLayer.setStyles(layer.cloneStyles());
FeatureCollection emptyFeatureCollection = emptyLayer.getFeatureCollectionWrapper();
newLayers.add(emptyLayer);
emptyFeatureCollection.addAll(emptyFeatures);
}
if (pointFeatures.size() > 0) {
Layer pointLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.RESULT
: selectedCategories.iterator().next().toString(), layer.getName() + "_" + POINT,
new FeatureDataset(featureSchema));
pointLayer.setStyles(layer.cloneStyles());
FeatureCollection pointFeatureCollection = pointLayer.getFeatureCollectionWrapper();
newLayers.add(pointLayer);
pointFeatureCollection.addAll(pointFeatures);
}
if (lineFeatures.size() > 0) {
Layer lineLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.RESULT
: selectedCategories.iterator().next().toString(), layer.getName() + "_" + LINE,
new FeatureDataset(featureSchema));
lineLayer.setStyles(layer.cloneStyles());
FeatureCollection lineFeatureCollection = lineLayer.getFeatureCollectionWrapper();
newLayers.add(lineLayer);
lineFeatureCollection.addAll(lineFeatures);
}
if (polyFeatures.size() > 0) {
Layer polyLayer = context.addLayer(selectedCategories.isEmpty()
? StandardCategoryNames.RESULT
: selectedCategories.iterator().next().toString(), layer.getName() + "_" + AREA,
new FeatureDataset(featureSchema));
polyLayer.setStyles(layer.cloneStyles());
FeatureCollection polyFeatureCollection = polyLayer.getFeatureCollectionWrapper();
newLayers.add(polyLayer);
polyFeatureCollection.addAll(polyFeatures);
}
context.getLayerViewPanel().repaint();
return newLayers;
}
static final int emptyBit = 0;
static final int pointBit = 1;
static final int lineBit = 2;
static final int polyBit = 3;
private void explodeGeometryCollection(FeatureSchema fs,
ArrayList emptyFeatures,
ArrayList pointFeatures,
ArrayList lineFeatures,
ArrayList polyFeatures,
GeometryCollection geometryCollection,
Feature feature) {
if (geometryCollection.isEmpty()) {
emptyFeatures.add(feature.clone(false));
}
else {
for (int i = 0; i < geometryCollection.getNumGeometries(); i++) {
Geometry geometry = geometryCollection.getGeometryN(i);
if (geometry instanceof GeometryCollection) {
explodeGeometryCollection(fs, emptyFeatures, pointFeatures, lineFeatures,
polyFeatures, (GeometryCollection)geometry, feature);
}
else {
Feature newFeature = feature.clone(false);
newFeature.setGeometry((Geometry) geometry.clone());
BitSet featureBit = new BitSet();
featureBit = setBit(featureBit, geometry);
if (featureBit.get(pointBit)) {
pointFeatures.add(newFeature);
} else if (featureBit.get(lineBit)) {
lineFeatures.add(newFeature);
} else if (featureBit.get(polyBit)) {
polyFeatures.add(newFeature);
}
}
}
}
}
private boolean compatibleFeatures(Layer layer) {
BitSet bitSet = new BitSet();
FeatureCollection featureCollection = layer.getFeatureCollectionWrapper();
List featureList = featureCollection.getFeatures();
for (Iterator i = featureList.iterator(); i.hasNext();) {
bitSet = setBit(bitSet, ((Feature) i.next()).getGeometry());
}
return (bitSet.cardinality() < 2);
}
private static BitSet setBit(BitSet bitSet, Geometry geometry) {
BitSet newBitSet = (BitSet) bitSet.clone();
if (geometry instanceof Point) newBitSet.set(pointBit);
else if (geometry instanceof MultiPoint) newBitSet.set(pointBit);
else if (geometry instanceof LineString) newBitSet.set(lineBit);
else if (geometry instanceof LinearRing) newBitSet.set(lineBit);
else if (geometry instanceof MultiLineString) newBitSet.set(lineBit);
else if (geometry instanceof Polygon) newBitSet.set(polyBit);
else if (geometry instanceof MultiPolygon) newBitSet.set(polyBit);
else if (geometry instanceof GeometryCollection) {
if (geometry.isEmpty()) newBitSet.set(emptyBit);
else {
GeometryCollection geometryCollection = (GeometryCollection) geometry;
for (int i = 0; i < geometryCollection.getNumGeometries(); i++) {
newBitSet = setBit(newBitSet, geometryCollection.getGeometryN(i));
}
}
}
return newBitSet;
}
}