/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
/*
* Copyright (C) 2010 srichter
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
* MeasuringComponent.java
*
* Created on 10.02.2010, 11:00:03
*/
package de.cismet.cismap.commons.gui.measuring;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.util.AffineTransformation;
import java.awt.Cursor;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.util.List;
import de.cismet.cismap.commons.BoundingBox;
import de.cismet.cismap.commons.Crs;
import de.cismet.cismap.commons.XBoundingBox;
import de.cismet.cismap.commons.features.DefaultFeatureCollection;
import de.cismet.cismap.commons.features.DefaultRasterDocumentFeature;
import de.cismet.cismap.commons.features.Feature;
import de.cismet.cismap.commons.features.FeatureCollection;
import de.cismet.cismap.commons.features.PureNewFeature;
import de.cismet.cismap.commons.features.RasterDocumentFeature;
import de.cismet.cismap.commons.gui.MappingComponent;
import de.cismet.cismap.commons.gui.layerwidget.ActiveLayerModel;
import de.cismet.cismap.commons.gui.piccolo.eventlistener.MessenGeometryListener;
import de.cismet.tools.collections.TypeSafeCollections;
/**
* DOCUMENT ME!
*
* @author srichter
* @version $Revision$, $Date$
*/
public class MeasuringComponent extends javax.swing.JPanel {
//~ Static fields/initializers ---------------------------------------------
private static final String MY_MESSEN_MODE = "MY_MESSEN_MODE";
//~ Instance fields --------------------------------------------------------
private final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(this.getClass());
private final XBoundingBox initialBoundingBox;
private RasterDocumentFeature mainRasterDocumentFeature;
private final MessenGeometryListener mapListener;
// Variables declaration - do not modify//GEN-BEGIN:variables
private de.cismet.cismap.commons.gui.MappingComponent map;
private javax.swing.JPanel panCenter;
// End of variables declaration//GEN-END:variables
//~ Constructors -----------------------------------------------------------
/**
* Creates new form MeasuringComponent.
*/
public MeasuringComponent() {
this(new XBoundingBox(
2583621.251964098d,
5682507.032498134d,
2584022.9413952776d,
5682742.852810634d,
"EPSG:31466",
false),
new Crs("EPSG:31466", "EPSG:31466", "EPSG:31466", false, true));
}
/**
* Creates a new MeasuringComponent object.
*
* @param initialBBox DOCUMENT ME!
* @param srs DOCUMENT ME!
*/
public MeasuringComponent(final XBoundingBox initialBBox, final Crs srs) {
initComponents();
this.mapListener = new MessenGeometryListener(map);
this.initialBoundingBox = initialBBox;
this.mainRasterDocumentFeature = null;
final ActiveLayerModel mappingModel = new ActiveLayerModel();
mappingModel.addHome(initialBBox);
mappingModel.setSrs(srs);
mappingModel.setDefaultHomeSrs(srs);
map.setAnimationDuration(0);
map.setReadOnly(false);
map.setMappingModel(mappingModel);
// initial positioning of the map
map.gotoInitialBoundingBox();
// interaction mode
map.setInteractionMode(MappingComponent.PAN);
map.addInputListener(MY_MESSEN_MODE, mapListener);
map.unlock();
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public MessenGeometryListener getMessenInputListener() {
return mapListener;
}
/**
* DOCUMENT ME!
*/
public void dispose() {
// TODO:
// this is a quick fix for the memory leak that some mapping components can not be garbage collected
panCenter.remove(map);
map.removeInputEventListener(mapListener);
map.dispose();
map = null;
}
/**
* DOCUMENT ME!
*/
public void reset() {
removeAllFeatures();
map.setInteractionMode(MappingComponent.PAN);
}
/**
* DOCUMENT ME!
*/
public void removeAllFeatures() {
final FeatureCollection fc = map.getFeatureCollection();
if (fc instanceof DefaultFeatureCollection) {
((DefaultFeatureCollection)fc).clear();
} else {
fc.removeAllFeatures();
}
}
/**
* DOCUMENT ME!
*/
public void gotoInitialBoundingBox() {
map.gotoInitialBoundingBox();
}
/**
* DOCUMENT ME!
*
* @param feature DOCUMENT ME!
*/
public void addFeature(final Feature feature) {
if (feature != null) {
if (feature instanceof RasterDocumentFeature) {
mainRasterDocumentFeature = (RasterDocumentFeature)feature;
}
getFeatureCollection().addFeature(feature);
} else {
log.warn("Feature is null!");
}
}
/**
* DOCUMENT ME!
*
* @param bi DOCUMENT ME!
*/
public void addImage(final BufferedImage bi) {
addImage(bi, null);
}
/**
* DOCUMENT ME!
*
* @param bi DOCUMENT ME!
* @param geometry DOCUMENT ME!
*/
public void addImage(final BufferedImage bi, final Geometry geometry) {
final DefaultRasterDocumentFeature drdf;
if (geometry != null) {
drdf = new DefaultRasterDocumentFeature(bi, geometry);
} else {
drdf = new DefaultRasterDocumentFeature(bi, initialBoundingBox.getX1(), initialBoundingBox.getY1());
}
addFeature(drdf);
}
/**
* DOCUMENT ME!
*
* @param bi DOCUMENT ME!
* @param geometry DOCUMENT ME!
* @param srid DOCUMENT ME!
*/
public void addImage(final BufferedImage bi, final Geometry geometry, final int srid) {
final DefaultRasterDocumentFeature drdf;
if (geometry != null) {
drdf = new DefaultRasterDocumentFeature(bi, geometry);
} else {
drdf = new DefaultRasterDocumentFeature(bi, initialBoundingBox.getX1(), initialBoundingBox.getY1(), srid);
}
addFeature(drdf);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public MappingComponent getMap() {
return map;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public FeatureCollection getFeatureCollection() {
return map.getFeatureCollection();
}
/**
* DOCUMENT ME!
*/
public void zoomToFeatureCollection() {
if ((map.getWidth() > 0) && (map.getHeight() > 0)) {
map.zoomToFeatureCollection();
} else {
// lazy zoom if map is hidden and has size zero.
map.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(final ComponentEvent e) {
if ((map.getWidth() > 0) && (map.getHeight() > 0)) {
map.zoomToFeatureCollection();
map.removeComponentListener(this);
}
}
});
}
}
/**
* 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() {
panCenter = new javax.swing.JPanel();
map = new de.cismet.cismap.commons.gui.MappingComponent();
setOpaque(false);
setLayout(new java.awt.BorderLayout());
panCenter.setOpaque(false);
panCenter.setLayout(new java.awt.BorderLayout());
map.setBorder(javax.swing.BorderFactory.createEtchedBorder());
panCenter.add(map, java.awt.BorderLayout.CENTER);
add(panCenter, java.awt.BorderLayout.CENTER);
} // </editor-fold>//GEN-END:initComponents
/**
* DOCUMENT ME!
*
* @param realDistance DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
private double calculateScaleFactor(final double realDistance) {
for (final Feature f : map.getFeatureCollection().getAllFeatures()) {
// Danger: Messlinie finden...unter der Annahme dass es nur ein PNF gibt!
if (f instanceof PureNewFeature) {
final double virtualDistance = f.getGeometry().getLength();
if (virtualDistance != 0) {
return realDistance / virtualDistance;
}
}
}
return 0;
}
/**
* DOCUMENT ME!
*
* @param scalefactor DOCUMENT ME!
*/
private void applyScaling(final double scalefactor) {
// save camera position
final BoundingBox oldViewBounds = map.getCurrentBoundingBoxFromCamera();
double vX1 = oldViewBounds.getX1();
double vY1 = oldViewBounds.getY1();
double vX2 = oldViewBounds.getX2();
double vY2 = oldViewBounds.getY2();
// unhold all features, so that they all can be scaled
getFeatureCollection().setHoldAll(false);
final List<Feature> backup = TypeSafeCollections.newArrayList();
for (final Feature f : map.getFeatureCollection().getAllFeatures()) {
backup.add(f);
}
map.getFeatureCollection().removeAllFeatures();
AffineTransformation trafo = new AffineTransformation();
trafo = trafo.scale(scalefactor, scalefactor);
Point centroid = mainRasterDocumentFeature.getGeometry().getCentroid();
final double oldX = centroid.getX();
final double oldY = centroid.getY();
for (final Feature f : backup) {
f.getGeometry().apply(trafo);
}
centroid = mainRasterDocumentFeature.getGeometry().getCentroid();
final double transX = oldX - centroid.getX();
final double transY = oldY - centroid.getY();
final AffineTransformation backTranslation = AffineTransformation.translationInstance(transX, transY);
for (final Feature f : backup) {
f.getGeometry().apply(backTranslation);
}
map.getFeatureCollection().addFeatures(backup);
// apply trafo on camera position
vX1 *= scalefactor;
vY1 *= scalefactor;
vX2 *= scalefactor;
vY2 *= scalefactor;
vX1 += transX;
vY1 += transY;
vX2 += transX;
vY2 += transY;
final BoundingBox newBB = new BoundingBox(vX1, vY1, vX2, vY2);
// adjust camera
map.gotoBoundingBox(newBB, false, true, 0);
}
/**
* DOCUMENT ME!
*/
public void actionOverview() {
map.zoomToFeatureCollection();
}
/**
* DOCUMENT ME!
*
* @param measuredDistance DOCUMENT ME!
*/
public void actionCalibrate(final double measuredDistance) {
if ((measuredDistance != 0d) && (mainRasterDocumentFeature != null)) {
final double scalefactor = calculateScaleFactor(measuredDistance);
applyScaling(scalefactor);
}
map.setInteractionMode(MappingComponent.PAN);
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public Geometry getMainDocumentGeometry() {
if (mainRasterDocumentFeature != null) {
return mainRasterDocumentFeature.getGeometry();
}
return null;
}
/**
* DOCUMENT ME!
*/
public void actionMeasurePolygon() {
mapListener.setMode(MessenGeometryListener.POLYGON);
map.setInteractionMode(MY_MESSEN_MODE);
map.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
/**
* DOCUMENT ME!
*/
public void actionMeasureLine() {
mapListener.setMode(MessenGeometryListener.LINESTRING);
map.setInteractionMode(MY_MESSEN_MODE);
map.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
}
/**
* DOCUMENT ME!
*/
public void actionPan() {
map.setInteractionMode(MappingComponent.PAN);
}
/**
* DOCUMENT ME!
*/
public void actionZoom() {
map.setInteractionMode(MappingComponent.ZOOM);
}
}