/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2011, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.gui.swing.render2d.control.edition;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.simplify.DouglasPeuckerSimplifier;
import com.vividsolutions.jts.simplify.TopologyPreservingSimplifier;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.sis.feature.FeatureExt;
import org.geotoolkit.geometry.jts.JTSMapping;
import org.geotoolkit.geometry.jts.JTS;
import org.geotoolkit.gui.swing.render2d.JMap2D;
import org.geotoolkit.gui.swing.resource.MessageBundle;
import org.apache.sis.referencing.CRS;
import org.apache.sis.util.logging.Logging;
import org.opengis.feature.AttributeType;
import org.opengis.feature.Feature;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
/**
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class JSimplificationPanel extends javax.swing.JPanel {
private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.gui.swing.render2d.control.edition");
public static final String GEOMETRY_PROPERTY = "geometry";
private JMap2D map;
private Feature original = null;
private Geometry current = null;
public JSimplificationPanel(final JMap2D map) {
this.map = map;
initComponents();
}
public JMap2D getMap() {
return map;
}
public void setMap(JMap2D map) {
this.map = map;
}
public void setGeometry(final Feature feature){
this.original = feature;
this.current = null;
}
/**
* @return Geometry is data CRS.
*/
public Geometry getGeometry(){
if(current == null){
return (Geometry) FeatureExt.getDefaultGeometryAttributeValue(original);
}else{
return current;
}
}
private boolean generate(){
if(original == null){
return false;
}
if(map == null){
return false;
}
final boolean mapCrs = guiMapCrs.isSelected();
try{
final CoordinateReferenceSystem mapCRS = map.getCanvas().getObjectiveCRS2D();
final AttributeType desc = FeatureExt.getDefaultGeometryAttribute(original.getType());
final CoordinateReferenceSystem dataCRS = FeatureExt.getCRS(desc);
Geometry geom = (Geometry) FeatureExt.getDefaultGeometryAttributeValue(original);
geom = (Geometry) geom.clone();
final Class clazz = desc.getValueClass();
if(mapCrs){
//reproject geometry in map crs for simplification
final MathTransform trs = CRS.findOperation(dataCRS,mapCRS, null).getMathTransform();
geom = JTS.transform(geom, trs);
}
if(guiDouglas.isSelected()){
final DouglasPeuckerSimplifier simplifier = new DouglasPeuckerSimplifier(geom);
simplifier.setDistanceTolerance((Double)guiIndice.getValue());
current = simplifier.getResultGeometry();
}else{
final TopologyPreservingSimplifier simplifier = new TopologyPreservingSimplifier(geom);
simplifier.setDistanceTolerance((Double)guiIndice.getValue());
current = simplifier.getResultGeometry();
}
if(mapCrs){
//reproject geometry in data crs
final MathTransform trs = CRS.findOperation(mapCRS, dataCRS, null).getMathTransform();
current = JTS.transform(current, trs);
}
//ensure geometry type is preserved
current = JTSMapping.convertType(current, clazz);
guiError.setText("");
return true;
}catch(Exception ex){
LOGGER.log(Level.INFO, ex.getLocalizedMessage(),ex);
guiError.setText(ex.getLocalizedMessage());
return false;
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
groupSimplify = new javax.swing.ButtonGroup();
groupCRS = new javax.swing.ButtonGroup();
guiRollback = new javax.swing.JButton();
guiApply = new javax.swing.JButton();
guiError = new javax.swing.JLabel();
lbl = new javax.swing.JLabel();
guiIndice = new javax.swing.JSpinner();
jPanel1 = new javax.swing.JPanel();
guiMapCrs = new javax.swing.JRadioButton();
guiDataCrs = new javax.swing.JRadioButton();
jPanel2 = new javax.swing.JPanel();
guiDouglas = new javax.swing.JRadioButton();
guiTopology = new javax.swing.JRadioButton();
guiRollback.setText(MessageBundle.format("cancel")); // NOI18N
guiRollback.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
guiRollbackActionPerformed(evt);
}
});
guiApply.setText(MessageBundle.format("apply")); // NOI18N
guiApply.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
guiApplyActionPerformed(evt);
}
});
guiError.setForeground(new java.awt.Color(255, 0, 0));
lbl.setText(MessageBundle.format("factor")); // NOI18N
guiIndice.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(0.0d), Double.valueOf(0.0d), null, Double.valueOf(1.0d)));
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(MessageBundle.format("crs"))); // NOI18N
groupCRS.add(guiMapCrs);
guiMapCrs.setSelected(true);
guiMapCrs.setText(MessageBundle.format("map")); // NOI18N
groupCRS.add(guiDataCrs);
guiDataCrs.setText(MessageBundle.format("data")); // NOI18N
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(guiDataCrs, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(guiMapCrs, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(guiMapCrs)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(guiDataCrs)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(MessageBundle.format("type"))); // NOI18N
groupSimplify.add(guiDouglas);
guiDouglas.setSelected(true);
guiDouglas.setText(MessageBundle.format("douglaspeuker")); // NOI18N
groupSimplify.add(guiTopology);
guiTopology.setText(MessageBundle.format("topologic")); // NOI18N
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(guiDouglas, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(guiTopology, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE))
.addContainerGap())
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(guiDouglas)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(guiTopology)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lbl)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(guiIndice, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(guiError, javax.swing.GroupLayout.DEFAULT_SIZE, 124, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(guiApply)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(guiRollback))
.addGroup(layout.createSequentialGroup()
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {guiApply, guiRollback});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lbl)
.addComponent(guiIndice, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(guiError, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(guiRollback, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
.addComponent(guiApply, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void guiApplyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_guiApplyActionPerformed
if(generate()){
firePropertyChange(GEOMETRY_PROPERTY, -1,1);
}
}//GEN-LAST:event_guiApplyActionPerformed
private void guiRollbackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_guiRollbackActionPerformed
this.current = null;
firePropertyChange(GEOMETRY_PROPERTY, -1,1);
}//GEN-LAST:event_guiRollbackActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup groupCRS;
private javax.swing.ButtonGroup groupSimplify;
private javax.swing.JButton guiApply;
private javax.swing.JRadioButton guiDataCrs;
private javax.swing.JRadioButton guiDouglas;
private javax.swing.JLabel guiError;
private javax.swing.JSpinner guiIndice;
private javax.swing.JRadioButton guiMapCrs;
private javax.swing.JButton guiRollback;
private javax.swing.JRadioButton guiTopology;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JLabel lbl;
// End of variables declaration//GEN-END:variables
}