// license Licence CeCILL http://www.cecill.info/
package org.openjump.core.ui.plugin.tools;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.feature.*;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jump.workbench.ui.GUIUtil;
import com.vividsolutions.jump.workbench.ui.GenericNames;
import com.vividsolutions.jump.workbench.ui.MenuNames;
import com.vividsolutions.jump.workbench.ui.MultiInputDialog;
import com.vividsolutions.jump.workbench.plugin.EnableCheckFactory;
import com.vividsolutions.jump.workbench.plugin.MultiEnableCheck;
import com.vividsolutions.jump.workbench.plugin.ThreadedBasePlugIn;
import com.vividsolutions.jump.task.TaskMonitor;
import com.vividsolutions.jump.tools.AttributeMapping;
import com.vividsolutions.jump.workbench.plugin.PlugInContext;
import com.vividsolutions.jump.workbench.model.Layer;
import com.vividsolutions.jump.workbench.model.StandardCategoryNames;
import com.vividsolutions.jump.feature.FeatureCollection;
/**
*
* This PlugIn can make spatial joins using different geometry predicates.
*
* @author ERWAN BOCHER Laboratoire RESO UMR CNRS 6590
* @see <a ref="http://www.projet-sigle.org">projet-sigle</a>
* @version 2006-02-20
*
*/
public class SpatialJoinPlugIn extends ThreadedBasePlugIn {
private final static String LAYER1 = GenericNames.LAYER_A;
private final static String LAYER2 = GenericNames.LAYER_B;
//-- reset in execute to correct language
private static String METHODS = I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.spatial-operation");
private static String METHOD_EQUAL = I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.equal");
private static String METHOD_WITHIN = "A " + I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.within") +" B";
private static String METHOD_EQUAL_AND_WITHIN = "A " + I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.equal-AND-within" +" B");
private static String METHOD_EQUAL_OR_WITHIN = "A " + I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.equal-OR-within" +" B");
private static Collection getSpatialJoinMethodNames()
{
Collection names = new ArrayList();
names.add(METHOD_EQUAL);
names.add(METHOD_WITHIN);
names.add(METHOD_EQUAL_AND_WITHIN);
names.add(METHOD_EQUAL_OR_WITHIN);
return names;
}
private Collection SpatialJoinMethodNames;
private MultiInputDialog dialog;
private Layer layer1, layer2;
private String methodNameToRun;
private boolean exceptionThrown = false;
/**
* Sets geomentryMethodNames variable using getGeometryMethodNames function.
*/
public SpatialJoinPlugIn()
{
SpatialJoinMethodNames = getSpatialJoinMethodNames();
}
public void initialize(PlugInContext context) throws Exception {
context.getFeatureInstaller().addMainMenuItem(this,new String[] { MenuNames.TOOLS, MenuNames.TOOLS_EDIT_ATTRIBUTES},
this.getName(), false, null,
new MultiEnableCheck().add(new EnableCheckFactory(context.getWorkbenchContext()).createTaskWindowMustBeActiveCheck())
.add(new EnableCheckFactory(context.getWorkbenchContext()).createAtLeastNLayersMustExistCheck(2))
);
}
public boolean execute(PlugInContext context) throws Exception {
METHODS = I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.spatial-operation");
METHOD_EQUAL = I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.equal");
METHOD_WITHIN = "A " + I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.within" +" B");
METHOD_EQUAL_AND_WITHIN = "A " + I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.equal-AND-within" +" B");
METHOD_EQUAL_OR_WITHIN = "A " + I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.equal-OR-within" +" B");
MultiInputDialog dialog = new MultiInputDialog(
context.getWorkbenchFrame(), getName(), true);
setDialogValues(dialog, context);
GUIUtil.centreOnWindow(dialog);
dialog.setVisible(true);
if (! dialog.wasOKPressed()) { return false; }
getDialogValues(dialog);
return true;
}
public String getName(){
return I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.Transfer-Attributes");
}
public void run(TaskMonitor monitor, PlugInContext context)
throws Exception
{
FeatureSchema featureSchema = new FeatureSchema();
FeatureCollection resultColl = runSpatialJoinMethod(layer1.getFeatureCollectionWrapper(),
layer2.getFeatureCollectionWrapper(),
methodNameToRun);
if (resultColl.size()>0)
context.addLayer(StandardCategoryNames.WORKING, I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.Result") + methodNameToRun, resultColl);
if (exceptionThrown)
context.getWorkbenchFrame().warnUser(I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.Error-while-executing-spatial-function"));
}
private FeatureCollection runSpatialJoinMethod(FeatureCollection fcA,
FeatureCollection fcB,
String methodName
)
{
exceptionThrown = false;
FeatureCollection resultFC;
Feature fEqual = null;
Feature fWithin = null;
Feature fEqualAndWithin = null;
Feature fEqualOrWithin = null;
AttributeMapping mapping = null;
mapping = new AttributeMapping(new FeatureSchema(), new FeatureSchema());
List aFeatures = null;
mapping = new AttributeMapping(fcB.getFeatureSchema(), fcA.getFeatureSchema());
aFeatures = fcA.getFeatures();
FeatureDataset fcRecup = new FeatureDataset(mapping.createSchema("GEOMETRY"));
IndexedFeatureCollection indexedB = new IndexedFeatureCollection(fcB);
for (int i = 0; (i < aFeatures.size());i++) {
Feature aFeature = (Feature) aFeatures.get(i);
Feature feature = new BasicFeature(fcRecup.getFeatureSchema());
int nbFeatureEqual = 0;
int nbFeatureWithin = 0;
int nbFeatureEqualAndWithin = 0;
int nbFeatureEqualOrWithin=0;
int nbFeature =0;
for (Iterator j = indexedB.query(aFeature.getGeometry().getEnvelopeInternal()).iterator();
j.hasNext();) {
Feature bFeature = (Feature) j.next();
if (methodName.equals(METHOD_EQUAL)) {
if (aFeature.getGeometry().equals(bFeature.getGeometry())) {
nbFeatureEqual++;
nbFeature++;
fEqual = bFeature;
}
}
else if (methodName.equals(METHOD_WITHIN)) {
if (aFeature.getGeometry().within(bFeature.getGeometry())) {
nbFeatureWithin++;
nbFeature++;
fWithin = bFeature;
}
}
else if (methodName.equals(METHOD_EQUAL_AND_WITHIN)) {
if ((aFeature.getGeometry().equals(bFeature.getGeometry()))&& ((aFeature.getGeometry().within(bFeature.getGeometry())))) {
nbFeatureEqualAndWithin++;
nbFeature++;
fEqualAndWithin = bFeature;
}
}
else if (methodName.equals(METHOD_EQUAL_OR_WITHIN)) {
if ((aFeature.getGeometry().equals(bFeature.getGeometry()))|| ((aFeature.getGeometry().within(bFeature.getGeometry())))) {
nbFeatureEqualOrWithin++;
nbFeature++;
fEqualOrWithin = bFeature;
}
}
}
// on ne transfere les attributs que lorsque la geometry resultat
// n'est contenue que une seule geometry source
if (nbFeatureEqual == 1) {
mapping.transferAttributes(fEqual, aFeature, feature);
feature.setGeometry((Geometry) aFeature.getGeometry().clone());
fcRecup.add(feature);
}
else if (nbFeatureWithin == 1){
mapping.transferAttributes(fWithin, aFeature, feature);
feature.setGeometry((Geometry) aFeature.getGeometry().clone());
fcRecup.add(feature);
}
else if (nbFeatureEqualAndWithin == 1){
mapping.transferAttributes(fEqualAndWithin, aFeature, feature);
feature.setGeometry((Geometry) aFeature.getGeometry().clone());
fcRecup.add(feature);
}
else if (nbFeatureEqualOrWithin == 1){
mapping.transferAttributes(fEqualOrWithin, aFeature, feature);
feature.setGeometry((Geometry) aFeature.getGeometry().clone());
fcRecup.add(feature);
}
// on clone la geometry pour que les modifs sur la geometry source
// ne soient pas transferees sur la geometry resultat
//feature.setGeometry((Geometry) aFeature.getGeometry().clone());
// fcRecup.add(feature);
}
return fcRecup;
}
private void setDialogValues(MultiInputDialog dialog, PlugInContext context)
{
//dialog.setSideBarImage(new ImageIcon(getClass().getResource("DiffSegments.png")));
dialog.setSideBarDescription(I18N.get("org.openjump.sigle.plugin.SpatialJoinPlugIn.Transfers-the-attributes-of-Layer-B-to-Layer-A-using-a-spatial-criterion"));
//Set initial layer values to the first and second layers in the layer list.
//In #initialize we've already checked that the number of layers >= 2. [Jon Aquino]
dialog.addLayerComboBox(LAYER1, layer1, context.getLayerManager());
dialog.addLayerComboBox(LAYER2, layer2, context.getLayerManager());
dialog.addComboBox(METHODS, methodNameToRun, SpatialJoinMethodNames, null);
}
private void getDialogValues(MultiInputDialog dialog) {
layer1 = dialog.getLayer(LAYER1);
layer2 = dialog.getLayer(LAYER2);
methodNameToRun = dialog.getText(METHODS);
}
}