/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package de.cismet.cismap.actions;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
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.jts.geom.util.LineStringExtracter;
import com.vividsolutions.jts.operation.polygonize.Polygonizer;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import de.cismet.cismap.commons.features.CommonFeatureAction;
import de.cismet.cismap.commons.features.Feature;
import de.cismet.cismap.commons.features.PureNewFeature;
import de.cismet.cismap.commons.interaction.CismapBroker;
/**
* DOCUMENT ME!
*
* @author thorsten
* @version $Revision$, $Date$
*/
@ServiceProvider(service = CommonFeatureAction.class)
public class SplitFeatureAction extends AbstractAction implements CommonFeatureAction {
//~ Static fields/initializers ---------------------------------------------
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(SplitFeatureAction.class);
//~ Instance fields --------------------------------------------------------
Feature currentFeature = null;
//~ Constructors -----------------------------------------------------------
/**
* Creates a new DuplicateGeometryFeatureAction object.
*/
public SplitFeatureAction() {
super(NbBundle.getMessage(
SplitFeatureAction.class,
"SplitFeatureAction.SplitFeatureAction()"));
super.putValue(
Action.SMALL_ICON,
new javax.swing.ImageIcon(getClass().getResource("/de/cismet/cismap/actions/arrow-split.png")));
}
//~ Methods ----------------------------------------------------------------
@Override
public int getSorter() {
return 1;
}
@Override
public Feature getSourceFeature() {
return currentFeature;
}
@Override
public boolean isActive() {
return ((currentFeature instanceof PureNewFeature) && (currentFeature.getGeometry() instanceof Polygon)
&& (getIntersectingLineFeatureIfUnambigous(currentFeature) != null));
}
@Override
public void setSourceFeature(final Feature source) {
currentFeature = source;
}
/**
* DOCUMENT ME!
*
* @param geometry DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public static Geometry polygonize(final Geometry geometry) {
final List lines = LineStringExtracter.getLines(geometry);
final Polygonizer polygonizer = new Polygonizer();
polygonizer.add(lines);
final Collection polys = polygonizer.getPolygons();
final Polygon[] polyArray = GeometryFactory.toPolygonArray(polys);
return geometry.getFactory().createGeometryCollection(polyArray);
}
/**
* DOCUMENT ME!
*
* @param poly DOCUMENT ME!
* @param line DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public static Geometry splitPolygon(final Geometry poly, final Geometry line) {
final Geometry nodedLinework = poly.getBoundary().union(line);
final Geometry polys = polygonize(nodedLinework);
// Only keep polygons which are inside the input
final List output = new ArrayList();
for (int i = 0; i < polys.getNumGeometries(); i++) {
final Polygon candpoly = (Polygon)polys.getGeometryN(i);
if (poly.contains(candpoly.getInteriorPoint())) {
output.add(candpoly);
}
}
return poly.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(output));
}
/**
* DOCUMENT ME!
*
* @param polygonfeature DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private Feature getIntersectingLineFeatureIfUnambigous(final Feature polygonfeature) {
Feature lineFeature = null;
for (final Feature f : CismapBroker.getInstance().getMappingComponent().getFeatureCollection().getAllFeatures()) {
if ((f != polygonfeature) && (f.getGeometry() instanceof LineString)
&& polygonfeature.getGeometry().intersects(f.getGeometry())) {
if (lineFeature == null) {
lineFeature = f;
} else {
return null;
}
}
}
return lineFeature;
}
@Override
public void actionPerformed(final ActionEvent e) {
de.cismet.tools.CismetThreadPool.execute(new javax.swing.SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
Thread.currentThread().setName("SplitGeometryFeatureAction");
final Feature lineFeature = getIntersectingLineFeatureIfUnambigous(currentFeature);
final Geometry splitResult = splitPolygon(currentFeature.getGeometry(), lineFeature.getGeometry());
if (splitResult instanceof GeometryCollection) {
for (int i = 0; i < ((GeometryCollection)splitResult).getNumGeometries(); i++) {
final Geometry geom = ((GeometryCollection)splitResult).getGeometryN(i);
// the geometry should be cloned, because different polygons can use the same coordinate
// object and this can lead to problems, if the polygons will be moved on the map.
final PureNewFeature pnf = new PureNewFeature((Geometry)geom.clone());
if ((geom instanceof LineString) || (geom instanceof MultiLineString)) {
pnf.setGeometryType(PureNewFeature.geomTypes.LINESTRING);
} else if (geom instanceof Polygon) {
pnf.setGeometryType(PureNewFeature.geomTypes.POLYGON);
} else if (geom instanceof MultiPolygon) {
pnf.setGeometryType(PureNewFeature.geomTypes.MULTIPOLYGON);
} else if ((geom instanceof Point) || (geom instanceof MultiPoint)) {
pnf.setGeometryType(PureNewFeature.geomTypes.POINT);
} else {
pnf.setGeometryType(PureNewFeature.geomTypes.UNKNOWN);
}
pnf.setEditable(true);
CismapBroker.getInstance().getMappingComponent().getFeatureCollection().addFeature(pnf);
CismapBroker.getInstance().getMappingComponent().getFeatureCollection().holdFeature(pnf);
}
CismapBroker.getInstance()
.getMappingComponent()
.getFeatureCollection()
.removeFeature(lineFeature);
CismapBroker.getInstance()
.getMappingComponent()
.getFeatureCollection()
.removeFeature(currentFeature);
}
return null;
}
@Override
protected void done() {
try {
get();
} catch (Exception e) {
LOG.error("Error while splitting geometries.", e);
final ErrorInfo errorInfo = new ErrorInfo(
NbBundle.getMessage(
SplitFeatureAction.class,
"SplitFeatureAction.actionPerformed().done().title"),
NbBundle.getMessage(
SplitFeatureAction.class,
"SplitFeatureAction.actionPerformed().done().message"),
null,
null,
e,
Level.ALL,
null);
JXErrorPane.showDialog(CismapBroker.getInstance().getMappingComponent(), errorInfo);
}
}
});
}
/**
* DOCUMENT ME!
*
* @param args DOCUMENT ME!
*/
public static void main(final String[] args) {
final WaitDialog w = new WaitDialog();
w.setVisible(true);
}
}
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
//class WaitDialog extends JDialog {
//
// //~ Constructors -----------------------------------------------------------
//
// /**
// * Creates a new WaitDialog object.
// */
// public WaitDialog() {
// super(StaticSwingTools.getParentFrame(CismapBroker.getInstance().getMappingComponent()), true);
// setLayout(new FlowLayout());
// getContentPane().add(new JLabel(
// new javax.swing.ImageIcon(
// getClass().getResource("/de/cismet/cismap/actions/raiseProgress.png"))));
// final JProgressBar prb = new JProgressBar();
// prb.setForeground(new Color(51, 153, 204));
// prb.setBorderPainted(false);
// prb.setIndeterminate(true);
// getContentPane().add(prb);
// setUndecorated(true);
// final JComponent c = CismapBroker.getInstance().getMappingComponent();
// pack();
// setLocationRelativeTo(c);
// }
//}
//
//}