[Schmitzm-commits] r156 - in trunk: dist src/schmitzm/geotools src/schmitzm/geotools/gui

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Jun 22 14:58:50 CEST 2009


Author: mojays
Date: 2009-06-22 14:58:36 +0200 (Mon, 22 Jun 2009)
New Revision: 156

Modified:
   trunk/dist/schmitzm-src.zip
   trunk/dist/schmitzm.jar
   trunk/src/schmitzm/geotools/JTSUtil.java
   trunk/src/schmitzm/geotools/gui/JMapPane.java
Log:
JMapPane: Selection now "CRS-sensitive"

Modified: trunk/dist/schmitzm-src.zip
===================================================================
(Binary files differ)

Modified: trunk/dist/schmitzm.jar
===================================================================
(Binary files differ)

Modified: trunk/src/schmitzm/geotools/JTSUtil.java
===================================================================
--- trunk/src/schmitzm/geotools/JTSUtil.java	2009-06-22 10:53:59 UTC (rev 155)
+++ trunk/src/schmitzm/geotools/JTSUtil.java	2009-06-22 12:58:36 UTC (rev 156)
@@ -19,6 +19,7 @@
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 
+import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Envelope;
 
 /**
@@ -66,4 +67,26 @@
 	}
     return destEnv;
   }
+
+  /**
+   * Transformiert eine Koordinate von einem CRS in ein anderes.
+   * @param sourceCoord Koordinate
+   * @param sourceCRS   CRS von {@code sourceCoord}
+   * @param destCRS     CRS in das umgerechnet werden soll
+   * @see CRS#findMathTransform(CoordinateReferenceSystem,CoordinateReferenceSystem)
+   * @see JTS#transform(Coordinate, Coordinate, MathTransform)
+   */
+  public static Coordinate transformCoordinate(Coordinate sourceCoord, CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem destCRS) {
+    Coordinate destCoord = null;
+    MathTransform transform;
+    try {
+        transform = CRS.findMathTransform(sourceCRS, destCRS);
+        destCoord = JTS.transform(sourceCoord,null,transform);
+    } catch (FactoryException e) {
+        LOGGER.warn("CRS tranformation for JTS coordinate not successful",e);
+    } catch (TransformException e) {
+        LOGGER.warn("CRS tranformation for JTS coordinate not successful",e);
+    }
+    return destCoord;
+  }
 }

Modified: trunk/src/schmitzm/geotools/gui/JMapPane.java
===================================================================
--- trunk/src/schmitzm/geotools/gui/JMapPane.java	2009-06-22 10:53:59 UTC (rev 155)
+++ trunk/src/schmitzm/geotools/gui/JMapPane.java	2009-06-22 12:58:36 UTC (rev 156)
@@ -27,8 +27,10 @@
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Vector;
 
 import javax.swing.JList;
@@ -46,6 +48,7 @@
 import org.geotools.feature.Feature;
 import org.geotools.feature.FeatureCollection;
 import org.geotools.feature.FeatureType;
+import org.geotools.feature.GeometryAttributeType;
 import org.geotools.filter.AbstractFilter;
 import org.geotools.filter.FilterFactoryImpl;
 import org.geotools.filter.GeometryFilterImpl;
@@ -69,6 +72,7 @@
 import org.opengis.coverage.CannotEvaluateException;
 import org.opengis.filter.Filter;
 import org.opengis.filter.expression.Expression;
+import org.opengis.filter.spatial.BinarySpatialOperator;
 import org.opengis.parameter.GeneralParameterValue;
 import org.opengis.referencing.FactoryException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -78,6 +82,7 @@
 import schmitzm.geotools.FilterUtil;
 import schmitzm.geotools.GTUtil;
 import schmitzm.geotools.JTSUtil;
+import schmitzm.geotools.feature.FeatureUtil;
 import schmitzm.geotools.grid.GridUtil;
 import schmitzm.geotools.map.event.FeatureSelectedEvent;
 import schmitzm.geotools.map.event.GeneralSelectionEvent;
@@ -133,2272 +138,2430 @@
  * {@linkplain AffineTransform affine Transformation} mit der die aktuellen
  * Fenster-Koordinaten (z.B. eines <code>MouseEvent</code>) in
  * Karten-Koordinaten (Latitude/Longitude) umgerechnet werden koennen.
- * 
+ *
  * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
  *         (University of Bonn/Germany)
  * @version 1.0
  */
 public class JMapPane extends org.geotools.gui.swing.JMapPane {
 
-	/**
-	 * SK: Nach dem Drag, soll die {@link GeoMapPane} erfahren, dass die Area
-	 * veraendert wurde.
-	 */
-	protected void processDrag(int x1, int y1, int x2, int y2, MouseEvent e) {
-		// MS, 26.05.2008: Zoom-Funktion der Oberklasse soll nur erfolgen, wenn
-		// diese auch fuer die WindowSelection-Aktion eingestellt ist!
-		// Wenn z.B. fuer Links-Klick ZOOM_IN eingestellt ist, fuer
-		// Links-Drag aber SELECT_TOP, dann soll kein Zoom beim
-		// Links-Drag erfolgen!!
-		// Ausnahme: Bei Rechts-Drag (Button 3) soll die Methode
-		// trotzdem aufgerufen werden fuer Pan!
-		if (getState() == ZOOM_IN && getWindowSelectionState() != ZOOM_IN
-				&& e.getButton() != 3)
-			return;
-		super.processDrag(x1, y1, x2, y2, e);
+    /**
+     * SK: Nach dem Drag, soll die {@link GeoMapPane} erfahren, dass die Area
+     * veraendert wurde.
+     */
+    protected void processDrag(int x1, int y1, int x2, int y2, MouseEvent e) {
+        // MS, 26.05.2008: Zoom-Funktion der Oberklasse soll nur erfolgen, wenn
+        // diese auch fuer die WindowSelection-Aktion eingestellt ist!
+        // Wenn z.B. fuer Links-Klick ZOOM_IN eingestellt ist, fuer
+        // Links-Drag aber SELECT_TOP, dann soll kein Zoom beim
+        // Links-Drag erfolgen!!
+        // Ausnahme: Bei Rechts-Drag (Button 3) soll die Methode
+        // trotzdem aufgerufen werden fuer Pan!
+        if (getState() == ZOOM_IN && getWindowSelectionState() != ZOOM_IN
+                && e.getButton() != 3)
+            return;
+        super.processDrag(x1, y1, x2, y2, e);
 
-		// SK, 19.6.2009:
-		// Ein MapAreaChangedEvent soll nur geworfen werden, wenn auch gezoomt
-		// wurde! Irgendwie wird das auch aufgerufen, wenn man mit InfoClick
-		// tool nur click - also garkeit kein draggin gemacht hat.
-		if (!oldMapArea.equals(mapArea) && (getState() == ZOOM_IN || getState() == ZOOM_OUT))
-			fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea, mapArea));
-	}
+        // SK, 19.6.2009:
+        // Ein MapAreaChangedEvent soll nur geworfen werden, wenn auch gezoomt
+        // wurde! Irgendwie wird das auch aufgerufen, wenn man mit InfoClick
+        // tool nur click - also garkeit kein draggin gemacht hat.
+        if (!oldMapArea.equals(mapArea) && (getState() == ZOOM_IN || getState() == ZOOM_OUT))
+            fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea, mapArea));
+    }
 
-	private static final Cursor WAIT_CURSOR = Cursor
-			.getPredefinedCursor(Cursor.WAIT_CURSOR);
+    private static final Cursor WAIT_CURSOR = Cursor
+            .getPredefinedCursor(Cursor.WAIT_CURSOR);
 
-	/** Logger for debug messages. */
-	protected static final Logger LOGGER = Logger.getLogger(JMapPane.class
-			.getName());
+    /** Logger for debug messages. */
+    protected static final Logger LOGGER = Logger.getLogger(JMapPane.class
+            .getName());
 
-	/** @deprecated ersetzt durch {@link #ZOOM_IN} */
-	public static final int ZoomIn = org.geotools.gui.swing.JMapPane.ZoomIn;
-	/** @deprecated ersetzt durch {@link #ZOOM_OUT} */
-	public static final int ZoomOut = org.geotools.gui.swing.JMapPane.ZoomOut;
-	/** @deprecated ersetzt durch {@link #PAN} */
-	public static final int Pan = org.geotools.gui.swing.JMapPane.Pan;
-	/** @deprecated ersetzt durch {@link #RESET} */
-	public static final int Reset = org.geotools.gui.swing.JMapPane.Reset;
-	/** @deprecated ersetzt durch {@link #SELECT_TOP} */
-	public static final int Select = org.geotools.gui.swing.JMapPane.Select;
+    /** @deprecated ersetzt durch {@link #ZOOM_IN} */
+    public static final int ZoomIn = org.geotools.gui.swing.JMapPane.ZoomIn;
+    /** @deprecated ersetzt durch {@link #ZOOM_OUT} */
+    public static final int ZoomOut = org.geotools.gui.swing.JMapPane.ZoomOut;
+    /** @deprecated ersetzt durch {@link #PAN} */
+    public static final int Pan = org.geotools.gui.swing.JMapPane.Pan;
+    /** @deprecated ersetzt durch {@link #RESET} */
+    public static final int Reset = org.geotools.gui.swing.JMapPane.Reset;
+    /** @deprecated ersetzt durch {@link #SELECT_TOP} */
+    public static final int Select = org.geotools.gui.swing.JMapPane.Select;
 
-	/**
-	 * Flag fuer Modus "Nichts machen".
-	 * 
-	 * @see #setWindowSelectionState(int)
-	 * @see #setState(int)
-	 */
-	public static final int NONE = 100;
-	/**
-	 * Flag fuer Modus "Zuruecksetzen". Nicht fuer Window-Auswahl moeglich!
-	 * 
-	 * @see #setState(int)
-	 */
-	public static final int RESET = org.geotools.gui.swing.JMapPane.Reset;
-	/**
-	 * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl
-	 * moeglich!
-	 * 
-	 * @see #setState(int)
-	 */
-	public static final int PAN = org.geotools.gui.swing.JMapPane.Pan;
-	/**
-	 * Flag fuer Modus "Heran zoomen".
-	 * 
-	 * @see #setWindowSelectionState(int)
-	 * @see #setState(int)
-	 */
-	public static final int ZOOM_IN = org.geotools.gui.swing.JMapPane.ZoomIn;
-	/**
-	 * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich!
-	 * 
-	 * @see #setState(int)
-	 */
-	public static final int ZOOM_OUT = org.geotools.gui.swing.JMapPane.ZoomOut;
-	/**
-	 * Flag fuer Modus "Feature-Auswahl auf dem obersten (sichtbaren) Layer".
-	 * 
-	 * @see #setWindowSelectionState(int)
-	 * @see #setState(int)
-	 */
-	public static final int SELECT_TOP = org.geotools.gui.swing.JMapPane.Select;
-	/**
-	 * Flag fuer Modus "Feature-Auswahl auf allen (sichtbaren) Layern".
-	 * 
-	 * @see #setWindowSelectionState(int)
-	 * @see #setState(int)
-	 */
-	public static final int SELECT_ALL = 103;
-	/**
-	 * Flag fuer Modus
-	 * "Auswahl nur eines Features, das erste sichtbare von Oben".
-	 * 
-	 * @see #setWindowSelectionState(int)
-	 * @see #setState(int)
-	 */
-	public static final int SELECT_ONE_FROM_TOP = 104;
+    /**
+     * Flag fuer Modus "Nichts machen".
+     *
+     * @see #setWindowSelectionState(int)
+     * @see #setState(int)
+     */
+    public static final int NONE = 100;
+    /**
+     * Flag fuer Modus "Zuruecksetzen". Nicht fuer Window-Auswahl moeglich!
+     *
+     * @see #setState(int)
+     */
+    public static final int RESET = org.geotools.gui.swing.JMapPane.Reset;
+    /**
+     * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl
+     * moeglich!
+     *
+     * @see #setState(int)
+     */
+    public static final int PAN = org.geotools.gui.swing.JMapPane.Pan;
+    /**
+     * Flag fuer Modus "Heran zoomen".
+     *
+     * @see #setWindowSelectionState(int)
+     * @see #setState(int)
+     */
+    public static final int ZOOM_IN = org.geotools.gui.swing.JMapPane.ZoomIn;
+    /**
+     * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich!
+     *
+     * @see #setState(int)
+     */
+    public static final int ZOOM_OUT = org.geotools.gui.swing.JMapPane.ZoomOut;
+    /**
+     * Flag fuer Modus "Feature-Auswahl auf dem obersten (sichtbaren) Layer".
+     *
+     * @see #setWindowSelectionState(int)
+     * @see #setState(int)
+     */
+    public static final int SELECT_TOP = org.geotools.gui.swing.JMapPane.Select;
+    /**
+     * Flag fuer Modus "Feature-Auswahl auf allen (sichtbaren) Layern".
+     *
+     * @see #setWindowSelectionState(int)
+     * @see #setState(int)
+     */
+    public static final int SELECT_ALL = 103;
+    /**
+     * Flag fuer Modus
+     * "Auswahl nur eines Features, das erste sichtbare von Oben".
+     *
+     * @see #setWindowSelectionState(int)
+     * @see #setState(int)
+     */
+    public static final int SELECT_ONE_FROM_TOP = 104;
 
-	/** Modus fuer Window-Selektion (Default: {@link #ZOOM_IN}). */
-	protected int selState = NONE;
+    /** Modus fuer Window-Selektion (Default: {@link #ZOOM_IN}). */
+    protected int selState = NONE;
 
-	/**
-	 * Transformation zwischen Fenster-Koordinaten und Karten-Koordinaten
-	 * (lat/lon)
-	 */
-	protected AffineTransform transform = null;
+    /**
+     * Transformation zwischen Fenster-Koordinaten und Karten-Koordinaten
+     * (lat/lon)
+     */
+    protected AffineTransform transform = null;
 
-	/**
-	 * Liste der angeschlossenen Listener, die auf Aktionen des MapPanes
-	 * lauschen.
-	 */
-	protected Vector<JMapPaneListener> mapPaneListeners = new Vector<JMapPaneListener>();
+    /**
+     * Liste der angeschlossenen Listener, die auf Aktionen des MapPanes
+     * lauschen.
+     */
+    protected Vector<JMapPaneListener> mapPaneListeners = new Vector<JMapPaneListener>();
 
-	protected MouseSelectionTracker_Public selTracker = new MouseSelectionTracker_Public() {
-		// MS (2009-13-05): noch buggy -> wieder rausgenommen (Probleme mit
-		// mehreren parallelen Mouse(Motion)Listenern
-		public void mouseDragged(final MouseEvent event) {
-			// Wenn Fenster-Selektions-Modus auf NICHTS steht (z.B. Info-Tool),
-			// keinen Rahmen beim Draggen zeichnen
-			if (selState == NONE)
-				return;
-			if (getState() == ZOOM_IN || getState() == ZOOM_OUT)
-				return;
+    protected MouseSelectionTracker_Public selTracker = new MouseSelectionTracker_Public() {
+        public void mouseDragged(final MouseEvent event) {
+          // Wenn Fenster-Selektions-Modus auf NICHTS steht (z.B. Info-Tool),
+          // keinen Rahmen beim Draggen zeichnen
+          if ( selState == NONE  )
+            return;
+          // Wenn Zoom bereits durch Oberklasse aktiviert wird,
+          // malt diese das Rectangle
+          if ( getState() == ZOOM_IN || getState() == ZOOM_OUT )
+            return;
 
-			super.mouseDragged(event);
-		}
+          super.mouseDragged(event);
+        }
 
-		protected void selectionPerformed(int ox, int oy, int px, int py) {
-			// MS, 20.05.2008: In performSelectionEvent(..) wurde das Zoomen
-			// wieder
-			// reingenommen, damit bei Fenster-Auswahl auch gezoomt
-			// wird, wenn der Klick-Zoom (setState(.)) deaktiviert
-			// ist. Wenn dieser jedoch ebenfalls aktiviert ist,
-			// darf an dieser Stelle nicht nochmal gezoomt werden,
-			// da sonst 2x gezoomt wird!!
-			if (getState() != ZOOM_IN)
-				performSelectionEvent(ox, oy, px, py);
-		}
-	};
+        protected void selectionPerformed(int ox, int oy, int px, int py) {
+            // MS, 20.05.2008: In performSelectionEvent(..) wurde das Zoomen
+            // wieder reingenommen, damit bei Fenster-Auswahl auch gezoomt
+            // wird, wenn der Klick-Zoom (setState(.)) deaktiviert
+            // ist. Wenn dieser jedoch ebenfalls aktiviert ist,
+            // darf an dieser Stelle nicht nochmal gezoomt werden,
+            // da sonst 2x gezoomt wird!!
+            if (getState() != ZOOM_IN)
+                performSelectionEvent(ox, oy, px, py);
+        }
+    };
 
-	private static final FilterFactoryImpl ff = FilterUtil.FILTER_FAC;
-	private static final GeometryFactory gf = FilterUtil.GEOMETRY_FAC;
+    private static final FilterFactoryImpl ff = FilterUtil.FILTER_FAC;
+    private static final GeometryFactory gf = FilterUtil.GEOMETRY_FAC;
 
-	/**
-	 * A flag indicating if dispose() was already called. If true, then further
-	 * use of this {@link JMapPane} is undefined.
-	 */
-	private boolean disposed = false;
+    /**
+     * A flag indicating if dispose() was already called. If true, then further
+     * use of this {@link JMapPane} is undefined.
+     */
+    private boolean disposed = false;
 
-	/** Listener, der auf das Mausrad lauscht und mit Zoom reagiert */
-	private MouseWheelListener mouseWheelZoomListener;
+    /** Listener, der auf das Mausrad lauscht und mit Zoom reagiert */
+    private MouseWheelListener mouseWheelZoomListener;
 
-	// /** Wenn true, dann werden RasterLayer waehrend des Panning auf
-	// setVisible(false) gesetzt **/
-	// protected boolean hideRasterLayersDuringPan = false;
-	// /** Remebers the layers that are hidden during a PAN action **/
-	// protected List<MapLayer> hiddenForPanning = new LinkedList<MapLayer>();
+    // /** Wenn true, dann werden RasterLayer waehrend des Panning auf
+    // setVisible(false) gesetzt **/
+    // protected boolean hideRasterLayersDuringPan = false;
+    // /** Remebers the layers that are hidden during a PAN action **/
+    // protected List<MapLayer> hiddenForPanning = new LinkedList<MapLayer>();
 
-	/**
-	 * Wenn true, dann wird der Cursor waehrend des naechsten Repaint auf die
-	 * WAIT gesetzt.
-	 **/
-	private boolean setWaitCursorDuringNextRepaint;
-	/**
-	 * Defines which Component to change the MouseCursor if in WAIT STATE. If
-	 * unset, only THIS component is used
-	 **/
-	private Component mouseWaitCursorComponent;
+    /**
+     * Wenn true, dann wird der Cursor waehrend des naechsten Repaint auf die
+     * WAIT gesetzt.
+     **/
+    private boolean setWaitCursorDuringNextRepaint;
+    /**
+     * Defines which Component to change the MouseCursor if in WAIT STATE. If
+     * unset, only THIS component is used
+     **/
+    private Component mouseWaitCursorComponent;
 
-	/** Cursor wenn kein Mausbutton gedrueckt wird. default oder SwingUtil.PAN **/
-	private Cursor normalCursor = Cursor
-			.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
+    /** Cursor wenn kein Mausbutton gedrueckt wird. default oder SwingUtil.PAN **/
+    private Cursor normalCursor = Cursor
+            .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
 
-	/**
-	 * Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen
-	 * MapPane-Funktion
-	 */
-	protected Cursor staticCursor = null;
+    /**
+     * Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen
+     * MapPane-Funktion
+     */
+    protected Cursor staticCursor = null;
 
-	private MouseInputAdapter dragWaitCursorListener;
+    private MouseInputAdapter dragWaitCursorListener;
 
-	/** An (transparent) image to paint over the map in the lower right corner **/
-	private BufferedImage mapImage = null;
+    /** An (transparent) image to paint over the map in the lower right corner **/
+    private BufferedImage mapImage = null;
 
-	/**
-	 * Erzeugt ein neues MapPane.
-	 * 
-	 * @param layout
-	 *            Layout-Manager fuer die GUI-Komponente (z.B.
-	 *            {@link BorderLayout})
-	 * @param isDoubleBuffered
-	 *            siehe Konstruktor der
-	 *            {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
-	 *            Oberklasse}
-	 * @param renderer
-	 *            Renderer fuer die graphische Darestellung (z.B.
-	 *            {@link StreamingRenderer})
-	 * @param context
-	 *            Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
-	 *            ).
-	 */
-	public JMapPane() {
-		this(null, true, null, null);
-	}
+    /**
+     * Erzeugt ein neues MapPane.
+     *
+     * @param layout
+     *            Layout-Manager fuer die GUI-Komponente (z.B.
+     *            {@link BorderLayout})
+     * @param isDoubleBuffered
+     *            siehe Konstruktor der
+     *            {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
+     *            Oberklasse}
+     * @param renderer
+     *            Renderer fuer die graphische Darestellung (z.B.
+     *            {@link StreamingRenderer})
+     * @param context
+     *            Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+     *            ).
+     */
+    public JMapPane() {
+        this(null, true, null, null);
+    }
 
-	/**
-	 * Erzeugt ein neues MapPane.
-	 * 
-	 * @param layout
-	 *            Layout-Manager fuer die GUI-Komponente (z.B.
-	 *            {@link BorderLayout})
-	 * @param isDoubleBuffered
-	 *            siehe Konstruktor der
-	 *            {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
-	 *            Oberklasse}. Bei <code>null</code> wird <code>true</code> andgenommen.
-	 * @param renderer
-	 *            Renderer fuer die graphische Darestellung (z.B.
-	 *            {@link StreamingRenderer})
-	 * @param context
-	 *            Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
-	 *            ).
-	 */
-	public JMapPane(LayoutManager layout, Boolean isDoubleBuffered,
-			GTRenderer renderer, MapContext context) {
-		super(layout != null ? layout : new BorderLayout(), isDoubleBuffered != null ? isDoubleBuffered : true,
-				renderer != null ? renderer : new StreamingRenderer(),
-				context != null ? context : new DefaultMapContext(GTUtil.WGS84));
+    /**
+     * Erzeugt ein neues MapPane.
+     *
+     * @param layout
+     *            Layout-Manager fuer die GUI-Komponente (z.B.
+     *            {@link BorderLayout})
+     * @param isDoubleBuffered
+     *            siehe Konstruktor der
+     *            {@linkplain org.geotools.gui.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
+     *            Oberklasse}. Bei <code>null</code> wird <code>true</code> andgenommen.
+     * @param renderer
+     *            Renderer fuer die graphische Darestellung (z.B.
+     *            {@link StreamingRenderer})
+     * @param context
+     *            Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+     *            ).
+     */
+    public JMapPane(LayoutManager layout, Boolean isDoubleBuffered,
+            GTRenderer renderer, MapContext context) {
+        super(layout != null ? layout : new BorderLayout(), isDoubleBuffered != null ? isDoubleBuffered : true,
+                renderer != null ? renderer : new StreamingRenderer(),
+                context != null ? context : new DefaultMapContext(GTUtil.WGS84));
 
-		// Dieser Hint sorgt wohl dafuer, dass die Rasterpixel nicht
-		// interpoliert werden
-		// Ueber die Methode enableAntiAliasing(boolean) kann das
-		// rechenintensive AntiAliasing fuer Text un Vectoren eingeschaltet
-		// werden
-		RenderingHints hints = ImageUtilities.NN_INTERPOLATION_HINT;
-		getRenderer().setJava2DHints(hints);
+        // Dieser Hint sorgt wohl dafuer, dass die Rasterpixel nicht
+        // interpoliert werden
+        // Ueber die Methode enableAntiAliasing(boolean) kann das
+        // rechenintensive AntiAliasing fuer Text un Vectoren eingeschaltet
+        // werden
+        RenderingHints hints = ImageUtilities.NN_INTERPOLATION_HINT;
+        getRenderer().setJava2DHints(hints);
 
-		// hints.add( new RenderingHints(RenderingHints.KEY_ANTIALIASING,
-		// RenderingHints.VALUE_ANTIALIAS_OFF ) );
-		// hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
-		// RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ) );
-		// hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
-		// RenderingHints.VALUE_INTERPOLATION_BICUBIC ) );
-		// hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
-		// RenderingHints.VALUE_INTERPOLATION_BILINEAR ) );
-		// hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
-		// RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED ) );
-		// hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
-		// RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY ) );
-		// Map rendererParams = new HashMap();
-		// rendererParams.put("optimizedDataLoadingEnabled",new Boolean(true) );
-		// renderer.setRendererHints( rendererParams );
+        // hints.add( new RenderingHints(RenderingHints.KEY_ANTIALIASING,
+        // RenderingHints.VALUE_ANTIALIAS_OFF ) );
+        // hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
+        // RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ) );
+        // hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
+        // RenderingHints.VALUE_INTERPOLATION_BICUBIC ) );
+        // hints.add( new RenderingHints(RenderingHints.KEY_INTERPOLATION,
+        // RenderingHints.VALUE_INTERPOLATION_BILINEAR ) );
+        // hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
+        // RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED ) );
+        // hints.add( new RenderingHints(RenderingHints.KEY_ALPHA_INTERPOLATION,
+        // RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY ) );
+        // Map rendererParams = new HashMap();
+        // rendererParams.put("optimizedDataLoadingEnabled",new Boolean(true) );
+        // renderer.setRendererHints( rendererParams );
 
-		setWindowSelectionState(ZOOM_IN);
-		setState(ZOOM_IN);
+        setWindowSelectionState(ZOOM_IN);
+        setState(ZOOM_IN);
 
-		// MS (2009-13-05): noch buggy -> wieder rausgenommen (Probleme mit
-		// mehreren parallelen Mouse(Motion)Listenern
-		// // Listener fuer Selektions-Rahmen
-		// addMouseListener(selTracker);
+         // Listener, der auf das Mausrad lauscht und mit Zoom reagiert
+         mouseWheelZoomListener = new MouseWheelListener() {
+           public void mouseWheelMoved(MouseWheelEvent e) {
+             performMouseWheelEvent(e);
+           }
+         };
+         this.addMouseWheelListener(mouseWheelZoomListener);
 
-		// Listener, der auf das Mausrad lauscht und mit Zoom reagiert
-		mouseWheelZoomListener = new MouseWheelListener() {
-			public void mouseWheelMoved(MouseWheelEvent e) {
-				performMouseWheelEvent(e);
-			}
-		};
-		this.addMouseWheelListener(mouseWheelZoomListener);
+        // Listener, der auf das Mausrad lauscht und mit Zoom reagiert
+        mouseWheelZoomListener = new MouseWheelListener() {
+            public void mouseWheelMoved(MouseWheelEvent e) {
+                performMouseWheelEvent(e);
+            }
+        };
+        this.addMouseWheelListener(mouseWheelZoomListener);
 
-		/**
-		 * Dieser Listener setzt nach dem Panning (aka Drag) den Maus-Cursor auf
-		 * Wait. Der Rest des Panning wird in der Uberklasse abgewickelt
-		 */
-		dragWaitCursorListener = new MouseInputAdapter() {
-			public void mouseReleased(MouseEvent e) {
-				setWaitCursorDuringNextRepaint = true;
-			};
-		};
-		this.addMouseListener(dragWaitCursorListener);
+        /**
+         * Dieser Listener setzt nach dem Panning (aka Drag) den Maus-Cursor auf
+         * Wait. Der Rest des Panning wird in der Uberklasse abgewickelt
+         */
+        dragWaitCursorListener = new MouseInputAdapter() {
+            public void mouseReleased(MouseEvent e) {
+                setWaitCursorDuringNextRepaint = true;
+            };
+        };
+        this.addMouseListener(dragWaitCursorListener);
 
-		// Hightlight immer auf dem obersten sichtbaren Nicht-Raster-Layer
-		// MS-01.sc: Der GT-Highlight-Manager arbeitet zu langsam und ohnehin
-		// nur
-		// fuer unprojizierte Layer korrekt
-		// this.setHighlight(true);
-		this.setHighlight(false);
-		// MS-01.ec
+        // Hightlight immer auf dem obersten sichtbaren Nicht-Raster-Layer
+        // MS-01.sc: Der GT-Highlight-Manager arbeitet zu langsam und ohnehin
+        // nur fuer unprojizierte Layer korrekt
+        // this.setHighlight(true);
+        this.setHighlight(false);
+        // MS-01.ec
 
-		getContext().addMapLayerListListener(
-				new schmitzm.geotools.map.event.MapLayerListAdapter() {
-					private void resetHighlightLayer() {
-						if (isHighlight())
-							setHighlightLayer(getTopVisibleNonGridCoverageLayer());
-					}
+        getContext().addMapLayerListListener(
+                new schmitzm.geotools.map.event.MapLayerListAdapter() {
+                    private void resetHighlightLayer() {
+                        if (isHighlight())
+                            setHighlightLayer(getTopVisibleNonGridCoverageLayer());
+                    }
 
-					public void layerAdded(
-							org.geotools.map.event.MapLayerListEvent e) {
-						resetHighlightLayer();
-					}
+                    public void layerAdded(
+                            org.geotools.map.event.MapLayerListEvent e) {
+                        resetHighlightLayer();
+                    }
 
-					public void layerChanged(
-							org.geotools.map.event.MapLayerListEvent e) {
-						resetHighlightLayer();
-					}
+                    public void layerChanged(
+                            org.geotools.map.event.MapLayerListEvent e) {
+                        resetHighlightLayer();
+                    }
 
-					public void layerMoved(
-							org.geotools.map.event.MapLayerListEvent e) {
-						resetHighlightLayer();
-					}
+                    public void layerMoved(
+                            org.geotools.map.event.MapLayerListEvent e) {
+                        resetHighlightLayer();
+                    }
 
-					public void layerRemoved(
-							org.geotools.map.event.MapLayerListEvent e) {
-						resetHighlightLayer();
-					}
-				});
+                    public void layerRemoved(
+                            org.geotools.map.event.MapLayerListEvent e) {
+                        resetHighlightLayer();
+                    }
+                });
 
-		// CRS wird immer vom ersten in die Karte eingefuegten Layer uebernommen
-		// Wenn noch keine MapArea gesetzt wurde, wird diese vom Layer
-		// uebernommen
-		getContext().addMapLayerListListener(
-				new schmitzm.geotools.map.event.MapLayerListAdapter() {
-					public void layerAdded(
-							org.geotools.map.event.MapLayerListEvent e) {
-						if (getContext().getLayerCount() == 1) {
-							CoordinateReferenceSystem crs = null;
-							// CRS aus Layer ermitteln
-							try {
-								crs = e.getLayer().getFeatureSource()
-										.getSchema().getDefaultGeometry()
-										.getCoordinateSystem();
-								// wenn noch keine MapArea gesetzt wurde, den
-								// Ausdehnungsbereich des ersten Layers
-								// verwenden, so dass die erste
-								// Karte komplett angezeigt wird
-								if (getMapArea() == null) {
-									Envelope newMapArea = new Envelope(e
-											.getLayer().getFeatureSource()
-											.getBounds());
-									// Kartenbereich um 10% vergroessern, damit
-									// z.B. auch ein Punkt-Layer, welches nur
-									// aus 2 Punnkten
-									// besteht, sichtbar ist (Punkte liegen
-									// sonst
-									// genau auf dem Rand der angezeigten
-									// Flaeche)
-									newMapArea.expandBy(
-											newMapArea.getWidth() * 0.1,
-											newMapArea.getHeight() * 0.1);
-									setMapArea(newMapArea);
-									// in layerAdded(.) der Oberklasse wird
-									// mapArea nochmal neu gesetzt, wenn das
-									// erste Layer
-									// eingefuegt wird
-									// >> hier nur die AreaOfInterest setzen
-									getContext().setAreaOfInterest(newMapArea,
-											crs);
-								}
-							} catch (Exception err) {
-								LOGGER
-										.warn("CRS could not be determined from map layer. WGS84 used.");
-								// err.printStackTrace();
-								crs = DefaultGeographicCRS.WGS84;
-							}
-							// CRS dem MapContext zuweisen
-							try {
-								getContext().setCoordinateReferenceSystem(crs);
-							} catch (Exception err) {
-								LOGGER
-										.error("CRS could not be assigned to map context.");
-							}
-						}
-					}
-				});
-	}
+        // CRS wird immer vom ersten in die Karte eingefuegten Layer uebernommen
+        // Wenn noch keine MapArea gesetzt wurde, wird diese vom Layer
+        // uebernommen
+        getContext().addMapLayerListListener(
+                new schmitzm.geotools.map.event.MapLayerListAdapter() {
+                    public void layerAdded(
+                            org.geotools.map.event.MapLayerListEvent e) {
+                        if (getContext().getLayerCount() == 1) {
+                            CoordinateReferenceSystem crs = null;
+                            // CRS aus Layer ermitteln
+                            try {
+                                crs = e.getLayer().getFeatureSource()
+                                        .getSchema().getDefaultGeometry()
+                                        .getCoordinateSystem();
+                                // wenn noch keine MapArea gesetzt wurde, den
+                                // Ausdehnungsbereich des ersten Layers
+                                // verwenden, so dass die erste
+                                // Karte komplett angezeigt wird
+                                if (getMapArea() == null) {
+                                    Envelope newMapArea = new Envelope(e
+                                            .getLayer().getFeatureSource()
+                                            .getBounds());
+                                    // Kartenbereich um 10% vergroessern, damit
+                                    // z.B. auch ein Punkt-Layer, welches nur
+                                    // aus 2 Punnkten
+                                    // besteht, sichtbar ist (Punkte liegen
+                                    // sonst
+                                    // genau auf dem Rand der angezeigten
+                                    // Flaeche)
+                                    newMapArea.expandBy(
+                                            newMapArea.getWidth() * 0.1,
+                                            newMapArea.getHeight() * 0.1);
+                                    setMapArea(newMapArea);
+                                    // in layerAdded(.) der Oberklasse wird
+                                    // mapArea nochmal neu gesetzt, wenn das
+                                    // erste Layer
+                                    // eingefuegt wird
+                                    // >> hier nur die AreaOfInterest setzen
+                                    getContext().setAreaOfInterest(newMapArea,
+                                            crs);
+                                }
+                            } catch (Exception err) {
+                                LOGGER
+                                        .warn("CRS could not be determined from map layer. WGS84 used.");
+                                // err.printStackTrace();
+                                crs = DefaultGeographicCRS.WGS84;
+                            }
+                            // CRS dem MapContext zuweisen
+                            try {
+                                getContext().setCoordinateReferenceSystem(crs);
+                                LOGGER.debug("MapContext-CRS set to: "+crs);
+                            } catch (Exception err) {
+                                LOGGER
+                                        .error("CRS could not be assigned to map context.");
+                            }
+                        }
+                    }
+                });
+    }
 
-	/**
-	 * Get the BufferedImage to use as a flaoting icon in the lower right
-	 * corner.
-	 * 
-	 * @return <code>null</code> if the feature is deactivated.
-	 */
-	public BufferedImage getMapImage() {
-		return mapImage;
-	}
+    /**
+     * Get the BufferedImage to use as a flaoting icon in the lower right
+     * corner.
+     *
+     * @return <code>null</code> if the feature is deactivated.
+     */
+    public BufferedImage getMapImage() {
+        return mapImage;
+    }
 
-	/**
-	 * Set the BufferedImage to use as a flaoting icon in the lower right corner
-	 * 
-	 * @param mapImageIcon
-	 *            <code>null</code> is allowed and deactivates this icon.
-	 */
-	public void setMapImage(BufferedImage mapImage) {
-		this.mapImage = mapImage;
-	}
+    /**
+     * Set the BufferedImage to use as a flaoting icon in the lower right corner
+     *
+     * @param mapImageIcon
+     *            <code>null</code> is allowed and deactivates this icon.
+     */
+    public void setMapImage(BufferedImage mapImage) {
+        this.mapImage = mapImage;
+    }
 
-	/**
-	 * Gibt die optional gesetzte {@link Component} zurueck, deren Cursor auch
-	 * auf WAIT gesetzt werden soll
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 * 
-	 * @return null oder {@link Component}
-	 */
-	public Component getWaitCursorComponent() {
-		return mouseWaitCursorComponent;
-	}
+    /**
+     * Gibt die optional gesetzte {@link Component} zurueck, deren Cursor auch
+     * auf WAIT gesetzt werden soll
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     *
+     * @return null oder {@link Component}
+     */
+    public Component getWaitCursorComponent() {
+        return mouseWaitCursorComponent;
+    }
 
-	/**
-	 * Setzt eine Componente, deren Cursor zusaetzlich zu THIS noch auf WAIT
-	 * gesetzt wird falls durch dies ueberhaupt durch
-	 * setSetWaitCursorDuringNextRepaint(true) veranlasst wurde
-	 * 
-	 * @param parentComponent
-	 *            z.b. der Frame, der diese {@link JMapPane} enhaelt
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void setWaitCursorComponent(Component parentComponent) {
-		this.mouseWaitCursorComponent = parentComponent;
-	}
+    /**
+     * Setzt eine Componente, deren Cursor zusaetzlich zu THIS noch auf WAIT
+     * gesetzt wird falls durch dies ueberhaupt durch
+     * setSetWaitCursorDuringNextRepaint(true) veranlasst wurde
+     *
+     * @param parentComponent
+     *            z.b. der Frame, der diese {@link JMapPane} enhaelt
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void setWaitCursorComponent(Component parentComponent) {
+        this.mouseWaitCursorComponent = parentComponent;
+    }
 
-	/**
-	 * Aktualisiert die Karten-Anzeige vollstaendig. Ruft
-	 * {@link JMapPane#setReset(boolean) JMapPane#setReset(true)} auf und
-	 * anschliessend {@link #repaint()}.
-	 * 
-	 * <br>
-	 * SK: Der Mauszeiger wird waehrend des repaints auf WAIT gesetzt mittels
-	 * {@link #setWaitCursorDuringNextRepaint(boolean)}
-	 * 
-	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-	 *         (University of Bonn/Germany)
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void refresh() {
+    /**
+     * Aktualisiert die Karten-Anzeige vollstaendig. Ruft
+     * {@link JMapPane#setReset(boolean) JMapPane#setReset(true)} auf und
+     * anschliessend {@link #repaint()}.
+     *
+     * <br>
+     * SK: Der Mauszeiger wird waehrend des repaints auf WAIT gesetzt mittels
+     * {@link #setWaitCursorDuringNextRepaint(boolean)}
+     *
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     *         (University of Bonn/Germany)
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void refresh() {
 
-		// SK: Added by SK, 27.09.2007
-		// Durch den reset ist das repaint immer etwas aufwaendiger. Der Cursor
-		// wechselt dann auf WAIT
-		setWaitCursorDuringNextRepaint(true);
+        // SK: Added by SK, 27.09.2007
+        // Durch den reset ist das repaint immer etwas aufwaendiger. Der Cursor
+        // wechselt dann auf WAIT
+        setWaitCursorDuringNextRepaint(true);
 
-		setReset(true);
-		repaint();
-	}
+        setReset(true);
+        repaint();
+    }
 
-	/**
-	 * Aktiviert oder Deaktiviert das AntiAliasing for diese {@link JMapPane}.
-	 * AntiALiasing ist besonders fuer Textbeschriftung sehr schoen, verbraucht
-	 * aber auch mehr Performance.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void setAntiAliasing(final boolean aa) {
-		// LOGGER.info("Setting AntiAliasing for this JMapPane to " + aa);
-		RenderingHints java2DHints = getRenderer().getJava2DHints();
-		if (java2DHints == null)
-			java2DHints = GeoTools.getDefaultHints();
-		java2DHints.put(RenderingHints.KEY_ANTIALIASING,
-				aa ? RenderingHints.VALUE_ANTIALIAS_ON
-						: RenderingHints.VALUE_ANTIALIAS_OFF);
-		java2DHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
-				aa ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
-						: RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
-		java2DHints.put(RenderingHints.KEY_RENDERING,
-				aa ? RenderingHints.VALUE_RENDER_QUALITY
-						: RenderingHints.VALUE_RENDER_SPEED);
-		getRenderer().setJava2DHints(java2DHints);
-	}
+    /**
+     * Aktiviert oder Deaktiviert das AntiAliasing for diese {@link JMapPane}.
+     * AntiALiasing ist besonders fuer Textbeschriftung sehr schoen, verbraucht
+     * aber auch mehr Performance.
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void setAntiAliasing(final boolean aa) {
+        // LOGGER.info("Setting AntiAliasing for this JMapPane to " + aa);
+        RenderingHints java2DHints = getRenderer().getJava2DHints();
+        if (java2DHints == null)
+            java2DHints = GeoTools.getDefaultHints();
+        java2DHints.put(RenderingHints.KEY_ANTIALIASING,
+                aa ? RenderingHints.VALUE_ANTIALIAS_ON
+                        : RenderingHints.VALUE_ANTIALIAS_OFF);
+        java2DHints.put(RenderingHints.KEY_TEXT_ANTIALIASING,
+                aa ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
+                        : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+        java2DHints.put(RenderingHints.KEY_RENDERING,
+                aa ? RenderingHints.VALUE_RENDER_QUALITY
+                        : RenderingHints.VALUE_RENDER_SPEED);
+        getRenderer().setJava2DHints(java2DHints);
+    }
 
-	/**
-	 * Setzt den Kartenausschnitt auf die Ausdehnung eines bestimmten Layers.
-	 * Macht nichts, wenn {@code null} uebergeben wird.
-	 * 
-	 * <br>
-	 * A refresh of the map is NOT called.
-	 * 
-	 * @param layer
-	 *            ein Layer
-	 */
-	public void zoomToLayer(MapLayer layer) {
-		if (layer == null)
-			return;
-		// This action ususally takes some time..
-		setWaitCursorDuringNextRepaint = true;
-		try {
+    /**
+     * Setzt den Kartenausschnitt auf die Ausdehnung eines bestimmten Layers.
+     * Macht nichts, wenn {@code null} uebergeben wird.
+     *
+     * <br>
+     * A refresh of the map is NOT called.
+     *
+     * @param layer
+     *            ein Layer
+     */
+    public void zoomToLayer(MapLayer layer) {
+        if (layer == null)
+            return;
+        // This action ususally takes some time..
+        setWaitCursorDuringNextRepaint = true;
+        try {
 
-			// BB umrechnen von Layer-CRS in Map-CRS
-			final Envelope mapAreaNew = JTSUtil.transformEnvelope(layer
-					.getFeatureSource().getBounds(), layer.getFeatureSource()
-					.getSchema().getDefaultGeometry().getCoordinateSystem(),
-					getContext().getCoordinateReferenceSystem());
-			// Kartenbereich um 10% vergroessern, damit z.B. auch ein
-			// Punkt-Layer,
-			// welches nur aus 2 Punnkten besteht, sichtbar ist (Punkte liegen
-			// sonst
-			// genau auf dem Rand der angezeigten Flaeche)
-			mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1, mapAreaNew
-					.getHeight() * 0.1);
-			setMapArea(mapAreaNew);
-		} catch (Exception err) {
-			LOGGER.warn("Zoom to layer did not terminate correctly", err);
-		}
-	}
+            // BB umrechnen von Layer-CRS in Map-CRS
+            final Envelope mapAreaNew = JTSUtil.transformEnvelope(layer
+                    .getFeatureSource().getBounds(), layer.getFeatureSource()
+                    .getSchema().getDefaultGeometry().getCoordinateSystem(),
+                    getContext().getCoordinateReferenceSystem());
+            // Kartenbereich um 10% vergroessern, damit z.B. auch ein
+            // Punkt-Layer,
+            // welches nur aus 2 Punnkten besteht, sichtbar ist (Punkte liegen
+            // sonst
+            // genau auf dem Rand der angezeigten Flaeche)
+            mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1, mapAreaNew
+                    .getHeight() * 0.1);
+            setMapArea(mapAreaNew);
+        } catch (Exception err) {
+            LOGGER.warn("Zoom to layer did not terminate correctly", err);
+        }
+    }
 
-	/**
-	 * Zooms the {@link JMapPane} to the {@link Envelope} of a layer.
-	 * 
-	 * <br>
-	 * A refresh of the map is not done automatically
-	 * 
-	 * @param index
-	 *            Index of the {@link MapLayer} in the {@link MapContext} (from
-	 *            back to top)
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void zoomToLayer(int index) {
-		final MapContext context = getContext();
-		if (context != null)
-			zoomToLayer(context.getLayer(index));
-	}
+    /**
+     * Zooms the {@link JMapPane} to the {@link Envelope} of a layer.
+     *
+     * <br>
+     * A refresh of the map is not done automatically
+     *
+     * @param index
+     *            Index of the {@link MapLayer} in the {@link MapContext} (from
+     *            back to top)
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void zoomToLayer(int index) {
+        final MapContext context = getContext();
+        if (context != null)
+            zoomToLayer(context.getLayer(index));
+    }
 
-	/**
-	 * Zooms the {@link JMapPane} to the {@link Envelope} of the selected layer.
-	 * The layer is selected by the idx, counting from front to back, like
-	 * humans would expect in a {@link JList}
-	 * 
-	 * <br>
-	 * A refresh of the map is not done automatically
-	 * 
-	 * 
-	 * 
-	 * @param index
-	 *            Reverse index of the {@link MapLayer} in the
-	 *            {@link MapContext}
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void zoomToLayerIdxReverse(int index) {
-		zoomToLayer(getContext().getLayerCount() - 1 - index);
-	}
+    /**
+     * Zooms the {@link JMapPane} to the {@link Envelope} of the selected layer.
+     * The layer is selected by the idx, counting from front to back, like
+     * humans would expect in a {@link JList}
+     *
+     * <br>
+     * A refresh of the map is not done automatically
+     *
+     *
+     *
+     * @param index
+     *            Reverse index of the {@link MapLayer} in the
+     *            {@link MapContext}
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void zoomToLayerIdxReverse(int index) {
+        zoomToLayer(getContext().getLayerCount() - 1 - index);
+    }
 
-	/**
-	 * Liefert die Anzahl der Einheiten, die ein Bildschirm-Pixel darstellt. Die
-	 * Einheit ist die Grundeinheit des CRS
-	 */
-	public double getScale() {
-		if (getWidth() == 0 || getMapArea() == null)
-			return 0.0;
-		return getMapArea().getWidth() / getWidth();
-	}
+    /**
+     * Liefert die Anzahl der Einheiten, die ein Bildschirm-Pixel darstellt. Die
+     * Einheit ist die Grundeinheit des CRS
+     */
+    public double getScale() {
+        if (getWidth() == 0 || getMapArea() == null)
+            return 0.0;
+        return getMapArea().getWidth() / getWidth();
+    }
 
-	/**
-	 * Liefert oberste Layer (sichtbar oder unsichtbar).
-	 */
-	public MapLayer getTopLayer() {
-		int count = getContext().getLayerCount();
-		return count > 0 ? getContext().getLayer(count - 1) : null;
-	}
+    /**
+     * Liefert oberste Layer (sichtbar oder unsichtbar).
+     */
+    public MapLayer getTopLayer() {
+        int count = getContext().getLayerCount();
+        return count > 0 ? getContext().getLayer(count - 1) : null;
+    }
 
-	/**
-	 * Liefert oberste sichtbare Layer.
-	 */
-	public MapLayer getTopVisibleLayer() {
-		for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
-			MapLayer layer = getContext().getLayer(i);
-			if (layer.isVisible())
-				return layer;
-		}
-		return null;
-	}
+    /**
+     * Liefert oberste sichtbare Layer.
+     */
+    public MapLayer getTopVisibleLayer() {
+        for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
+            MapLayer layer = getContext().getLayer(i);
+            if (layer.isVisible())
+                return layer;
+        }
+        return null;
+    }
 
-	/**
-	 * Liefert oberste sichtbare Raster-Layer.
-	 */
-	public MapLayer getTopVisibleGridCoverageLayer() {
-		for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
-			MapLayer layer = getContext().getLayer(i);
-			if (layer.isVisible() && isGridCoverageLayer(layer))
-				return layer;
-		}
-		return null;
-	}
+    /**
+     * Liefert oberste sichtbare Raster-Layer.
+     */
+    public MapLayer getTopVisibleGridCoverageLayer() {
+        for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
+            MapLayer layer = getContext().getLayer(i);
+            if (layer.isVisible() && isGridCoverageLayer(layer))
+                return layer;
+        }
+        return null;
+    }
 
-	/**
-	 * Liefert oberste sichtbare Nicht-Raster-Layer.
-	 */
-	public MapLayer getTopVisibleNonGridCoverageLayer() {
-		for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
-			MapLayer layer = getContext().getLayer(i);
-			if (layer.isVisible() && !isGridCoverageLayer(layer))
-				return layer;
-		}
-		return null;
-	}
+    /**
+     * Liefert oberste sichtbare Nicht-Raster-Layer.
+     */
+    public MapLayer getTopVisibleNonGridCoverageLayer() {
+        for (int i = getContext().getLayerCount() - 1; i >= 0; i--) {
+            MapLayer layer = getContext().getLayer(i);
+            if (layer.isVisible() && !isGridCoverageLayer(layer))
+                return layer;
+        }
+        return null;
+    }
 
-	/**
-	 * Liefert unterste Layer (sichtbar oder unsichtbar).
-	 */
-	public MapLayer getBottomLayer() {
-		return getContext().getLayerCount() > 0 ? getContext().getLayer(0)
-				: null;
-	}
+    /**
+     * Liefert unterste Layer (sichtbar oder unsichtbar).
+     */
+    public MapLayer getBottomLayer() {
+        return getContext().getLayerCount() > 0 ? getContext().getLayer(0)
+                : null;
+    }
 
-	/**
-	 * Setzt den Modus fuer Window-Selektion. Default ist {@link #ZOOM_IN}.
-	 * 
-	 * 
-	 * <ul>
-	 * <li>{@link #ZOOM_IN}: Zoom auf selektierten Bereich</li>
-	 * <li>{@link #SELECT_TOP}: Auswahl der Features im selektierten Bereich des
-	 * <b>obersten</b> (sichtbaren) Layers</li>
-	 * <li>{@link #SELECT_ALL} Auswahl der Features im selektierten ueber alle
-	 * Layer</li>
-	 * <li>{@link #NONE} Nichts machen</li>
-	 * </ul>
-	 * 
-	 * @param newSelState
-	 *            Modus fuer Window-Selektion
-	 */
-	public void setWindowSelectionState(final int newSelState) {
-		if (newSelState != NONE && newSelState != ZOOM_IN
-				&& newSelState != SELECT_TOP && newSelState != SELECT_ALL
-				&& newSelState != SELECT_ONE_FROM_TOP)
-			throw new IllegalArgumentException(
-					"Unknown selection state for window selection!");
+    /**
+     * Setzt den Modus fuer Window-Selektion. Default ist {@link #ZOOM_IN}.
+     *
+     *
+     * <ul>
+     * <li>{@link #ZOOM_IN}: Zoom auf selektierten Bereich</li>
+     * <li>{@link #SELECT_TOP}: Auswahl der Features im selektierten Bereich des
+     * <b>obersten</b> (sichtbaren) Layers</li>
+     * <li>{@link #SELECT_ALL} Auswahl der Features im selektierten ueber alle
+     * Layer</li>
+     * <li>{@link #NONE} Nichts machen</li>
+     * </ul>
+     *
+     * @param newSelState
+     *            Modus fuer Window-Selektion
+     */
+    public void setWindowSelectionState(final int newSelState) {
+        if (newSelState != NONE && newSelState != ZOOM_IN
+                && newSelState != SELECT_TOP && newSelState != SELECT_ALL
+                && newSelState != SELECT_ONE_FROM_TOP)
+            throw new IllegalArgumentException(
+                    "Unknown selection state for window selection!");
 
-		// MS (2009-13-05): noch buggy -> wieder reingenommen (Probleme mit
-		// mehreren parallelen Mouse(Motion)Listenern
-		// MS (13.05.2009): Wird durch Ueberschreiben von mouseDragged(.) des
-		// MouseSelectionTracker realisiert
-		// Den selTracker bei Wechsel zu NONE deaktivieren (SK), damit
-		// Selektionsfenster beim Draggen nicht mehr gezeichnet wird
-		if ((newSelState == NONE) && (selState != NONE)) {
-			this.removeMouseListener(selTracker);
-		} else
-		// Den selTracker bei Wechsel von NONE aktivieren (SK)
-		if ((newSelState != NONE) && (selState == NONE)) {
-			this.addMouseListener(selTracker);
-		}
+        // Den selTracker bei Wechsel zu NONE deaktivieren (SK), damit
+        // Selektionsfenster beim Draggen nicht mehr gezeichnet wird
+        if ((newSelState == NONE) && (selState != NONE)) {
+            this.removeMouseListener(selTracker);
+        } else
+        // Den selTracker bei Wechsel von NONE aktivieren (SK)
+        if ((newSelState != NONE) && (selState == NONE)) {
+            this.addMouseListener(selTracker);
+        }
 
-		this.selState = newSelState;
+        this.selState = newSelState;
 
-		// Je nach Aktion den Cursor umsetzen
-		updateCursor();
-	}
+        // Je nach Aktion den Cursor umsetzen
+        updateCursor();
+    }
 
-	/**
-	 * Standardmaessig wird der Cursor automatisch je nach MapPane-Aktion (Zoom,
-	 * Auswahl, ...) gesetzt. Mit dieser Methode kann ein statischer Cursor
-	 * gesetzt werden, der unabhaengig von der aktuellen MapPanes-Aktion
-	 * beibehalten wird. Um diesen statischen Cursor wieder zu entfernen, kann
-	 * {@code null} als Parameter uebergeben werden
-	 * 
-	 * @param cursor
-	 *            Cursor
-	 */
-	public void setStaticCursor(Cursor cursor) {
-		this.staticCursor = cursor;
-		if (cursor != null)
-			super.setCursor(cursor);
-	}
+    /**
+     * Standardmaessig wird der Cursor automatisch je nach MapPane-Aktion (Zoom,
+     * Auswahl, ...) gesetzt. Mit dieser Methode kann ein statischer Cursor
+     * gesetzt werden, der unabhaengig von der aktuellen MapPanes-Aktion
+     * beibehalten wird. Um diesen statischen Cursor wieder zu entfernen, kann
+     * {@code null} als Parameter uebergeben werden
+     *
+     * @param cursor
+     *            Cursor
+     */
+    public void setStaticCursor(Cursor cursor) {
+        this.staticCursor = cursor;
+        if (cursor != null)
+            super.setCursor(cursor);
+    }
 
-	/**
-	 * Liefert den statisch eingestellten Cursor, der unabhaengig von der
-	 * eingestellten MapPane-Aktion (Zoom, Auswahl, ...) verwendet wird.
-	 * 
-	 * @return {@code null}, wenn kein statischer Cursor verwendet, sondern der
-	 *         Cursor automatisch je nach MapPane-Aktion eingestellt wird.
-	 */
-	public Cursor getStaticCursor() {
-		return this.staticCursor;
-	}
+    /**
+     * Liefert den statisch eingestellten Cursor, der unabhaengig von der
+     * eingestellten MapPane-Aktion (Zoom, Auswahl, ...) verwendet wird.
+     *
+     * @return {@code null}, wenn kein statischer Cursor verwendet, sondern der
+     *         Cursor automatisch je nach MapPane-Aktion eingestellt wird.
+     */
+    public Cursor getStaticCursor() {
+        return this.staticCursor;
+    }
 
-	/**
-	 * Abhaengig von selState wird der Cursor gesetzt
-	 */
-	public void updateCursor() {
-		// wenn manueller Cursor gesetzt ist, dann diesen verwenden (unabhaengig
-		// von der aktuellen Aktion
-		if (this.staticCursor != null) {
-			setCursor(staticCursor);
-			return;
-		}
-		// Je nach Aktion den Cursor umsetzen
-		switch (this.selState) {
-		case SELECT_TOP:
-		case SELECT_ONE_FROM_TOP:
-		case SELECT_ALL:
-			setCursor(SwingUtil.CROSSHAIR_CURSOR);
-			break;
-		case ZOOM_IN:
-			setCursor(SwingUtil.ZOOMIN_CURSOR);
-			break;
-		case ZOOM_OUT:
-			setCursor(SwingUtil.ZOOMOUT_CURSOR);
-			break;
-		default:
-			setCursor(getNormalCursor());
-			break;
-		}
-	}
+    /**
+     * Abhaengig von selState wird der Cursor gesetzt
+     */
+    public void updateCursor() {
+        // wenn manueller Cursor gesetzt ist, dann diesen verwenden (unabhaengig
+        // von der aktuellen Aktion
+        if (this.staticCursor != null) {
+            setCursor(staticCursor);
+            return;
+        }
+        // Je nach Aktion den Cursor umsetzen
+        switch (this.selState) {
+        case SELECT_TOP:
+        case SELECT_ONE_FROM_TOP:
+        case SELECT_ALL:
+            setCursor(SwingUtil.CROSSHAIR_CURSOR);
+            break;
+        case ZOOM_IN:
+            setCursor(SwingUtil.ZOOMIN_CURSOR);
+            break;
+        case ZOOM_OUT:
+            setCursor(SwingUtil.ZOOMOUT_CURSOR);
+            break;
+        default:
+            setCursor(getNormalCursor());
+            break;
+        }
+    }
 
-	/**
-	 * Liefert den Modus fuer Window-Selektion.
-	 * 
-	 * @see #setWindowSelectionState(int)
-	 */
-	public int getWindowSelectionState() {
-		return this.selState;
-	}
+    /**
+     * Liefert den Modus fuer Window-Selektion.
+     *
+     * @see #setWindowSelectionState(int)
+     */
+    public int getWindowSelectionState() {
+        return this.selState;
+    }
 
-	/**
-	 * Fuegt der Map einen Listener hinzu.
-	 * 
-	 * @param l
-	 *            neuer Listener
-	 */
-	public void addMapPaneListener(JMapPaneListener l) {
-		mapPaneListeners.add(l);
-	}
+    /**
+     * Fuegt der Map einen Listener hinzu.
+     *
+     * @param l
+     *            neuer Listener
+     */
+    public void addMapPaneListener(JMapPaneListener l) {
+        mapPaneListeners.add(l);
+    }
 
-	/**
-	 * Entfernt einen Listener von der Map.
-	 * 
-	 * @param l
-	 *            zu entfernender Listener
-	 */
-	public void removeMapPaneListener(JMapPaneListener l) {
-		mapPaneListeners.remove(l);
-	}
+    /**
+     * Entfernt einen Listener von der Map.
+     *
+     * @param l
+     *            zu entfernender Listener
+     */
+    public void removeMapPaneListener(JMapPaneListener l) {
+        mapPaneListeners.remove(l);
+    }
 
-	/**
-	 * Propagiert ein Ereignis an alle angeschlossenen Listener.
-	 * 
-	 * @param e
-	 *            Ereignis
-	 */
-	protected void fireMapPaneEvent(JMapPaneEvent e) {
-		for (JMapPaneListener l : mapPaneListeners)
-			l.performMapPaneEvent(e);
-	}
+    /**
+     * Propagiert ein Ereignis an alle angeschlossenen Listener.
+     *
+     * @param e
+     *            Ereignis
+     */
+    protected void fireMapPaneEvent(JMapPaneEvent e) {
+        for (JMapPaneListener l : mapPaneListeners)
+            l.performMapPaneEvent(e);
+    }
 
-	/**
-	 * Konvertiert die Maus-Koordinaten (relativ zum <code>JMapPane</code>) in
-	 * Karten-Koordinaten.
-	 * 
-	 * @param e
-	 *            Maus-Ereignis
-	 */
-	public static Point2D getMapCoordinatesFromEvent(MouseEvent e) {
-		// aktuelle Geo-Position aus GeoMouseEvent ermitteln
-		if (e != null && e instanceof GeoMouseEvent)
-			try {
-				return ((GeoMouseEvent) e).getMapCoordinate(null).toPoint2D();
-			} catch (Exception err) {
-				err.printStackTrace();
-			}
+    /**
+     * Konvertiert die Maus-Koordinaten (relativ zum <code>JMapPane</code>) in
+     * Karten-Koordinaten.
+     *
+     * @param e
+     *            Maus-Ereignis
+     */
+    public static Point2D getMapCoordinatesFromEvent(MouseEvent e) {
+        // aktuelle Geo-Position aus GeoMouseEvent ermitteln
+        if (e != null && e instanceof GeoMouseEvent)
+            try {
+                return ((GeoMouseEvent) e).getMapCoordinate(null).toPoint2D();
+            } catch (Exception err) {
+                err.printStackTrace();
+            }
 
-		// aktuelle Geo-Position ueber Transformation des JMapPane berechnen
-		if (e != null && e.getSource() instanceof JMapPane) {
-			AffineTransform at = ((JMapPane) e.getSource()).getTransform();
-			if (at != null)
-				return at.transform(e.getPoint(), null);
-		}
+        // aktuelle Geo-Position ueber Transformation des JMapPane berechnen
+        if (e != null && e.getSource() instanceof JMapPane) {
+            AffineTransform at = ((JMapPane) e.getSource()).getTransform();
+            if (at != null)
+                return at.transform(e.getPoint(), null);
+        }
 
-		return null;
-	}
+        return null;
+    }
 
-	/**
-	 * Verarbeitet die Selektion eines Karten-Ausschnitts. Erzeugt immer ein
-	 * {@link GeneralSelectionEvent} fuer den ausgewaehlten Bereich. Wurden
-	 * Features oder Raster selektiert, werden zudem
-	 * {@link FeatureSelectedEvent FeatureSelectedEvents} (bzw.
-	 * GridCoverageSelectedEvents GridCoverageSelectedEvents) ausgeloest.
-	 * 
-	 * @param ox
-	 *            X-Koordinate der VON-Position
-	 * @param oy
-	 *            Y-Koordinate der VON-Position
-	 * @param px
-	 *            X-Koordinate der BIS-Position
-	 * @param py
-	 *            Y-Koordinate der BIS-Position
-	 */
-	protected void performSelectionEvent(int ox, int oy, int px, int py) {
-		if (getContext().getLayerCount() == 0)
-			return;
+    /**
+     * Verarbeitet die Selektion eines Karten-Ausschnitts. Erzeugt immer ein
+     * {@link GeneralSelectionEvent} fuer den ausgewaehlten Bereich. Wurden
+     * Features oder Raster selektiert, werden zudem
+     * {@link FeatureSelectedEvent FeatureSelectedEvents} (bzw.
+     * GridCoverageSelectedEvents GridCoverageSelectedEvents) ausgeloest.
+     *
+     * @param ox
+     *            X-Koordinate der VON-Position
+     * @param oy
+     *            Y-Koordinate der VON-Position
+     * @param px
+     *            X-Koordinate der BIS-Position
+     * @param py
+     *            Y-Koordinate der BIS-Position
+     */
+    protected void performSelectionEvent(int ox, int oy, int px, int py) {
+        if (getContext().getLayerCount() == 0)
+            return;
 
-		// keine wirkliche Selektion, sondern nur ein Klick
-		if (ox == px || oy == py)
-			return;
+        // keine wirkliche Selektion, sondern nur ein Klick
+        if (ox == px || oy == py)
+            return;
 
-		// Fenster-Koordinaten in Map-Koordinaten umwandeln
-		Envelope env = tranformWindowToGeo(ox, oy, px, py);
+        // Fenster-Koordinaten in Map-Koordinaten umwandeln
+        Envelope env = tranformWindowToGeo(ox, oy, px, py);
 
-		// Generelles Event ausloesen
-		fireMapPaneEvent(new GeneralSelectionEvent(this, env));
+        // Generelles Event ausloesen
+        fireMapPaneEvent(new GeneralSelectionEvent(this, env));
 
-		int selectState = getWindowSelectionState();
-		switch (selectState) {
-		case ZOOM_IN: // Karte neu setzen
-			this.setMapArea(env);
-			refresh(); // WICHTIG!! Damit die veraenderte Form beruecksichtigt
-			// wird!?
-			break;
-		case SELECT_TOP:
-		case SELECT_ONE_FROM_TOP:
-		case SELECT_ALL: // Features selektieren
-			boolean featuresFound = findFeaturesAndFireEvents(
-					createBoundingBoxFilter(env), selectState, env);
-			if (selectState == SELECT_ALL || !featuresFound)
-				findGridCoverageSubsetsAndFireEvents(env, selectState);
-			break;
-		}
-	}
+        int selectState = getWindowSelectionState();
+        switch (selectState) {
+        case ZOOM_IN: // Karte neu setzen
+            this.setMapArea(env);
+            refresh(); // WICHTIG!! Damit die veraenderte Form beruecksichtigt
+            // wird!?
+            break;
+        case SELECT_TOP:
+        case SELECT_ONE_FROM_TOP:
+        case SELECT_ALL: // Features selektieren
+            boolean featuresFound = findFeaturesAndFireEvents(
+                                      new BoundingBoxFilterGenerator(env,getContext().getCoordinateReferenceSystem()),
+                                      selectState,
+                                      env
+            );
+            if (selectState == SELECT_ALL || !featuresFound)
+                findGridCoverageSubsetsAndFireEvents(env, selectState);
+            break;
+        }
+    }
 
-	/**
-	 * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
-	 * 
-	 * @param e
-	 *            Mausrad-Event
-	 */
-	protected void performMouseWheelEvent(MouseWheelEvent e) {
-		if (getContext().getLayerCount() == 0)
-			return;
+    /**
+     * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
+     *
+     * @param e
+     *            Mausrad-Event
+     */
+    protected void performMouseWheelEvent(MouseWheelEvent e) {
+        if (getContext().getLayerCount() == 0)
+            return;
 
-		int units = e.getUnitsToScroll();
-		// Positiver Wert --> Zoom in --> Faktor < 1
-		// Negativer Wert --> Zoom out --> Faktir > 1
+        int units = e.getUnitsToScroll();
+        // Positiver Wert --> Zoom in --> Faktor < 1
+        // Negativer Wert --> Zoom out --> Faktir > 1
 
-		// SK: 9.9.2007 zoom jetzt wie bei GoogleEarth
-		double zFactor = units > 0 ? 1.3 : 1 / 1.3;
-		// vorher double zFactor = units > 0 ? 1/1.2 : 1.2;
+        // SK: 9.9.2007 zoom jetzt wie bei GoogleEarth
+        double zFactor = units > 0 ? 1.3 : 1 / 1.3;
+        // vorher double zFactor = units > 0 ? 1/1.2 : 1.2;
 
-		// Fenster-Koordinaten zu Karten-Koordinaten transformieren
-		Point2D mapCoord = getTransform().transform(e.getPoint(), null);
-		// Relative Position des Mauszeigers zum Kartenausschnitt
-		// -> Nach Zoom soll dieselbe Kartenposition unterhalb des Mauszeigers
-		// erscheinen, wie vor dem Zoom
-		double relX = (mapCoord.getX() - getMapArea().getMinX())
-				/ getMapArea().getWidth();
-		double relY = (mapCoord.getY() - getMapArea().getMinY())
-				/ getMapArea().getHeight();
+        // Fenster-Koordinaten zu Karten-Koordinaten transformieren
+        Point2D mapCoord = getTransform().transform(e.getPoint(), null);
+        // Relative Position des Mauszeigers zum Kartenausschnitt
+        // -> Nach Zoom soll dieselbe Kartenposition unterhalb des Mauszeigers
+        // erscheinen, wie vor dem Zoom
+        double relX = (mapCoord.getX() - getMapArea().getMinX())
+                / getMapArea().getWidth();
+        double relY = (mapCoord.getY() - getMapArea().getMinY())
+                / getMapArea().getHeight();
 
-		// Neuen Karten-Ausschnitt berechnen
-		Coordinate ll = new Coordinate(mapCoord.getX()
-				- getMapArea().getWidth() * relX * zFactor, mapCoord.getY()
-				- getMapArea().getHeight() * relY * zFactor);
-		Coordinate ur = new Coordinate(mapCoord.getX()
-				+ getMapArea().getWidth() * (1 - relX) * zFactor, mapCoord
-				.getY()
-				+ getMapArea().getHeight() * (1 - relY) * zFactor);
-		setMapArea(new Envelope(ll, ur));
+        // Neuen Karten-Ausschnitt berechnen
+        Coordinate ll = new Coordinate(mapCoord.getX()
+                - getMapArea().getWidth() * relX * zFactor, mapCoord.getY()
+                - getMapArea().getHeight() * relY * zFactor);
+        Coordinate ur = new Coordinate(mapCoord.getX()
+                + getMapArea().getWidth() * (1 - relX) * zFactor, mapCoord
+                .getY()
+                + getMapArea().getHeight() * (1 - relY) * zFactor);
+        setMapArea(new Envelope(ll, ur));
 
-		setWaitCursorDuringNextRepaint(true);
-		repaint();
-	}
+        setWaitCursorDuringNextRepaint(true);
+        repaint();
+    }
 
-	/**
-	 * Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten.
-	 * 
-	 * @param ox
-	 *            X-Koordinate der VON-Position
-	 * @param oy
-	 *            Y-Koordinate der VON-Position
-	 * @param px
-	 *            X-Koordinate der BIS-Position
-	 * @param py
-	 *            Y-Koordinate der BIS-Position
-	 */
-	public Envelope tranformWindowToGeo(int ox, int oy, int px, int py) {
-		AffineTransform at = getTransform();
-		Point2D geoO = at.transform(new Point2D.Double(ox, oy), null);
-		Point2D geoP = at.transform(new Point2D.Double(px, py), null);
-		return new Envelope(geoO.getX(), geoP.getX(), geoO.getY(), geoP.getY());
-	}
+    /**
+     * Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten.
+     *
+     * @param ox
+     *            X-Koordinate der VON-Position
+     * @param oy
+     *            Y-Koordinate der VON-Position
+     * @param px
+     *            X-Koordinate der BIS-Position
+     * @param py
+     *            Y-Koordinate der BIS-Position
+     */
+    public Envelope tranformWindowToGeo(int ox, int oy, int px, int py) {
+        AffineTransform at = getTransform();
+        Point2D geoO = at.transform(new Point2D.Double(ox, oy), null);
+        Point2D geoP = at.transform(new Point2D.Double(px, py), null);
+        return new Envelope(geoO.getX(), geoP.getX(), geoO.getY(), geoP.getY());
+    }
 
-	/**
-	 * Transformiert eine Fenster-Koordinate in eine Geo-Koordinate.
-	 * 
-	 * @param x
-	 *            X-Koordinate
-	 * @param y
-	 *            Y-Koordinate
-	 */
-	public Point2D tranformWindowToGeo(int x, int y) {
-		AffineTransform at = getTransform();
-		return at.transform(new Point2D.Double(x, y), null);
-	}
+    /**
+     * Transformiert eine Fenster-Koordinate in eine Geo-Koordinate.
+     *
+     * @param x
+     *            X-Koordinate
+     * @param y
+     *            Y-Koordinate
+     */
+    public Point2D tranformWindowToGeo(int x, int y) {
+        AffineTransform at = getTransform();
+        return at.transform(new Point2D.Double(x, y), null);
+    }
 
-	/**
-	 * Berechnet die Transformation zwischen Fenster- und Karten-Koordinaten
-	 * neu.
-	 */
-	protected void resetTransform() {
-		if (getMapArea() == null || getWidth() == 0 || getHeight() == 0)
-			return;
-		this.transform = new AffineTransform(
-		// Genauso wie die Fenster-Koordinaten, werden die Longitude-Koordinaten
-				// nach rechts (Osten) hin groesser
-				// --> positive Verschiebung
-				getMapArea().getWidth() / getWidth(),
-				// keine Verzerrung
-				0.0, 0.0,
-				// Waehrend die Fenster-Koordinaten nach unten hin groesser
-				// werden,
-				// werden Latitude-Koordinaten nach Sueden hin keiner
-				// --> negative Verschiebung
-				-getMapArea().getHeight() / getHeight(),
-				// Die Longitude-Koordinaten werden nach Osten hin groesser
-				// --> obere linke Ecke des Fensters hat also den Minimalwert
-				getMapArea().getMinX(),
-				// Die Latitude-Koordinaten werden nach Norden hin groesser
-				// --> obere linke Ecke des Fensters hat also den Maximalwert
-				getMapArea().getMaxY());
-	}
+    /**
+     * Berechnet die Transformation zwischen Fenster- und Karten-Koordinaten
+     * neu.
+     */
+    protected void resetTransform() {
+        if (getMapArea() == null || getWidth() == 0 || getHeight() == 0)
+            return;
+        this.transform = new AffineTransform(
+        // Genauso wie die Fenster-Koordinaten, werden die Longitude-Koordinaten
+                // nach rechts (Osten) hin groesser
+                // --> positive Verschiebung
+                getMapArea().getWidth() / getWidth(),
+                // keine Verzerrung
+                0.0, 0.0,
+                // Waehrend die Fenster-Koordinaten nach unten hin groesser
+                // werden,
+                // werden Latitude-Koordinaten nach Sueden hin keiner
+                // --> negative Verschiebung
+                -getMapArea().getHeight() / getHeight(),
+                // Die Longitude-Koordinaten werden nach Osten hin groesser
+                // --> obere linke Ecke des Fensters hat also den Minimalwert
+                getMapArea().getMinX(),
+                // Die Latitude-Koordinaten werden nach Norden hin groesser
+                // --> obere linke Ecke des Fensters hat also den Maximalwert
+                getMapArea().getMaxY());
+    }
 
-	/**
-	 * Liefert eine affine Transformation, um von den Fenster-Koordinaten in die
-	 * Karten-Koordinaten (Lat/Lon) umzurechnen.
-	 * 
-	 * @return eine Kopie der aktuellen Transformation; <code>null</code> wenn
-	 *         noch keine Karte angezeigt wird
-	 */
-	public AffineTransform getTransform() {
-		// Workaround: Obwohl eine Karte gesetzt ist, kann es sein, dass die
-		// Transformation noch nicht gesetzt ist (da noch kein
-		// setMapArea(.)-Aufruf stattgefunden hat!)
-		if (transform == null)
-			resetTransform();
-		// nur Kopie der Transformation zurueckgeben!
-		if (transform != null)
-			return new AffineTransform(transform);
-		return null;
-	}
+    /**
+     * Liefert eine affine Transformation, um von den Fenster-Koordinaten in die
+     * Karten-Koordinaten (Lat/Lon) umzurechnen.
+     *
+     * @return eine Kopie der aktuellen Transformation; <code>null</code> wenn
+     *         noch keine Karte angezeigt wird
+     */
+    public AffineTransform getTransform() {
+        // Workaround: Obwohl eine Karte gesetzt ist, kann es sein, dass die
+        // Transformation noch nicht gesetzt ist (da noch kein
+        // setMapArea(.)-Aufruf stattgefunden hat!)
+        if (transform == null)
+            resetTransform();
+        // nur Kopie der Transformation zurueckgeben!
+        if (transform != null)
+            return new AffineTransform(transform);
+        return null;
+    }
 
-	/**
-	 * Setzt die sichtbare Karte. Danach wird die {@linkplain AffineTransform
-	 * Transformation} zwischen Fenster-Koordinaten und Karten-Koordinaten neu
-	 * berechnet.<br>
-	 * Loest ein {@link ScaleChangedEvent aus}
-	 * 
-	 * {@link #setMapArea(Envelope)} wird ignoriert, falls durch die neue
-	 * MapArea ein nicht gueltiger Massstab entstehen wuerde UND die bisherige
-	 * maparea != null ist
-	 * 
-	 * @param env
-	 *            neuer Kartenausschnitt
-	 * @see #resetTransform()
-	 * @see #getTransform()
-	 * 
-	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-	 *         (University of Bonn/Germany)
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	@Override
-	public void setMapArea(Envelope env) {
-		// **********************************************************************
-		// Ueber die Funktionen setMaxZoomScale und setMinZoomScale kann der
-		// geotools JMapPane ein gueltiger Massstabsbereich gesetzt werden.
-		// Dieser
-		// wird hier ueberprueft. (SK)
-		// **********************************************************************
-		if (super.getMapArea() != null) {
-			env = bestAllowedMapArea(env);
-		}
+    /**
+     * Setzt die sichtbare Karte. Danach wird die {@linkplain AffineTransform
+     * Transformation} zwischen Fenster-Koordinaten und Karten-Koordinaten neu
+     * berechnet.<br>
+     * Loest ein {@link ScaleChangedEvent aus}
+     *
+     * {@link #setMapArea(Envelope)} wird ignoriert, falls durch die neue
+     * MapArea ein nicht gueltiger Massstab entstehen wuerde UND die bisherige
+     * maparea != null ist
+     *
+     * @param env
+     *            neuer Kartenausschnitt
+     * @see #resetTransform()
+     * @see #getTransform()
+     *
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     *         (University of Bonn/Germany)
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    @Override
+    public void setMapArea(Envelope env) {
+        // **********************************************************************
+        // Ueber die Funktionen setMaxZoomScale und setMinZoomScale kann der
+        // geotools JMapPane ein gueltiger Massstabsbereich gesetzt werden.
+        // Dieser
+        // wird hier ueberprueft. (SK)
+        // **********************************************************************
+        if (super.getMapArea() != null) {
+            env = bestAllowedMapArea(env);
+        }
 
-		double oldScale = getScale();
-		Envelope oldEnv = getMapArea();
+        double oldScale = getScale();
+        Envelope oldEnv = getMapArea();
 
-		super.setMapArea(env);
+        super.setMapArea(env);
 
-		resetTransform();
-		double newScale = getScale();
-		Envelope newEnv = getMapArea();
+        resetTransform();
+        double newScale = getScale();
+        Envelope newEnv = getMapArea();
 
-		if (oldScale != newScale)
-			fireMapPaneEvent(new ScaleChangedEvent(this, oldScale, newScale));
-		if (oldEnv == null && newEnv != null || oldEnv != null
-				&& !oldEnv.equals(newEnv))
-			fireMapPaneEvent(new MapAreaChangedEvent(this, oldEnv, newEnv));
-	}
+        if (oldScale != newScale)
+            fireMapPaneEvent(new ScaleChangedEvent(this, oldScale, newScale));
+        if (oldEnv == null && newEnv != null || oldEnv != null
+                && !oldEnv.equals(newEnv))
+            fireMapPaneEvent(new MapAreaChangedEvent(this, oldEnv, newEnv));
+    }
 
-	/**
-	 * Reagiert auf Linksklick mit der ueber {@link #setState(int)}eingestellten
-	 * Aktion und auf Rechtsklick mit Zoom-Out (sofern {@link #ZOOM_IN}-State
-	 * fuer Linksklick eingestellt). Alle anderen Klicks werden ignoriert.
-	 * 
-	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-	 *         (University of Bonn/Germany)
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void mouseClicked(MouseEvent e) {
-		// wenn noch kein Layer dargestellt wird, nichts machen
-		if (getContext().getLayerCount() == 0)
-			return;
+    /**
+     * Reagiert auf Linksklick mit der ueber {@link #setState(int)}eingestellten
+     * Aktion und auf Rechtsklick mit Zoom-Out (sofern {@link #ZOOM_IN}-State
+     * fuer Linksklick eingestellt). Alle anderen Klicks werden ignoriert.
+     *
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     *         (University of Bonn/Germany)
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void mouseClicked(MouseEvent e) {
+        // wenn noch kein Layer dargestellt wird, nichts machen
+        if (getContext().getLayerCount() == 0)
+            return;
 
-		// double oldScale = getScale();
-		// Envelope oldEnv = getMapArea();
+        // double oldScale = getScale();
+        // Envelope oldEnv = getMapArea();
 
-		switch (e.getButton()) {
-		// Linksklick --> Eingestellte Funktion
-		case MouseEvent.BUTTON1: // Feature-Auswahl nicht ueber die
-			// super-Funktion
-			int state = getState();
+        switch (e.getButton()) {
+        // Linksklick --> Eingestellte Funktion
+        case MouseEvent.BUTTON1: // Feature-Auswahl nicht ueber die
+            // super-Funktion
+            int state = getState();
 
-			if (state == SELECT_TOP || state == SELECT_ONE_FROM_TOP
-					|| state == SELECT_ALL) {
+            if (state == SELECT_TOP || state == SELECT_ONE_FROM_TOP
+                    || state == SELECT_ALL) {
 
-				/**
-				 * BEGIN StefanChange Dieser Block findet sichtbare Features im
-				 * Umkreis des Mausklicks und kümmert sich selbst um das
-				 * verschicken der Events. Dabei wird z.Zt. immer eine
-				 * FeaterCollection mit nur einem Feature verschickt. Und zwar
-				 * jenes Feature, welches am nächsten liegt.
-				 */
+                /**
+                 * BEGIN StefanChange Dieser Block findet sichtbare Features im
+                 * Umkreis des Mausklicks und kümmert sich selbst um das
+                 * verschicken der Events. Dabei wird z.Zt. immer eine
+                 * FeaterCollection mit nur einem Feature verschickt. Und zwar
+                 * jenes Feature, welches am nächsten liegt.
+                 */
 
-				// Fenster-Koordinate in Geo-Koordinate umwandelt
-				Point2D geoCoord = getTransform().transform(e.getPoint(), null);
-				com.vividsolutions.jts.geom.Point mousePoint = new GeometryFactory()
-						.createPoint(new Coordinate(geoCoord.getX(), geoCoord
-								.getY()));
+                // Fenster-Koordinate in Geo-Koordinate umwandelt
+                Point2D geoCoord = getTransform().transform(e.getPoint(), null);
+                com.vividsolutions.jts.geom.Point mousePoint = new GeometryFactory()
+                        .createPoint(new Coordinate(geoCoord.getX(), geoCoord
+                                .getY()));
 
-				// Rechnet 10 Pixel in die Einheit der Karte um.
-				final Point pAtDistance = new Point(
-						(int) e.getPoint().getX() + 10, (int) e.getPoint()
-								.getY());
-				final Point2D geoCoordAtDistance = getTransform().transform(
-						pAtDistance, null);
-				final Double dist = Math.abs(geoCoordAtDistance.getX()
-						- geoCoord.getX());
+                // Rechnet 10 Pixel in die Einheit der Karte um.
+                final Point pAtDistance = new Point(
+                        (int) e.getPoint().getX() + 10, (int) e.getPoint()
+                                .getY());
+                final Point2D geoCoordAtDistance = getTransform().transform(
+                        pAtDistance, null);
+                final Double dist = Math.abs(geoCoordAtDistance.getX()
+                        - geoCoord.getX());
 
-				final Envelope envelope = new Envelope(geoCoord.getX(),
-						geoCoord.getX(), geoCoord.getY(), geoCoord.getY());
+                final Envelope envelope = new Envelope(geoCoord.getX(),
+                        geoCoord.getX(), geoCoord.getY(), geoCoord.getY());
 
-				Hashtable<MapLayer, FeatureCollection> result = findVisibleFeatures(
-						createNearPointFilter(geoCoord, dist), state, envelope);
+                Hashtable<MapLayer, FeatureCollection> result = findVisibleFeatures(
+                        new NearPointFilterGenerator(geoCoord, dist, getContext().getCoordinateReferenceSystem()),
+                        state,
+                        envelope
+                );
 
-				boolean featuresFound = false;
-				// Events ausloesen fuer jedes Layer
-				for (Enumeration<MapLayer> element = result.keys(); element
-						.hasMoreElements();) {
+                boolean featuresFound = false;
+                // Events ausloesen fuer jedes Layer
+                for (Enumeration<MapLayer> element = result.keys(); element
+                        .hasMoreElements();) {
 
-					MapLayer layer = element.nextElement();
-					FeatureCollection fc = result.get(layer);
-					FeatureCollection fcOne;
+                    MapLayer layer = element.nextElement();
+                    FeatureCollection fc = result.get(layer);
+                    FeatureCollection fcOne;
 
-					if (fc != null && !fc.isEmpty()) {
+                    if (fc != null && !fc.isEmpty()) {
 
-						if (fc.size() > 1) {
-							// Hier werden alle Features weggeschmissen, bis auf
-							// das raeumlich naechste.
+                        if (fc.size() > 1) {
+                            // Hier werden alle Features weggeschmissen, bis auf
+                            // das raeumlich naechste.
 
-							Feature nearestFeature = null;
-							Double nearestDist = 0.0;
+                            Feature nearestFeature = null;
+                            Double nearestDist = 0.0;
 
-							Iterator<Feature> fcIt = fc.iterator();
-							while (fcIt.hasNext()) {
-								Feature f = fcIt.next();
-								Object obj = f.getAttribute(0);
+                            Iterator<Feature> fcIt = fc.iterator();
+                            while (fcIt.hasNext()) {
+                                Feature f = fcIt.next();
+                                Object obj = f.getAttribute(0);
 
-								if (obj instanceof Geometry) {
-									// Bei Punkten ja noch ganz einfach:
-									Geometry featureGeometry = (Geometry) obj;
-									double distance = featureGeometry
-											.distance(mousePoint);
+                                if (obj instanceof Geometry) {
+                                    // Bei Punkten ja noch ganz einfach:
+                                    Geometry featureGeometry = (Geometry) obj;
+                                    double distance = featureGeometry
+                                            .distance(mousePoint);
 
-									if ((nearestFeature == null)
-											|| (distance < nearestDist)) {
-										nearestFeature = f;
-										nearestDist = distance;
-									}
-								} else {
-									LOGGER
-											.info("!obj instanceof Geometry      obj = "
-													+ obj.getClass()
-															.getSimpleName());
-								}
+                                    if ((nearestFeature == null)
+                                            || (distance < nearestDist)) {
+                                        nearestFeature = f;
+                                        nearestDist = distance;
+                                    }
+                                } else {
+                                    LOGGER
+                                            .info("!obj instanceof Geometry      obj = "
+                                                    + obj.getClass()
+                                                            .getSimpleName());
+                                }
 
-							}
-							fc.close(fcIt);
+                            }
+                            fc.close(fcIt);
 
-							fcOne = new MemoryFeatureCollection(fc
-									.getFeatureType());
-							fc.clear();
-							fcOne.add(nearestFeature);
-						} else {
-							fcOne = fc;
-						}
-						fireMapPaneEvent(new FeatureSelectedEvent(
-								JMapPane.this, layer, envelope, fcOne));
-						featuresFound = true;
-					}
-				}
+                            fcOne = new MemoryFeatureCollection(fc
+                                    .getFeatureType());
+                            fc.clear();
+                            fcOne.add(nearestFeature);
+                        } else {
+                            fcOne = fc;
+                        }
+                        fireMapPaneEvent(new FeatureSelectedEvent(
+                                JMapPane.this, layer, envelope, fcOne));
+                        featuresFound = true;
+                    }
+                }
 
-				// TODO TODO TODO SK: DIese trennung: erst Feature layers, dann
-				// grid layers check ist doof!
-				// if (state == SELECT_ALL || !result.isEmpty())
+                // TODO TODO TODO SK: DIese trennung: erst Feature layers, dann
+                // grid layers check ist doof!
+                // if (state == SELECT_ALL || !result.isEmpty())
 
-				// LOGGER.info("state= "+state+"     featuresFound = "+
-				// featuresFound);
-				if (state == SELECT_ALL || !featuresFound) {
-					// LOGGER.info("   findGridCoverageValuesAndFireEvents");
-					findGridCoverageValuesAndFireEvents(geoCoord, state);
-				}
+                // LOGGER.info("state= "+state+"     featuresFound = "+
+                // featuresFound);
+                if (state == SELECT_ALL || !featuresFound) {
+                    // LOGGER.info("   findGridCoverageValuesAndFireEvents");
+                    findGridCoverageValuesAndFireEvents(geoCoord, state);
+                }
 
-				break;
-			}
-			super.mouseClicked(e);
-			return; // was: breka, aber wir brauchen ja nicht das
-			// setMapArea(mapArea)
+                break;
+            }
+            super.mouseClicked(e);
+            return; // was: breka, aber wir brauchen ja nicht das
+            // setMapArea(mapArea)
 
-			// Rechtsklick --> Zoom-Out
-		case MouseEvent.BUTTON3:
-			int oldState = getState();
-			// MS: ist doch eleganter, wenn IMMER mit Rechtsklick raus-gezoomt
-			// werden kann!
-			// // ZOOM_OUT nur wenn Links-Klick auf ZOOM_IN eingestellt ist)
-			// if ( oldState != ZOOM_IN )
-			// return;
-			setState(ZOOM_OUT);
-			super.mouseClicked(e);
-			setState(oldState);
-			break;
-		// Sonst nix
-		default:
-			return;
-		}
+            // Rechtsklick --> Zoom-Out
+        case MouseEvent.BUTTON3:
+            int oldState = getState();
+            // MS: ist doch eleganter, wenn IMMER mit Rechtsklick raus-gezoomt
+            // werden kann!
+            // // ZOOM_OUT nur wenn Links-Klick auf ZOOM_IN eingestellt ist)
+            // if ( oldState != ZOOM_IN )
+            // return;
+            setState(ZOOM_OUT);
+            super.mouseClicked(e);
+            setState(oldState);
+            break;
+        // Sonst nix
+        default:
+            return;
+        }
 
-		// In super.mouseClicked(.) wird (nach Zoom) die MapArea neu gesetzt,
-		// aber
-		// leider ohne setMapArea(.) aufzurufen, sondern indem einfach die
-		// Variable
-		// 'mapArea' neu belegt wird
-		// --> Transform muss neu berechnet werden
-		// --> Aenderung der Aufloesung propagieren
+        // In super.mouseClicked(.) wird (nach Zoom) die MapArea neu gesetzt,
+        // aber
+        // leider ohne setMapArea(.) aufzurufen, sondern indem einfach die
+        // Variable
+        // 'mapArea' neu belegt wird
+        // --> Transform muss neu berechnet werden
+        // --> Aenderung der Aufloesung propagieren
 
-		setMapArea(mapArea);
-		// resetTransform();
-		// double newScale = getScale();
-		// Envelope newEnv = getMapArea();
-		// if ( oldScale != newScale )
-		// fireMapPaneEvent( new ScaleChangedEvent(this,oldScale,newScale) );
-		// if ( oldEnv == null && newEnv != null || oldEnv != null &&
-		// !oldEnv.equals( newEnv ) )
-		// fireMapPaneEvent( new MapAreaChangedEvent(this,oldEnv,newEnv) );
-	}
+        setMapArea(mapArea);
+        // resetTransform();
+        // double newScale = getScale();
+        // Envelope newEnv = getMapArea();
+        // if ( oldScale != newScale )
+        // fireMapPaneEvent( new ScaleChangedEvent(this,oldScale,newScale) );
+        // if ( oldEnv == null && newEnv != null || oldEnv != null &&
+        // !oldEnv.equals( newEnv ) )
+        // fireMapPaneEvent( new MapAreaChangedEvent(this,oldEnv,newEnv) );
+    }
 
-	/**
-	 * In <code>super.paintComponent(.)</code> wird unter gewissen Umstaenden
-	 * die MapArea neu gesetzt, aber leider ohne {@link #setMapArea(Envelope)}
-	 * aufzurufen, sondern indem einfach die Variable <code>mapArea</code> neu
-	 * belegt wird. Damit auch die Transformation an den neuen Kartenbereich
-	 * angepasst wird, muss diese Methode ueberschrieben werden.
-	 * <p>
-	 * Neu von SK: Ich habe in der Geotools
-	 * {@link org.geotools.gui.swing.JMapPane} die noetigen variablen protected
-	 * gemacht, um hier schon festzustellen, ob der aufruf von
-	 * super.paintComponent das eigentliche aussehen der Karte veraendern wird.
-	 * Die Methode paintComponent wird naemlich bei jeder Bewegung der Maus
-	 * aufgerufen, und meistens wird super.paintComponent nur ein gebufferted
-	 * Image auf den Ausschnitt zeichnen. Falls die "seriouseChange" zu erwarten
-	 * ist, wird evt. der Mauscursor auf WAIT gesetzt, und auf jeden Fall die
-	 * Methode {@link #resetTransform()} aufgerufen.<br>
-	 * Sinn des Ganzen? Ich habe versucht etwas Performance zu gewinnen, da
-	 * sonst bei jeder Mausbewegung die die {@link AffineTransform} durch
-	 * {@link #resetTransform()} neu berechnet wurde.
-	 * 
-	 * @param g
-	 *            Graphics
-	 * @see #resetTransform()
-	 * 
-	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-	 *         (University of Bonn/Germany)
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	protected void paintComponent(Graphics g) {
-		Cursor oldCursor = null;
-		boolean seriouseChange = false;
+    /**
+     * In <code>super.paintComponent(.)</code> wird unter gewissen Umstaenden
+     * die MapArea neu gesetzt, aber leider ohne {@link #setMapArea(Envelope)}
+     * aufzurufen, sondern indem einfach die Variable <code>mapArea</code> neu
+     * belegt wird. Damit auch die Transformation an den neuen Kartenbereich
+     * angepasst wird, muss diese Methode ueberschrieben werden.
+     * <p>
+     * Neu von SK: Ich habe in der Geotools
+     * {@link org.geotools.gui.swing.JMapPane} die noetigen variablen protected
+     * gemacht, um hier schon festzustellen, ob der aufruf von
+     * super.paintComponent das eigentliche aussehen der Karte veraendern wird.
+     * Die Methode paintComponent wird naemlich bei jeder Bewegung der Maus
+     * aufgerufen, und meistens wird super.paintComponent nur ein gebufferted
+     * Image auf den Ausschnitt zeichnen. Falls die "seriouseChange" zu erwarten
+     * ist, wird evt. der Mauscursor auf WAIT gesetzt, und auf jeden Fall die
+     * Methode {@link #resetTransform()} aufgerufen.<br>
+     * Sinn des Ganzen? Ich habe versucht etwas Performance zu gewinnen, da
+     * sonst bei jeder Mausbewegung die die {@link AffineTransform} durch
+     * {@link #resetTransform()} neu berechnet wurde.
+     *
+     * @param g
+     *            Graphics
+     * @see #resetTransform()
+     *
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     *         (University of Bonn/Germany)
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    protected void paintComponent(Graphics g) {
+        Cursor oldCursor = null;
+        boolean seriouseChange = false;
 
-		if (!getBounds().equals(oldRect) || reset)
-			seriouseChange = true;
-		else if (!mapArea.equals(oldMapArea))
-			seriouseChange = true;
+        if (!getBounds().equals(oldRect) || reset)
+            seriouseChange = true;
+        else if (!mapArea.equals(oldMapArea))
+            seriouseChange = true;
 
-		if (seriouseChange) {
-			if (setWaitCursorDuringNextRepaint) {
+        if (seriouseChange) {
+            if (setWaitCursorDuringNextRepaint) {
 
-				if (getWaitCursorComponent() != null) {
-					// Der Cursor soll auch in einer anderen Component geaendert
-					// werden..
-					oldCursor = getWaitCursorComponent().getCursor();
-					getWaitCursorComponent().setCursor(WAIT_CURSOR);
-				}
+                if (getWaitCursorComponent() != null) {
+                    // Der Cursor soll auch in einer anderen Component geaendert
+                    // werden..
+                    oldCursor = getWaitCursorComponent().getCursor();
+                    getWaitCursorComponent().setCursor(WAIT_CURSOR);
+                }
 
-				// Den Cursor extra nochmal in dieser COmponente aendern
-				setCursor(WAIT_CURSOR);
-			}
-		}
+                // Den Cursor extra nochmal in dieser COmponente aendern
+                setCursor(WAIT_CURSOR);
+            }
+        }
 
-		try {
-			super.paintComponent(g);
-		} catch (Exception e) {
-			/**
-			 * I only need to catch UnknownHostException.. well...
-			 */
-			LOGGER.info(e);
-			LOGGER
-					.info("Probably we are offline and reference some online SVGs? ");
-		}
-		if (seriouseChange) {
-			resetTransform();
-			if (setWaitCursorDuringNextRepaint) {
-				setWaitCursorDuringNextRepaint = false;
-				if (oldCursor != null)
-					getWaitCursorComponent().setCursor(oldCursor);
-				updateCursor(); // Den Cursor in dieser Componente immer wieder
-				// herstellen
-			}
+        try {
+            super.paintComponent(g);
+        } catch (Exception e) {
+            /**
+             * I only need to catch UnknownHostException.. well...
+             */
+            LOGGER.info(e);
+            LOGGER
+                    .info("Probably we are offline and reference some online SVGs? ");
+        }
+        if (seriouseChange) {
+            resetTransform();
+            if (setWaitCursorDuringNextRepaint) {
+                setWaitCursorDuringNextRepaint = false;
+                if (oldCursor != null)
+                    getWaitCursorComponent().setCursor(oldCursor);
+                updateCursor(); // Den Cursor in dieser Componente immer wieder
+                // herstellen
+            }
 
-			/**
-			 * Paint an icon in the lower right corner. FeatureRequest: [#717]
-			 * MapIcon has long been disabled and should come back
-			 */
-			if (mapImage != null && baseImage != null) {
-				baseImage
-						.getGraphics()
-						.drawImage(
-								mapImage,
-								baseImage.getWidth() - mapImage.getWidth() - 10,
-								baseImage.getHeight() - mapImage.getHeight()
-										- 10, this);
-				// Repaint with the cached image (fast) which now contains the
-				// logo
-				super.paintComponent(g);
-			}
-		}
+            /**
+             * Paint an icon in the lower right corner. FeatureRequest: [#717]
+             * MapIcon has long been disabled and should come back
+             */
+            if (mapImage != null && baseImage != null) {
+                baseImage
+                        .getGraphics()
+                        .drawImage(
+                                mapImage,
+                                baseImage.getWidth() - mapImage.getWidth() - 10,
+                                baseImage.getHeight() - mapImage.getHeight()
+                                        - 10, this);
+                // Repaint with the cached image (fast) which now contains the
+                // logo
+                super.paintComponent(g);
+            }
+        }
 
-	}
+    }
 
-	/**
-	 * Testet (anhand der Bounding-Box), ob das Objekt eines Layers eine andere
-	 * Bounding-Box schneidet. Die Bounding-Box des Layer-Objekts wird zunaechst
-	 * in das CRS des MapPanes umgerechnets.
-	 * 
-	 * @param layer
-	 *            ein Layer
-	 * @param env
-	 *            Bounding-Box in CRS des MapPane
-	 */
-	private boolean gridLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
-		try {
-			// BB des Layers umrechnen von Layer-CRS in Map-CRS
-			Envelope bounds_MapCRS = JTSUtil.transformEnvelope(layer
-					.getFeatureSource().getBounds(), layer.getFeatureSource()
-					.getSchema().getDefaultGeometry().getCoordinateSystem(),
-					getContext().getCoordinateReferenceSystem());
+    /**
+     * Testet (anhand der Bounding-Box), ob das Objekt eines Layers eine andere
+     * Bounding-Box schneidet. Die Bounding-Box des Layer-Objekts wird zunaechst
+     * in das CRS des MapPanes umgerechnets.
+     *
+     * @param layer
+     *            ein Layer
+     * @param env
+     *            Bounding-Box in CRS des MapPane
+     */
+    private boolean gridLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
+        try {
+            // BB des Layers umrechnen von Layer-CRS in Map-CRS
+            Envelope bounds_MapCRS = JTSUtil.transformEnvelope(layer
+                    .getFeatureSource().getBounds(), layer.getFeatureSource()
+                    .getSchema().getDefaultGeometry().getCoordinateSystem(),
+                    getContext().getCoordinateReferenceSystem());
 
-			// TODO warum kann bounds_MapCRS == null sein ?? ?SK fragt martin???
-			if (bounds_MapCRS == null)
-				return false;
+            // TODO warum kann bounds_MapCRS == null sein ?? ?SK fragt martin???
+            if (bounds_MapCRS == null)
+                return false;
 
-			return bounds_MapCRS.intersects(env);
-		} catch (Exception err) {
-			return false;
-		}
-	}
+            return bounds_MapCRS.intersects(env);
+        } catch (Exception err) {
+            return false;
+        }
+    }
 
-	/**
-	 * Testet (anhand der Features), ob das Objekt eines Layers eine
-	 * Bounding-Box schneidet.
-	 * 
-	 * @param layer
-	 *            ein Layer
-	 * @param env
-	 *            Bounding-Box in CRS des MapPane
-	 */
-	private boolean featureLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
-		try {
-			// BB umrechnen von Map-CRS in Layer-CRS
-			Envelope env_LayerCRS = JTSUtil.transformEnvelope(env, getContext()
-					.getCoordinateReferenceSystem(), layer.getFeatureSource()
-					.getSchema().getDefaultGeometry().getCoordinateSystem());
-			GeometryFilterImpl filter = createBoundingBoxFilter(env_LayerCRS);
-			Expression geometry = ff.createAttributeExpression(layer
-					.getFeatureSource().getSchema().getDefaultGeometry()
-					.getLocalName());
-			filter.setExpression1(geometry);
-			return !layer.getFeatureSource().getFeatures(filter).isEmpty();
-		} catch (Exception err) {
-			return false;
-		}
-	}
+    /**
+     * Testet (anhand der Features), ob das Objekt eines Layers eine
+     * Bounding-Box schneidet.
+     *
+     * @param layer
+     *            ein Layer
+     * @param env
+     *            Bounding-Box in CRS des MapPane
+     */
+    private boolean featureLayerIntersectsEnvelope(MapLayer layer, Envelope env) {
+        try {
+//          // BB umrechnen von Map-CRS in Layer-CRS
+//          Envelope env_LayerCRS = JTSUtil.transformEnvelope(env, getContext()
+//                  .getCoordinateReferenceSystem(), layer.getFeatureSource()
+//                  .getSchema().getDefaultGeometry().getCoordinateSystem());
+//          GeometryFilterImpl filter = createBoundingBoxFilter(env_LayerCRS);
+//          Expression geometry = ff.createAttributeExpression(layer
+//                  .getFeatureSource().getSchema().getDefaultGeometry()
+//                  .getLocalName());
+//          filter.setExpression1(geometry);
+            GeometryFilterImpl filter = new BoundingBoxFilterGenerator(
+                                               env,
+                                               getContext().getCoordinateReferenceSystem()
+            ).adaptFilter(layer.getFeatureSource());
+            return !layer.getFeatureSource().getFeatures(filter).isEmpty();
+        } catch (Exception err) {
+            return false;
+        }
+    }
 
-	/**
-	 * Ermittelt alle sichtbaren Features, die einen Filter erfuellen. Beim
-	 * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
-	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
-	 * durchsucht.
-	 * 
-	 * @see #findFeatures(GeometryFilterImpl, int, Envelope)
-	 * 
-	 * @param distancefilter
-	 *            Filter
-	 * @param mode
-	 *            Suchmodus
-	 * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
-	 */
-	protected Hashtable<MapLayer, FeatureCollection> findVisibleFeatures(
-			GeometryFilterImpl distancefilter, int mode, Envelope env) {
-		Hashtable<MapLayer, FeatureCollection> result = new Hashtable<MapLayer, FeatureCollection>();
-		if (distancefilter == null)
-			return result;
+    /**
+     * Ermittelt alle sichtbaren Features, die einen Filter erfuellen. Beim
+     * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
+     * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
+     * durchsucht.
+     *
+     * @see #findFeatures(GeometryFilterImpl, int, Envelope)
+     *
+     * @param filterGenerator
+     *            adapts the filter to a concrete FeatureSource
+     * @param mode
+     *            Suchmodus
+     * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
+     */
+    protected Hashtable<MapLayer, FeatureCollection> findVisibleFeatures(
+            GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+        Hashtable<MapLayer, FeatureCollection> result = new Hashtable<MapLayer, FeatureCollection>();
+        if (filterGenerator == null)
+            return result;
 
-		// Je nach Modus: Alle oder nur das oberste Layer
-		MapContext context = getContext();
-		MapLayer[] layerList = context.getLayers();
-		for (int i = layerList.length - 1; i >= 0; i--) {
-			MapLayer layer = layerList[i];
-			if (!layer.isVisible())
-				continue;
+        // Je nach Modus: Alle oder nur das oberste Layer
+        MapContext context = getContext();
+        MapLayer[] layerList = context.getLayers();
+        for (int i = layerList.length - 1; i >= 0; i--) {
+            MapLayer layer = layerList[i];
+            if (!layer.isVisible())
+                continue;
 
-			// Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
-			// im
-			// obersten (sichtbaren) Layer gesucht wird.
-			// Ansonsten Raster-Layer einfach uebergehen.
-			if (isGridCoverageLayer(layer)) {
-				if (mode == SELECT_TOP
-						&& gridLayerIntersectsEnvelope(layer, env))
-					break;
-				continue;
-			}
+            // Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
+            // im obersten (sichtbaren) Layer gesucht wird.
+            // Ansonsten Raster-Layer einfach uebergehen.
+            if (isGridCoverageLayer(layer)) {
+                if (mode == SELECT_TOP && gridLayerIntersectsEnvelope(layer, env))
+                    break;
+                continue;
+            }
 
-			// Filter an Layer koppeln
-			// WICHTIG: Dies darf erst geschehen, NACHDEM das
-			// Schleifen-Abbruch-Kriterium
-			// fuer die Raster-Layer geprueft wurde!!
-			// Werden folgende Zeilen naemlich auf das FeatureSource des
-			// Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
-			// zusammen und auch die ZUVOR gefilterten FeatureCollections,
-			// sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
-			final FeatureSource featureSource = layer.getFeatureSource();
-			Expression geometry = ff.createAttributeExpression(featureSource
-					.getSchema().getDefaultGeometry().getLocalName());
+            // Filter an Layer koppeln
+            // WICHTIG: Dies darf erst geschehen, NACHDEM das
+            // Schleifen-Abbruch-Kriterium
+            // fuer die Raster-Layer geprueft wurde!!
+            // Werden folgende Zeilen naemlich auf das FeatureSource des
+            // Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
+            // zusammen und auch die ZUVOR gefilterten FeatureCollections,
+            // sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            final FeatureSource      featureSource = layer.getFeatureSource();
+            final GeometryFilterImpl distancefilter = filterGenerator.adaptFilter(featureSource);
 
-			distancefilter.setExpression1(geometry);
+            /**
+             * 8.8.2008: SK Wenn für das Layer auch ein Filter aktiv ist, dann
+             * soll dieser mit AND an den distanceFilter gebunden werden.
+             * "Filter filter" ist entweder der distanceFilter oder
+             * (distanceFilter AND layerFilter)
+             */
+            Filter filter = distancefilter;
+            if (layer.getQuery() != null) {
+                final Filter layerFilter = layer.getQuery().getFilter();
+                if (layerFilter != null) {
+                    filter = distancefilter.and(layerFilter);
+                }
+            }
 
-			/**
-			 * 8.8.2008: SK Wenn für das Layer auch ein Filter aktiv ist, dann
-			 * soll dieser mit AND an den distanceFilter gebunden werden.
-			 * "Filter filter" ist entweder der distanceFilter oder
-			 * (distanceFilter AND layerFilter)
-			 */
-			Filter filter = distancefilter;
-			if (layer.getQuery() != null) {
-				final Filter layerFilter = layer.getQuery().getFilter();
-				if (layerFilter != null) {
-					filter = distancefilter.and(layerFilter);
-				}
-			}
+            try {
+                // Filter auf Layer des Features anwenden
+                // FeatureCollection fc = layer.getFeatureSource().getFeatures(
+                // FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
+                // FeatureCollection fc = featureSource.getFeatures(
+                // distancefilter );
+                FeatureCollection fc = featureSource.getFeatures(filter);
 
-			try {
-				// Filter auf Layer des Features anwenden
-				// FeatureCollection fc = layer.getFeatureSource().getFeatures(
-				// FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
-				// FeatureCollection fc = featureSource.getFeatures(
-				// distancefilter );
-				FeatureCollection fc = featureSource.getFeatures(filter);
+                // Liefert eine FeatureCollection zurück, in welcher nur
+                // Features enthalten sind, welche bei der aktuellen
+                // Anzeigeskala aufgrund des Styles gerendert werden.
+                if (layer.getTitle().equals(
+                        "vector_afrikan_countries_00040984322")) {
+                    LOGGER.warn("Cancelling here to avoid infinite loop in ShapefileReader.ensureCapacity(ByteBuffer, int, boolean) line: 203.");
+                    LOGGER.warn("Calling isEmpty() or getSize() in GT2.4.5 the ShapefileReader-Class enters infinite loop here for the here for layer vector_afrikan_countries_00040984322. It seems to be specific for this special ShapeFile. Canelling the operation here is a very ugly and very static work-arround. Hopefully this problem vanishes with GT 2.5");
+                    continue;
+                }
 
-				// Liefert eine FeatureCollection zurück, in welcher nur
-				// Features enthalten sind, welche bei der aktuellen
-				// Anzeigeskala aufgrund des Styles gerendert werden.
+                // @Martin Using size() produces the same problem
+                if (!fc.isEmpty()) {
+                    fc = filterSLDVisibleOnly(fc, layer.getStyle());
 
-				if (layer.getTitle().equals(
-						"vector_afrikan_countries_00040984322")) {
-					LOGGER
-							.warn("Cancelling here to avoid infinite loop in ShapefileReader.ensureCapacity(ByteBuffer, int, boolean) line: 203.");
-					LOGGER
-							.warn("Calling isEmpty() or getSize() in GT2.4.5 the ShapefileReader-Class enters infinite loop here for the here for layer vector_afrikan_countries_00040984322. It seems to be specific for this special ShapeFile. Canelling the operation here is a very ugly and very static work-arround. Hopefully this problem vanishes with GT 2.5");
-					continue;
-				}
+                    if (!fc.isEmpty()) {
+                        result.put(layer, fc);
+                        // Beim Modus "oberstes Layer selektieren" die Schleife
+                        // beenden
+                        if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+                            break;
+                    }
 
-				// @Martin Using size() produces the same problem
-				if (!fc.isEmpty()) {
+                }
+            } catch (IOException err) {
+                err.printStackTrace();
+            }
 
-					fc = filterSLDVisibleOnly(fc, layer.getStyle());
-					
-					if (!fc.isEmpty()) {
-						result.put(layer, fc);
-						// Beim Modus "oberstes Layer selektieren" die Schleife
-						// beenden
-						if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-							break;
-					}
+            // for ( FeatureCollection fc1 : result.values() )
+            // LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
+        }
+        // for ( FeatureCollection fc1 : result.values() )
+        // LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
 
-				}
-			} catch (IOException err) {
-				err.printStackTrace();
-			}
+        return result;
+    }
 
-			// for ( FeatureCollection fc1 : result.values() )
-			// LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
-		}
-		// for ( FeatureCollection fc1 : result.values() )
-		// LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
+    /**
+     * Ermittelt alle Features, die einen Filter erfuellen. Beim Modus
+     * {@link #SELECT_TOP} wird nur das oberste sichtbare Layer durchsucht. Beim
+     * Modus {@link #SELECT_ALL} werden alle sichtbaren Layer durchsucht.
+     *
+     * 17.4.08, Stefan
+     *
+     * @param filter
+     *            Filter
+     * @param mode
+     *            Suchmodus
+     * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
+     */
+    protected Hashtable<MapLayer, FeatureCollection> findFeatures(
+            GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+        Hashtable<MapLayer, FeatureCollection> result = new Hashtable<MapLayer, FeatureCollection>();
+        if (filterGenerator == null)
+            return result;
 
-		return result;
-	}
+        // Je nach Modus: Alle oder nur das oberste Layer
+        MapContext context = getContext();
+        MapLayer[] layerList = context.getLayers();
+        for (int i = layerList.length - 1; i >= 0; i--) {
+            MapLayer layer = layerList[i];
+            if (!layer.isVisible())
+                continue;
 
-	/**
-	 * Ermittelt alle Features, die einen Filter erfuellen. Beim Modus
-	 * {@link #SELECT_TOP} wird nur das oberste sichtbare Layer durchsucht. Beim
-	 * Modus {@link #SELECT_ALL} werden alle sichtbaren Layer durchsucht.
-	 * 
-	 * 17.4.08, Stefan
-	 * 
-	 * @param filter
-	 *            Filter
-	 * @param mode
-	 *            Suchmodus
-	 * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
-	 */
-	protected Hashtable<MapLayer, FeatureCollection> findFeatures(
-			GeometryFilterImpl filter, int mode, Envelope env) {
-		Hashtable<MapLayer, FeatureCollection> result = new Hashtable<MapLayer, FeatureCollection>();
-		if (filter == null)
-			return result;
+            // Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
+            // im
+            // obersten (sichtbaren) Layer gesucht
+            // wird.AbstractGridCoverage2DReader
+            // Ansonsten Raster-Layer einfach uebergehen.
+            if (isGridCoverageLayer(layer)) {
+                if (mode == SELECT_TOP
+                        && gridLayerIntersectsEnvelope(layer, env))
+                    break;
+                continue;
+            }
 
-		// Je nach Modus: Alle oder nur das oberste Layer
-		MapContext context = getContext();
-		MapLayer[] layerList = context.getLayers();
-		for (int i = layerList.length - 1; i >= 0; i--) {
-			MapLayer layer = layerList[i];
-			if (!layer.isVisible())
-				continue;
+            // Filter an Layer koppeln
+            // WICHTIG: Dies darf erst geschehen, NACHDEM das
+            // Schleifen-Abbruch-Kriterium
+            // fuer die Raster-Layer geprueft wurde!!
+            // Werden folgende Zeilen naemlich auf das FeatureSource des
+            // Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
+            // zusammen und auch die ZUVOR gefilterten FeatureCollections,
+            // sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
+            final FeatureSource      featureSource = layer.getFeatureSource();
+            final GeometryFilterImpl filter        = filterGenerator.adaptFilter(featureSource);
 
-			// Bei einem Raster-Layer, das die BB schneidet, abbrechen, wenn nur
-			// im
-			// obersten (sichtbaren) Layer gesucht
-			// wird.AbstractGridCoverage2DReader
-			// Ansonsten Raster-Layer einfach uebergehen.
-			if (isGridCoverageLayer(layer)) {
-				if (mode == SELECT_TOP
-						&& gridLayerIntersectsEnvelope(layer, env))
-					break;
-				continue;
-			}
+            try {
+                // Filter auf Layer des Features anwenden
+                // FeatureCollection fc = layer.getFeatureSource().getFeatures(
+                // FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
+                FeatureCollection fc = featureSource.getFeatures(filter);
 
-			// Filter an Layer koppeln
-			// WICHTIG: Dies darf erst geschehen, NACHDEM das
-			// Schleifen-Abbruch-Kriterium
-			// fuer die Raster-Layer geprueft wurde!!
-			// Werden folgende Zeilen naemlich auf das FeatureSource des
-			// Raster-Layers angewandt, dann "bricht" der Filter "irgendwie"
-			// zusammen und auch die ZUVOR gefilterten FeatureCollections,
-			// sind ploetzlich EMPTY!!!!!!!!!!!!!!!!!!!!!!!!!!!
-			final FeatureSource featureSource = layer.getFeatureSource();
-			Expression geometry = ff.createAttributeExpression(featureSource
-					.getSchema().getDefaultGeometry().getLocalName());
+                // Liefert eine FeatureCollection zurück, in welcher nur
+                // Features enthalten sind, welche bei der aktuellen
+                // Anzeigeskala aufgrund des Styles gerendert werden.
+                fc = filterSLDVisibleOnly(fc, layer.getStyle());
 
-			filter.setExpression1(geometry);
+                if (!fc.isEmpty()) {
+                    result.put(layer, fc);
+                    // Beim Modus "oberstes Layer selektieren" die Schleife
+                    // jetzt beenden, da wir sichtbare Features gefunden haben.
+                    if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+                        break;
+                }
+            } catch (Exception err) {
+                err.printStackTrace();
+                LOGGER.error(err);
+            }
 
-			try {
-				// Filter auf Layer des Features anwenden
-				// FeatureCollection fc = layer.getFeatureSource().getFeatures(
-				// FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
-				FeatureCollection fc = featureSource.getFeatures(filter);
+            // for ( FeatureCollection fc1 : result.values() )
+            // LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
+        }
+        // for ( FeatureCollection fc1 : result.values() )
+        // LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
 
-				// Liefert eine FeatureCollection zurück, in welcher nur
-				// Features enthalten sind, welche bei der aktuellen
-				// Anzeigeskala aufgrund des Styles gerendert werden.
-				fc = filterSLDVisibleOnly(fc, layer.getStyle());
+        return result;
+    }
 
-				if (!fc.isEmpty()) {
-					result.put(layer, fc);
-					// Beim Modus "oberstes Layer selektieren" die Schleife
-					// jetzt beenden, da wir sichtbare Features gefunden haben.
-					if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-						break;
-				}
-			} catch (Exception err) {
-				err.printStackTrace();
-				LOGGER.error(err);
-			}
+    /**
+     * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
+     * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
+     * werden.
+     *
+     * @param fc
+     *            Die zu filternde FeatureCollection. Diese wird nicht
+     *            verändert.
+     * @param style
+     *            Der Style, mit dem die Features gerendert werden (z.b.
+     *            layer.getStyle() )
+     *
+     * @return Eine FeatureCollection in welcher nur die Features enthalten
+     *         sind, welche bei aktuellen Scale mit dem übergebenen Style
+     *         gerendert werden.
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    private MemoryFeatureCollection filterSLDVisibleOnly(
+            final FeatureCollection fc, final Style style) {
 
-			// for ( FeatureCollection fc1 : result.values() )
-			// LOGGER.debug("A  "+fc1+"    "+fc1.isEmpty());
-		}
-		// for ( FeatureCollection fc1 : result.values() )
-		// LOGGER.debug("B   "+fc1+"    "+fc1.isEmpty());
+        // Der "scaleDenominator" der aktuellen JMapPane
+        Double scaleDenominator = RendererUtilities
+                .calculateOGCScale(new ReferencedEnvelope(getMapArea(),
+                        getContext().getCoordinateReferenceSystem()),
+                        getSize().width, null);
 
-		return result;
-	}
+        return StylingUtil.filterSLDVisibleOnly(fc, style, scaleDenominator);
+    }
 
-	/**
-	 * SLD Rules können die Paramter MinScaleDenominator und MaxScaleDenominator
-	 * enthalten. Dadurch können Elemente für manche Zoom-Stufen deaktiviert
-	 * werden.
-	 * 
-	 * @param fc
-	 *            Die zu filternde FeatureCollection. Diese wird nicht
-	 *            verändert.
-	 * @param style
-	 *            Der Style, mit dem die Features gerendert werden (z.b.
-	 *            layer.getStyle() )
-	 * 
-	 * @return Eine FeatureCollection in welcher nur die Features enthalten
-	 *         sind, welche bei aktuellen Scale mit dem übergebenen Style
-	 *         gerendert werden.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	private MemoryFeatureCollection filterSLDVisibleOnly(
-			final FeatureCollection fc, final Style style) {
+    /**
+     * Ermittelt alle Features, die in einem Bereich liegen und erzeugt
+     * entsprechende {@link FeatureSelectedEvent FeatureSelectedEvents}. Beim
+     * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
+     * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
+     * durchsucht.
+     *
+     * @param filterGenerator
+     *            adapts a filter to a concrete {@link FeatureSource}
+     * @param mode
+     *            Suchmodus
+     * @param env
+     *            Bereich der durchsucht wird (fuer das Filtern irrelevant; wird
+     *            nur fuer Events benoetigt!)
+     */
+    protected boolean findFeaturesAndFireEvents(GeomFilterGenerator filterGenerator,
+            int mode, Envelope env) {
+        Hashtable<MapLayer, FeatureCollection> result = findVisibleFeatures(
+            filterGenerator, mode, env);
 
-		// Der "scaleDenominator" der aktuellen JMapPane
-		Double scaleDenominator = RendererUtilities
-				.calculateOGCScale(new ReferencedEnvelope(getMapArea(),
-						getContext().getCoordinateReferenceSystem()),
-						getSize().width, null);
+        // Events ausloesen fuer jedes Layer
+        for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+            final MapLayer layer = e.nextElement();
+            final FeatureCollection fc = result.get(layer);
+            if (fc != null && !fc.isEmpty())
+                fireMapPaneEvent(new FeatureSelectedEvent(this, layer, env, fc));
+        }
+        return !result.isEmpty();
+    }
 
-		return StylingUtil.filterSLDVisibleOnly(fc, style, scaleDenominator);
-	}
+    /**
+     * Ermittelt alle Teil-Raster, die in einem Bereich liegen.
+     * BefindFeaturesAndFireEventsim Modus {@link #SELECT_TOP} wird nur das
+     * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
+     * alle sichtbaren Layer durchsucht.
+     *
+     * @param env
+     *            Bounding-Box
+     * @param mode
+     *            Suchmodus
+     * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
+     *         ist
+     */
+    protected Hashtable<MapLayer, GridCoverage2D> findGridCoverageSubsets(
+            Envelope env, int mode) {
+        Hashtable<MapLayer, GridCoverage2D> result = new Hashtable<MapLayer, GridCoverage2D>();
+        if (env == null)
+            return result;
 
-	/**
-	 * Ermittelt alle Features, die in einem Bereich liegen und erzeugt
-	 * entsprechende {@link FeatureSelectedEvent FeatureSelectedEvents}. Beim
-	 * Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
-	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
-	 * durchsucht.
-	 * 
-	 * @param filter
-	 *            Filter
-	 * @param mode
-	 *            Suchmodus
-	 * @param env
-	 *            Bereich der durchsucht wird (fuer das Filtern irrelevant; wird
-	 *            nur fuer Events benoetigt!)
-	 */
-	protected boolean findFeaturesAndFireEvents(GeometryFilterImpl filter,
-			int mode, Envelope env) {
-		Hashtable<MapLayer, FeatureCollection> result = findVisibleFeatures(
-				filter, mode, env);
+        MapContext context = getContext();
+        // Je nach Modus: Alle oder nur das oberste Layer
+        MapLayer[] layerList = context.getLayers();
+        for (int i = layerList.length - 1; i >= 0; i--) {
+            MapLayer layer = layerList[i];
+            Object layerObj = getLayerSourceObject(layer);
+            if (!layer.isVisible())
+                continue;
 
-		// Events ausloesen fuer jedes Layer
-		for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-			final MapLayer layer = e.nextElement();
-			final FeatureCollection fc = result.get(layer);
-			if (fc != null && !fc.isEmpty())
-				fireMapPaneEvent(new FeatureSelectedEvent(this, layer, env, fc));
-		}
-		return !result.isEmpty();
-	}
+            // Bei einem Nicht-Raster-Layer, das die BB schneidet, abbrechen,
+            // wenn nur im obersten (sichtbaren) Layer gesucht wird.
+            // Ansonsten Nicht-Raster-Layer einfach uebergehen.
+            if (!(layerObj instanceof GridCoverage2D)) {
+                if ((mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+                        && featureLayerIntersectsEnvelope(layer, env))
+                    break;
+                continue;
+            }
 
-	/**
-	 * Ermittelt alle Teil-Raster, die in einem Bereich liegen.
-	 * BefindFeaturesAndFireEventsim Modus {@link #SELECT_TOP} wird nur das
-	 * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
-	 * alle sichtbaren Layer durchsucht.
-	 * 
-	 * @param env
-	 *            Bounding-Box
-	 * @param mode
-	 *            Suchmodus
-	 * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
-	 *         ist
-	 */
-	protected Hashtable<MapLayer, GridCoverage2D> findGridCoverageSubsets(
-			Envelope env, int mode) {
-		Hashtable<MapLayer, GridCoverage2D> result = new Hashtable<MapLayer, GridCoverage2D>();
-		if (env == null)
-			return result;
+            GridCoverage2D sourceGrid = (GridCoverage2D) layerObj;
+            com.vividsolutions.jts.geom.Envelope jtsEnv = env;
+            org.geotools.geometry.Envelope2D gtEnv2D = JTS.getEnvelope2D(
+                    jtsEnv, sourceGrid.getCoordinateReferenceSystem());
+            // org.opengis.spatialschema.geometry.Envelope gtGenEnv = new
+            // GeneralEnvelope
+            // ((org.opengis.spatialschema.geometry.Envelope)gtEnv2D); //
+            // gt2-2.3.4
+            org.opengis.geometry.Envelope gtGenEnv = new GeneralEnvelope(
+                    (org.opengis.geometry.Envelope) gtEnv2D); // gt2-2.4.2
 
-		MapContext context = getContext();
-		// Je nach Modus: Alle oder nur das oberste Layer
-		MapLayer[] layerList = context.getLayers();
-		for (int i = layerList.length - 1; i >= 0; i--) {
-			MapLayer layer = layerList[i];
-			Object layerObj = getLayerSourceObject(layer);
-			if (!layer.isVisible())
-				continue;
+            // GridCoverage2D subsetGrid =
+            // (GridCoverage2D)Operations.DEFAULT.crop(sourceGrid,gtGenEnv);
+            GridCoverage2D subsetGrid = GridUtil.createGridCoverage(sourceGrid,
+                    gtGenEnv);
+            if (subsetGrid != null)
+                result.put(layer, subsetGrid);
+            // Beim Modus "oberstes Layer selektieren" die Schleife beenden
+            if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
+                break;
+        }
+        return result;
+    }
 
-			// Bei einem Nicht-Raster-Layer, das die BB schneidet, abbrechen,
-			// wenn nur im
-			// obersten (sichtbaren) Layer gesucht wird.
-			// Ansonsten Nicht-Raster-Layer einfach uebergehen.
-			if (!(layerObj instanceof GridCoverage2D)) {
-				if ((mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-						&& featureLayerIntersectsEnvelope(layer, env))
-					break;
-				continue;
-			}
+    /**
+     * Ermittelt alle Teil-Raster, die in einem Bereich liegen und erzeugt
+     * entsprechende {@link GridCoverageSelectedEvent
+     * GridCoverageSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur das
+     * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
+     * alle sichtbaren Layer durchsucht.
+     *
+     * @param env
+     *            Bounding-Box
+     * @param mode
+     *            Suchmodus
+     * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
+     *         ist
+     */
+    protected boolean findGridCoverageSubsetsAndFireEvents(final Envelope env,
+            final int mode) {
+        final Hashtable<MapLayer, GridCoverage2D> result = findGridCoverageSubsets(
+                env, mode);
+        // Events ausloesen fuer jedes Layer
+        for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+            final MapLayer layer = e.nextElement();
+            final GridCoverage2D subset = result.get(layer);
+            if (subset != null)
+                fireMapPaneEvent(new GridCoverageSelectedEvent(this, layer,
+                        env, subset));
+        }
+        return !result.isEmpty();
+    }
 
-			GridCoverage2D sourceGrid = (GridCoverage2D) layerObj;
-			com.vividsolutions.jts.geom.Envelope jtsEnv = env;
-			org.geotools.geometry.Envelope2D gtEnv2D = JTS.getEnvelope2D(
-					jtsEnv, sourceGrid.getCoordinateReferenceSystem());
-			// org.opengis.spatialschema.geometry.Envelope gtGenEnv = new
-			// GeneralEnvelope
-			// ((org.opengis.spatialschema.geometry.Envelope)gtEnv2D); //
-			// gt2-2.3.4
-			org.opengis.geometry.Envelope gtGenEnv = new GeneralEnvelope(
-					(org.opengis.geometry.Envelope) gtEnv2D); // gt2-2.4.2
+    /**
+     * Ermittelt alle Raster-Werte, die an einer bestimmten Geo-Position liegen.
+     * Beim Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
+     * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
+     * durchsucht.
+     * <p>
+     * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
+     * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
+     * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
+     *
+     * @param point
+     *            Geo-Referenzgeop
+     * @param mode
+     *            Suchmodus
+     * @return eine leere {@link Hashtable} falls keine Werte ermittelt werden
+     *         konnten
+     *
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     *         (University of Bonn/Germany)
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    protected Hashtable<MapLayer, double[]> findGridCoverageValues(
+            Point2D point, int mode) {
+        Hashtable<MapLayer, double[]> result = new Hashtable<MapLayer, double[]>();
 
-			// GridCoverage2D subsetGrid =
-			// (GridCoverage2D)Operations.DEFAULT.crop(sourceGrid,gtGenEnv);
-			GridCoverage2D subsetGrid = GridUtil.createGridCoverage(sourceGrid,
-					gtGenEnv);
-			if (subsetGrid != null)
-				result.put(layer, subsetGrid);
-			// Beim Modus "oberstes Layer selektieren" die Schleife beenden
-			if (mode == SELECT_TOP || mode == SELECT_ONE_FROM_TOP)
-				break;
-		}
-		return result;
-	}
+        if (point == null)
+            return result;
 
-	/**
-	 * Ermittelt alle Teil-Raster, die in einem Bereich liegen und erzeugt
-	 * entsprechende {@link GridCoverageSelectedEvent
-	 * GridCoverageSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur das
-	 * oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL} werden
-	 * alle sichtbaren Layer durchsucht.
-	 * 
-	 * @param env
-	 *            Bounding-Box
-	 * @param mode
-	 *            Suchmodus
-	 * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
-	 *         ist
-	 */
-	protected boolean findGridCoverageSubsetsAndFireEvents(final Envelope env,
-			final int mode) {
-		final Hashtable<MapLayer, GridCoverage2D> result = findGridCoverageSubsets(
-				env, mode);
-		// Events ausloesen fuer jedes Layer
-		for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-			final MapLayer layer = e.nextElement();
-			final GridCoverage2D subset = result.get(layer);
-			if (subset != null)
-				fireMapPaneEvent(new GridCoverageSelectedEvent(this, layer,
-						env, subset));
-		}
-		return !result.isEmpty();
-	}
+        MapContext context = getContext();
+        // Je nach Modus: Alle oder nur das oberste Layer
+        MapLayer[] layerList = context.getLayers();
+        for (int i = layerList.length - 1; i >= 0; i--) {
+            MapLayer layer = layerList[i];
+            if (!layer.isVisible())
+                continue;
+            Object layerObj = getLayerSourceObject(layer);
 
-	/**
-	 * Ermittelt alle Raster-Werte, die an einer bestimmten Geo-Position liegen.
-	 * Beim Modus {@link #SELECT_TOP} wird nur das oberste sichtbare Layer
-	 * durchsucht. Beim Modus {@link #SELECT_ALL} werden alle sichtbaren Layer
-	 * durchsucht.
-	 * <p>
-	 * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
-	 * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
-	 * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
-	 * 
-	 * @param point
-	 *            Geo-Referenzgeop
-	 * @param mode
-	 *            Suchmodus
-	 * @return eine leere {@link Hashtable} falls keine Werte ermittelt werden
-	 *         konnten
-	 * 
-	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-	 *         (University of Bonn/Germany)
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	protected Hashtable<MapLayer, double[]> findGridCoverageValues(
-			Point2D point, int mode) {
-		Hashtable<MapLayer, double[]> result = new Hashtable<MapLayer, double[]>();
+            // LOGGER.info("layerObj = "+layerObj.getClass().getSimpleName());
 
-		if (point == null)
-			return result;
+            // SK 29.9.2007 Vorher:
+            // // Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
+            // abbrechen, wenn nur im
+            // // obersten (sichtbaren) Layer gesucht wird.
+            // // Ansonsten Nicht-Raster-Layer einfach uebergehen.
+            // if ( !(layerObj instanceof GridCoverage2D) ) {
+            // if ( mode == SELECT_TOP &&
+            // featureLayerIntersectsEnvelope(layer,new
+            // Envelope(point.getX(),point.getX(),point.getY(),point.getY())) )
+            // break;
+            // continue;
+            // }
 
-		MapContext context = getContext();
-		// Je nach Modus: Alle oder nur das oberste Layer
-		MapLayer[] layerList = context.getLayers();
-		for (int i = layerList.length - 1; i >= 0; i--) {
-			MapLayer layer = layerList[i];
-			if (!layer.isVisible())
-				continue;
-			Object layerObj = getLayerSourceObject(layer);
+            // Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
+            // abbrechen, wenn nur im
+            // obersten (sichtbaren) Layer gesucht wird.
+            // Ansonsten Nicht-Raster-Layer einfach uebergehen.
+            // SK 29.9.07: Ein AbstractGridCoverage2DReader ist auch ein Raster
+            if (!(layerObj instanceof GridCoverage2D || layerObj instanceof AbstractGridCoverage2DReader)) {
+                final Envelope pointAsEnvelope = new Envelope(point.getX(),
+                        point.getX(), point.getY(), point.getY());
+                if (mode == SELECT_TOP
+                        && featureLayerIntersectsEnvelope(layer,
+                                pointAsEnvelope)) {
+                }
+                continue;
+            }
 
-			// LOGGER.info("layerObj = "+layerObj.getClass().getSimpleName());
+            GridCoverage2D sourceGrid;
 
-			// SK 29.9.2007 Vorher:
-			// // Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
-			// abbrechen, wenn nur im
-			// // obersten (sichtbaren) Layer gesucht wird.
-			// // Ansonsten Nicht-Raster-Layer einfach uebergehen.
-			// if ( !(layerObj instanceof GridCoverage2D) ) {
-			// if ( mode == SELECT_TOP &&
-			// featureLayerIntersectsEnvelope(layer,new
-			// Envelope(point.getX(),point.getX(),point.getY(),point.getY())) )
-			// break;
-			// continue;
-			// }
+            if (layerObj instanceof AbstractGridCoverage2DReader) {
+                // LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
+                // );
+                AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
+                Parameter readGG = new Parameter(
+                        AbstractGridFormat.READ_GRIDGEOMETRY2D);
 
-			// Bei einem Nicht-Raster-Layer, das den Punkt beinhaltet,
-			// abbrechen, wenn nur im
-			// obersten (sichtbaren) Layer gesucht wird.
-			// Ansonsten Nicht-Raster-Layer einfach uebergehen.
-			// SK 29.9.07: Ein AbstractGridCoverage2DReader ist auch ein Raster
-			if (!(layerObj instanceof GridCoverage2D || layerObj instanceof AbstractGridCoverage2DReader)) {
-				final Envelope pointAsEnvelope = new Envelope(point.getX(),
-						point.getX(), point.getY(), point.getY());
-				if (mode == SELECT_TOP
-						&& featureLayerIntersectsEnvelope(layer,
-								pointAsEnvelope)) {
-				}
-				continue;
-			}
+                ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(
+                        mapArea, context.getCoordinateReferenceSystem());
 
-			GridCoverage2D sourceGrid;
+                readGG.setValue(new GridGeometry2D(new GeneralGridRange(
+                        getBounds()), mapExtend));
 
-			if (layerObj instanceof AbstractGridCoverage2DReader) {
-				// LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
-				// );
-				AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
-				Parameter readGG = new Parameter(
-						AbstractGridFormat.READ_GRIDGEOMETRY2D);
+                try {
+                    sourceGrid = (GridCoverage2D) reader
+                            .read(new GeneralParameterValue[] { readGG });
+                } catch (Exception e) {
+                    LOGGER.error(e);
+                    continue;
+                }
+            } else {
+                // Ein instanceof ist nicht noetig, da sonst schon break oder
+                // continue aufgerufen worden waere
+                sourceGrid = (GridCoverage2D) layerObj;
+            }
 
-				ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(
-						mapArea, context.getCoordinateReferenceSystem());
+            // vorher: double[] value = new double[2];
 
-				readGG.setValue(new GridGeometry2D(new GeneralGridRange(
-						getBounds()), mapExtend));
+            // getNumSampleDimensions gibt die Anzahl der Baender des Rasters
+            // zurueck.
+            double[] values = new double[sourceGrid.getNumSampleDimensions()];
 
-				try {
-					sourceGrid = (GridCoverage2D) reader
-							.read(new GeneralParameterValue[] { readGG });
-				} catch (Exception e) {
-					LOGGER.error(e);
-					continue;
-				}
-			} else {
-				// Ein instanceof ist nicht noetig, da sonst schon break oder
-				// continue aufgerufen worden waere
-				sourceGrid = (GridCoverage2D) layerObj;
-			}
+            try {
+                // Grid an Geo-Position auswerten
+                sourceGrid.evaluate(point, values);
+            } catch (CannotEvaluateException err) {
+                // z.B. Punkt ausserhalb des Rasters --> Layer uebergehen
+                continue;
+            } catch (Exception e) {
+                LOGGER.error(e);
+                continue;
+            }
 
-			// vorher: double[] value = new double[2];
+            // SK: voher wurde nur der erste Wert zurueckgegeben
+            // result.put(layer,value[0]);
+            // jetzt werden alle werte zueuckgegeben
 
-			// getNumSampleDimensions gibt die Anzahl der Baender des Rasters
-			// zurueck.
-			double[] values = new double[sourceGrid.getNumSampleDimensions()];
+            result.put(layer, values);
+            // Beim Modus "oberstes Layer selektieren" die Schleife beenden
+            if (mode == SELECT_TOP)
+                break;
+        }
+        return result;
+    }
 
-			try {
-				// Grid an Geo-Position auswerten
-				sourceGrid.evaluate(point, values);
-			} catch (CannotEvaluateException err) {
-				// z.B. Punkt ausserhalb des Rasters --> Layer uebergehen
-				continue;
-			} catch (Exception e) {
-				LOGGER.error(e);
-				continue;
-			}
+    /**
+     * Ermittelt die Raster-Werte, die an einem Punkt liegen und erzeugt
+     * entsprechende {@link GridCoverageValueSelectedEvent
+     * GridCoverageValueSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur
+     * das oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL}
+     * werden alle sichtbaren Layer durchsucht.
+     * <p>
+     * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
+     * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
+     * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
+     *
+     * @param point
+     *            Geo-Referenz
+     * @param mode
+     *            Suchmodus
+     * @return eine leere {@link Hashtable} falls der Punkt {@code null} ist
+     *
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     *         (University of Bonn/Germany)
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    protected boolean findGridCoverageValuesAndFireEvents(Point2D point,
+            int mode) {
+        Hashtable<MapLayer, double[]> result = findGridCoverageValues(point,
+                mode);
 
-			// SK: voher wurde nur der erste Wert zurueckgegeben
-			// result.put(layer,value[0]);
-			// jetzt werden alle werte zueuckgegeben
+        // Events ausloesen fuer jedes Layer
+        for (Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+            MapLayer layer = e.nextElement();
+            double[] values = result.get(layer);
+            fireMapPaneEvent(new GridCoverageValueSelectedEvent(this, layer,
+                    point, values));
+        }
+        return !result.isEmpty();
+    }
 
-			result.put(layer, values);
-			// Beim Modus "oberstes Layer selektieren" die Schleife beenden
-			if (mode == SELECT_TOP)
-				break;
-		}
-		return result;
-	}
+//  /**
+//   * Bereitet einen BoundingBox-Filter vor. Das "linke" Attribut der
+//   * Expression (das Feature-Attribut, auf das der Filter angewendet wird),
+//   * wird dabei noch nicht belegt. Dies geschieht erst bei der Auswertung
+//   * entsprechend des jeweiligen Layers
+//   *
+//   * @param env
+//   *            Bounding-Box
+//   */
+//  private static GeometryFilterImpl createBoundingBoxFilter(Envelope env) {
+//      // Filter fuer Envelope zusammenstellen
+//      Expression bbox = ff.createBBoxExpression(env);
+//      GeometryFilterImpl bboxFilter = (GeometryFilterImpl) ff
+//              .createGeometryFilter(AbstractFilter.GEOMETRY_BBOX);
+//      // GeometryFilterImpl bboxFilter =
+//      // (GeometryFilterImpl)ff.createGeometryFilter
+//      // (AbstractFilter.GEOMETRY_WITHIN);
+//      bboxFilter.setExpression2(bbox);
+//      return bboxFilter;
+//  }
+//
+//  /**
+//   * Bereitet einen Punkt-Filter vor. Das "linke" Attribut der Expression (das
+//   * Feature-Attribut, auf das der Filter angewendet wird), wird dabei noch
+//   * nicht belegt. Dies geschieht erst bei der Auswertung entsprechend des
+//   * jeweiligen Layers
+//   *
+//   * @param point
+//   *            Geo-Koordinate
+//   */
+//  private static GeometryFilterImpl createPointFilter(Point2D point) {
+//      // Filter fuer Envelope zusammenstellen
+//      Geometry geometry = gf.createPoint(new Coordinate(point.getX(), point
+//              .getY()));
+//      GeometryFilterImpl pointFilter = (GeometryFilterImpl) ff
+//              .createGeometryFilter(GeometryFilterImpl.GEOMETRY_CONTAINS);
+//      pointFilter.setExpression2(ff.createLiteralExpression(geometry));
+//      return pointFilter;
+//  }
+//
+//  /**
+//   * Bereitet einen "InDerNaehe von" Distance-Filter vor. Das "linke" Attribut
+//   * der Expression (das Feature-Attribut, auf das der Filter angewendet
+//   * wird), wird dabei noch nicht belegt. Dies geschieht erst bei der
+//   * Auswertung entsprechend des jeweiligen Layers
+//   *
+//   * Wird benoetigt, um mit der Maus einen Punkt zu treffen.
+//   *
+//   * @param point
+//   *            Geo-Koordinate
+//   * @param dist
+//   *            Distanz zum Punkt in Einheiten des Layers
+//   *
+//   *            TODO SK Auf FilterFactory2 ändern... Beispiel von
+//   *            http://docs.codehaus.org/display/GEOTDOC/Filter+Examples
+//   *            funktioniert erst ab 2.5 ?? Vor dem Distcheck einen BBOX check
+//   *            sollte die geschwindigkeit erhöhen.
+//   *
+//   * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+//   *         Kr&uuml;ger</a>
+//   */
+//  private static GeometryFilterImpl createNearPointFilter(
+//          final Point2D point, final Double dist) {
+//      // Filter fuer Envelope zusammenstellen
+//      final Geometry geometry = gf.createPoint(new Coordinate(point.getX(),
+//              point.getY()));
+//
+//      final DWithinImpl dwithinFilter = (DWithinImpl) ff
+//              .createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
+//
+//      dwithinFilter.setDistance(dist);
+//
+//      dwithinFilter.setExpression2(ff.createLiteralExpression(geometry));
+//
+//      return dwithinFilter;
+//  }
 
-	/**
-	 * Ermittelt die Raster-Werte, die an einem Punkt liegen und erzeugt
-	 * entsprechende {@link GridCoverageValueSelectedEvent
-	 * GridCoverageValueSelectedEvents}. Beim Modus {@link #SELECT_TOP} wird nur
-	 * das oberste sichtbare Layer durchsucht. Beim Modus {@link #SELECT_ALL}
-	 * werden alle sichtbaren Layer durchsucht.
-	 * <p>
-	 * SK: 28.09.2007 Da ein Rasterlayer auch mehrere Baender haben kann, ist es
-	 * sinnvoll, nicht <code>Hashtable MapLayer,Double </code> sondern
-	 * <code>Hashtable MapLayer,Double[] </code> zurueckzugeben.
-	 * 
-	 * @param point
-	 *            Geo-Referenz
-	 * @param mode
-	 *            Suchmodus
-	 * @return eine leere {@link Hashtable} falls der Punkt {@code null} ist
-	 * 
-	 * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
-	 *         (University of Bonn/Germany)
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	protected boolean findGridCoverageValuesAndFireEvents(Point2D point,
-			int mode) {
-		Hashtable<MapLayer, double[]> result = findGridCoverageValues(point,
-				mode);
+    /**
+     * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
+     * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
+     * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
+     * Attribut mit dem Namen "GridCoverage" hat.
+     *
+     * SK: Pyramidenlayer aka AbstractGridCoverage2DReader geben auch true
+     * zurück.
+     *
+     * @param layer
+     *            zu ueberpruefendes Layer
+     */
+    public static boolean isGridCoverageLayer(MapLayer layer) {
+        final Object layerSourceObject = getLayerSourceObject(layer);
+        boolean b = (layerSourceObject instanceof GridCoverage2D)
+                || (layerSourceObject instanceof AbstractGridCoverage2DReader);
+        // if (!b && layerSourceObject instanceof DefaultFeatureResults){
+        // DefaultFeatureResults dfr = (DefaultFeatureResults)
+        // layerSourceObject;
+        // }
+        // LOGGER.debug(b+"= "+layerSourceObject.getClass().getSimpleName()+" "+
+        // layer.getTitle());
+        return b;
+        // try {
+        // FeatureCollection fc = layer.getFeatureSource().getFeatures();
+        // // Layer muss genau ein Feature beinhalten
+        // if ( fc == null || fc.size() != 1 )
+        // return false;
+        // // Feature muss genau 1 Attribut mit dem Namen "GridCoverage" haben
+        // FeatureType ftype = fc.getFeatureType();
+        // if ( ftype == null || ftype.getAttributeCount() != 1 ||
+        // !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(0).getName())
+        // )
+        // return false;
+        // } catch (Exception err) {
+        // }
+        // return true;
+    }
 
-		// Events ausloesen fuer jedes Layer
-		for (Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-			MapLayer layer = e.nextElement();
-			double[] values = result.get(layer);
-			fireMapPaneEvent(new GridCoverageValueSelectedEvent(this, layer,
-					point, values));
-		}
-		return !result.isEmpty();
-	}
+    /**
+     * Liefert das Objekt ({@link GridCoverage2D} oder {@link FeatureCollection}
+     * oder {@link AbstractGridCoverageReader} auf dem ein Layer basiert. Ein
+     * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
+     * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
+     * Attribut mit Namen "GridCoverage" und Typ {@code GridCoverage2D} oder
+     * {@link AbstractGridCoverageReader} hat. Sind diese Bedingungen erfuellt,
+     * wird das 2. Attribut zurueckgegeben, ansonsten die
+     * {@link FeatureCollection}.
+     *
+     * @param layer
+     *            ein Layer
+     * @return {@code null}, falls das Objekt nicht ermittelt werden kann (da
+     *         ein Fehler aufgetreten ist).
+     */
+    public static Object getLayerSourceObject(MapLayer layer) {
+        try {
+            final FeatureSource featureSource = layer.getFeatureSource();
+            FeatureCollection fc = featureSource.getFeatures();
+            // RasterLayer muss genau ein Feature beinhalten
+            // Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
+            if (fc == null || fc.size() != 1) {
 
-	/**
-	 * Bereitet einen BoundingBox-Filter vor. Das "linke" Attribut der
-	 * Expression (das Feature-Attribut, auf das der Filter angewendet wird),
-	 * wird dabei noch nicht belegt. Dies geschieht erst bei der Auswertung
-	 * entsprechend des jeweiligen Layers
-	 * 
-	 * @param env
-	 *            Bounding-Box
-	 */
-	private static GeometryFilterImpl createBoundingBoxFilter(Envelope env) {
-		// Filter fuer Envelope zusammenstellen
-		Expression bbox = ff.createBBoxExpression(env);
-		GeometryFilterImpl bboxFilter = (GeometryFilterImpl) ff
-				.createGeometryFilter(AbstractFilter.GEOMETRY_BBOX);
-		// GeometryFilterImpl bboxFilter =
-		// (GeometryFilterImpl)ff.createGeometryFilter
-		// (AbstractFilter.GEOMETRY_WITHIN);
-		bboxFilter.setExpression2(bbox);
-		return bboxFilter;
-	}
+                return fc;
+            }
+            // FeatureType des RasterLayer muss genau 1 Attribut mit Namen
+            // "GridCoverage"
+            // Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
+            FeatureType ftype = fc.getFeatureType();
+            if (ftype == null
+                    || ftype.getAttributeCount() != 1
+                    || !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(
+                            0).getLocalName()))
+                return fc;
+            // (Einziges) Feature muss genau 2 Attribute besitzen, wobei das
+            // erste vom
+            // Typ Geometry ist und das zweite vom Typ GridCoverage2D
+            // sonst: FeatureCollextion zurueckgeben
 
-	/**
-	 * Bereitet einen Punkt-Filter vor. Das "linke" Attribut der Expression (das
-	 * Feature-Attribut, auf das der Filter angewendet wird), wird dabei noch
-	 * nicht belegt. Dies geschieht erst bei der Auswertung entsprechend des
-	 * jeweiligen Layers
-	 * 
-	 * @param point
-	 *            Geo-Koordinate
-	 */
-	private static GeometryFilterImpl createPointFilter(Point2D point) {
-		// Filter fuer Envelope zusammenstellen
-		Geometry geometry = gf.createPoint(new Coordinate(point.getX(), point
-				.getY()));
-		GeometryFilterImpl pointFilter = (GeometryFilterImpl) ff
-				.createGeometryFilter(GeometryFilterImpl.GEOMETRY_CONTAINS);
-		pointFilter.setExpression2(ff.createLiteralExpression(geometry));
-		return pointFilter;
-	}
+            /** CHANGE SK 9.8.08 BEGIN */
+            Feature f = fc.features().next();
+            if ((f.getFeatureType().getTypeName().equals("GridCoverage") && f
+                    .getNumberOfAttributes() >= 2)) {
+                // I am sure, that it is a raster some. We do not have to cast
+                // it to either cridcoverage or abstractReader, as the results
+                // are tested anyway...
+                return f.getAttribute(1);
+            }
+            /** CHANGE SK 9.8.08 END */
 
-	/**
-	 * Bereitet einen "InDerNaehe von" Distance-Filter vor. Das "linke" Attribut
-	 * der Expression (das Feature-Attribut, auf das der Filter angewendet
-	 * wird), wird dabei noch nicht belegt. Dies geschieht erst bei der
-	 * Auswertung entsprechend des jeweiligen Layers
-	 * 
-	 * Wird benoetigt, um mit der Maus einen Punkt zu treffen.
-	 * 
-	 * @param point
-	 *            Geo-Koordinate
-	 * @param dist
-	 *            Distanz zum Punkt in Einheiten des Layers
-	 * 
-	 *            TODO SK Auf FilterFactory2 ändern... Beispiel von
-	 *            http://docs.codehaus.org/display/GEOTDOC/Filter+Examples
-	 *            funktioniert erst ab 2.5 ?? Vor dem Distcheck einen BBOX check
-	 *            sollte die geschwindigkeit erhöhen.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	private static GeometryFilterImpl createNearPointFilter(
-			final Point2D point, final Double dist) {
-		// Filter fuer Envelope zusammenstellen
-		final Geometry geometry = gf.createPoint(new Coordinate(point.getX(),
-				point.getY()));
+            if (f.getNumberOfAttributes() != 2
+                    || // Geaendert, da es bei AbstractGridCoverageReader 3 sind
+                    // (SK, 19.08.07)
+                    !(f.getAttribute(0) instanceof com.vividsolutions.jts.geom.Geometry)
+                    || !(f.getAttribute(1) instanceof GridCoverage2D))
+                return fc;
 
-		final DWithinImpl dwithinFilter = (DWithinImpl) ff
-				.createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
+            // Objekt ist ein Raster!
+            return (GridCoverage2D) f.getAttribute(1);
+        } catch (Exception err) {
+            LOGGER.warn(err.getMessage(), err);
+            return null;
+        }
+    }
 
-		dwithinFilter.setDistance(dist);
+    /**
+     * Should be called when the {@link JMapPane} is not needed no more to help
+     * the GarbageCollector
+     *
+     * Removes all {@link JMapPaneListener}s that are registered
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
 
-		dwithinFilter.setExpression2(ff.createLiteralExpression(geometry));
+    public void dispose() {
+        if (isDisposed())
+            return;
 
-		return dwithinFilter;
-	}
+        if (dragWaitCursorListener != null)
+            this.removeMouseListener(dragWaitCursorListener);
+        if (mouseWheelZoomListener != null)
+            this.removeMouseWheelListener(mouseWheelZoomListener);
 
-	/**
-	 * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
-	 * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
-	 * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
-	 * Attribut mit dem Namen "GridCoverage" hat.
-	 * 
-	 * SK: Pyramidenlayer aka AbstractGridCoverage2DReader geben auch true
-	 * zurück.
-	 * 
-	 * @param layer
-	 *            zu ueberpruefendes Layer
-	 */
-	public static boolean isGridCoverageLayer(MapLayer layer) {
-		final Object layerSourceObject = getLayerSourceObject(layer);
-		boolean b = (layerSourceObject instanceof GridCoverage2D)
-				|| (layerSourceObject instanceof AbstractGridCoverage2DReader);
-		// if (!b && layerSourceObject instanceof DefaultFeatureResults){
-		// DefaultFeatureResults dfr = (DefaultFeatureResults)
-		// layerSourceObject;
-		// }
-		// LOGGER.debug(b+"= "+layerSourceObject.getClass().getSimpleName()+" "+
-		// layer.getTitle());
-		return b;
-		// try {
-		// FeatureCollection fc = layer.getFeatureSource().getFeatures();
-		// // Layer muss genau ein Feature beinhalten
-		// if ( fc == null || fc.size() != 1 )
-		// return false;
-		// // Feature muss genau 1 Attribut mit dem Namen "GridCoverage" haben
-		// FeatureType ftype = fc.getFeatureType();
-		// if ( ftype == null || ftype.getAttributeCount() != 1 ||
-		// !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(0).getName())
-		// )
-		// return false;
-		// } catch (Exception err) {
-		// }
-		// return true;
-	}
+        // Alle mapPaneListener entfernen
+        mapPaneListeners.clear();
 
-	/**
-	 * Liefert das Objekt ({@link GridCoverage2D} oder {@link FeatureCollection}
-	 * oder {@link AbstractGridCoverageReader} auf dem ein Layer basiert. Ein
-	 * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
-	 * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
-	 * Attribut mit Namen "GridCoverage" und Typ {@code GridCoverage2D} oder
-	 * {@link AbstractGridCoverageReader} hat. Sind diese Bedingungen erfuellt,
-	 * wird das 2. Attribut zurueckgegeben, ansonsten die
-	 * {@link FeatureCollection}.
-	 * 
-	 * @param layer
-	 *            ein Layer
-	 * @return {@code null}, falls das Objekt nicht ermittelt werden kann (da
-	 *         ein Fehler aufgetreten ist).
-	 */
-	public static Object getLayerSourceObject(MapLayer layer) {
-		try {
-			final FeatureSource featureSource = layer.getFeatureSource();
-			FeatureCollection fc = featureSource.getFeatures();
-			// RasterLayer muss genau ein Feature beinhalten
-			// Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
-			if (fc == null || fc.size() != 1) {
+        getContext().clearLayerList();
 
-				return fc;
-			}
-			// FeatureType des RasterLayer muss genau 1 Attribut mit Namen
-			// "GridCoverage"
-			// Ist dies nicht der Fall wird die FeatureCollection zurueckgegeben
-			FeatureType ftype = fc.getFeatureType();
-			if (ftype == null
-					|| ftype.getAttributeCount() != 1
-					|| !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(
-							0).getLocalName()))
-				return fc;
-			// (Einziges) Feature muss genau 2 Attribute besitzen, wobei das
-			// erste vom
-			// Typ Geometry ist und das zweite vom Typ GridCoverage2D
-			// sonst: FeatureCollextion zurueckgeben
+        removeAll();
+        disposed = true;
+    }
 
-			/** CHANGE SK 9.8.08 BEGIN */
-			Feature f = fc.features().next();
-			if ((f.getFeatureType().getTypeName().equals("GridCoverage") && f
-					.getNumberOfAttributes() >= 2)) {
-				// I am sure, that it is a raster some. We do not have to cast
-				// it to either cridcoverage or abstractReader, as the results
-				// are tested anyway...
-				return f.getAttribute(1);
-			}
-			/** CHANGE SK 9.8.08 END */
+    /**
+     * A flag indicating if dispose() has already been called. If true, then
+     * further use of this {@link JMapPane} is undefined.
+     */
+    private boolean isDisposed() {
+        return disposed;
+    }
 
-			if (f.getNumberOfAttributes() != 2
-					|| // Geaendert, da es bei AbstractGridCoverageReader 3 sind
-					// (SK, 19.08.07)
-					!(f.getAttribute(0) instanceof com.vividsolutions.jts.geom.Geometry)
-					|| !(f.getAttribute(1) instanceof GridCoverage2D))
-				return fc;
+    //
+    // /**
+    // * Werden Rasterlayer waehrend einer PAN Aktion versteckt?
+    // * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+    // Kr&uuml;ger</a>
+    // */
+    // public boolean isHideRasterLayersDuringPan() {
+    // return hideRasterLayersDuringPan;
+    // }
+    //
+    // /**
+    // * Bestimmt, ob Rasterlayer waehrend einer PAN Aktion versteckt werden
+    // soll. Default ist false.
+    // * @param hideRasterLayersDuringPan
+    // * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+    // Kr&uuml;ger</a>
+    // */
+    // public void setHideRasterLayersDuringPan(boolean
+    // hideRasterLayersDuringPan) {
+    // this.hideRasterLayersDuringPan = hideRasterLayersDuringPan;
+    // }
 
-			// Objekt ist ein Raster!
-			return (GridCoverage2D) f.getAttribute(1);
-		} catch (Exception err) {
-			LOGGER.warn(err.getMessage(), err);
-			return null;
-		}
-	}
+    public boolean isSetWaitCursorDuringNextRepaint() {
+        return setWaitCursorDuringNextRepaint;
+    }
 
-	/**
-	 * Should be called when the {@link JMapPane} is not needed no more to help
-	 * the GarbageCollector
-	 * 
-	 * Removes all {@link JMapPaneListener}s that are registered
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
+    /**
+     * When setting this to true, the next repaint of this component will be
+     * accompanied by a WAIT Cursor
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void setWaitCursorDuringNextRepaint(
+            boolean waitCursorDuringNextRepaint) {
+        this.setWaitCursorDuringNextRepaint = waitCursorDuringNextRepaint;
+    }
 
-	public void dispose() {
-		if (isDisposed())
-			return;
+    /**
+     * Gibt den "normalen" Cursor zurueck. Dieser kann neben dem "pointer" auch
+     * ein Sanduhr-Wartecursor sein.
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public Cursor getNormalCursor() {
+        return normalCursor;
+    }
 
-		if (dragWaitCursorListener != null)
-			this.removeMouseListener(dragWaitCursorListener);
-		if (mouseWheelZoomListener != null)
-			this.removeMouseWheelListener(mouseWheelZoomListener);
+    /**
+     * Setzt den "normalen" Cursor. Dieser kann neben dem default "pointer" z.B.
+     * auch ein Sanduhr-Wartecursor sein.
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    public void setNormalCursor(Cursor normalCursor) {
+        this.normalCursor = normalCursor;
+    }
 
-		// Alle mapPaneListener entfernen
-		mapPaneListeners.clear();
+    // /**
+    // * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
+    // * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
+    // * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
+    // Attribut
+    // * vom Type {@link org.geotools.feature.type.FeatureAttributeType} hat,
+    // welches
+    // * wiederum genau zwei Attribute hat:<br>
+    // * Eines vom Typ {@link
+    // org.opengis.spatialschema.geometry.geometry.Polygon}
+    // * und eines vom Typ {@link org.opengis.coverage.grid.GridCoverage}.
+    // * @param layer zu ueberpruefendes Layer
+    // */
+    // public static boolean isGridCoverageLayer(MapLayer layer) {
+    // try {
+    // FeatureCollection fc = layer.getFeatureSource().getFeatures();
+    // // Layer muss genau ein Feature beinhalten
+    // if ( fc == null || fc.size() != 1 )
+    // return false;
+    // // Feature muss genau 1 Attribut vom Typ FeatureAttributeType haben
+    // FeatureType ftype = fc.getFeatureType();
+    // if ( ftype == null || ftype.getAttributeCount() != 1 ||
+    // !(ftype.getAttributeType(0) instanceof
+    // org.geotools.feature.type.FeatureAttributeType) )
+    // return false;
+    // // FeatureAttribute muss genau 2 Atrribute haben
+    // org.geotools.feature.type.FeatureAttributeType atype =
+    // (org.geotools.feature
+    // .type.FeatureAttributeType)ftype.getAttributeType(0);
+    // if ( atype == null || atype.getAttributeCount() != 2 )
+    // return false;
+    // // Typ des ersten Attributs muss Polygon sein
+    // if ( !com.vividsolutions.jts.geom.Polygon.class.isAssignableFrom(
+    // atype.getAttributeType(0).getType() ) )
+    // return false;
+    // // Typ des zweiten Attributs muss GridCoverage sein
+    // if ( !org.opengis.coverage.grid.GridCoverage.class.isAssignableFrom(
+    // atype.getAttributeType(1).getType() ) )
+    // return false;
+    //
+    // } catch (Exception err) {
+    // }
+    // return true;
+    // }
 
-		getContext().clearLayerList();
+    /**
+     * Nuetzlich wenn die Componente gedruckt wird. Dann werden wird der
+     * Hintergrund auf WEISS gesetzt.
+     *
+     * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+     *         Kr&uuml;ger</a>
+     */
+    @Override
+    public void print(Graphics g) {
+        Color orig = getBackground();
+        setBackground(Color.WHITE);
 
-		removeAll();
-		disposed = true;
-	}
+        // wrap in try/finally so that we always restore the state
+        try {
+            super.print(g);
+        } finally {
+            setBackground(orig);
+        }
+    }
 
-	/**
-	 * A flag indicating if dispose() has already been called. If true, then
-	 * further use of this {@link JMapPane} is undefined.
-	 */
-	private boolean isDisposed() {
-		return disposed;
-	}
+    /**
+     * Sets the mapArea to smartly present the given features. Note: The method
+     * does not call {@link #repaint()} on the {@link JMapPane}.
+     */
+    public void zoomTo(org.geotools.feature.Feature feature) {
+        final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
+                .getFeatureType());
+        mfc.add(feature);
+        zoomTo(mfc);
+    }
 
-	//
-	// /**
-	// * Werden Rasterlayer waehrend einer PAN Aktion versteckt?
-	// * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	// Kr&uuml;ger</a>
-	// */
-	// public boolean isHideRasterLayersDuringPan() {
-	// return hideRasterLayersDuringPan;
-	// }
-	//
-	// /**
-	// * Bestimmt, ob Rasterlayer waehrend einer PAN Aktion versteckt werden
-	// soll. Default ist false.
-	// * @param hideRasterLayersDuringPan
-	// * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	// Kr&uuml;ger</a>
-	// */
-	// public void setHideRasterLayersDuringPan(boolean
-	// hideRasterLayersDuringPan) {
-	// this.hideRasterLayersDuringPan = hideRasterLayersDuringPan;
-	// }
+    /**
+     * Sets the mapArea to best possibly present the given features. If only one
+     * single point is given, the window is moved over the point.
+     *
+     * Note: The method does not call {@link #repaint()} on the {@link JMapPane}
+     * .
+     *
+     * @param features
+     *            if <code>null</code> or size==0, the function doesn nothing.
+     */
+    public void zoomTo(FeatureCollection features) {
 
-	public boolean isSetWaitCursorDuringNextRepaint() {
-		return setWaitCursorDuringNextRepaint;
-	}
+        CoordinateReferenceSystem mapCRS = getContext()
+                .getCoordinateReferenceSystem();
+        CoordinateReferenceSystem fCRS = features.getSchema()
+                .getDefaultGeometry().getCoordinateSystem();
+        // if (! mapCRS.equals(fCRS)) {
+        // throw new
+        // RuntimeException("Projecting the features to show to the map CRS is not yet implemented.");
+        // }
 
-	/**
-	 * When setting this to true, the next repaint of this component will be
-	 * accompanied by a WAIT Cursor
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void setWaitCursorDuringNextRepaint(
-			boolean waitCursorDuringNextRepaint) {
-		this.setWaitCursorDuringNextRepaint = waitCursorDuringNextRepaint;
-	}
+        double width = mapArea.getWidth();
+        double height = mapArea.getHeight();
+        double ratio = height / width;
 
-	/**
-	 * Gibt den "normalen" Cursor zurueck. Dieser kann neben dem "pointer" auch
-	 * ein Sanduhr-Wartecursor sein.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public Cursor getNormalCursor() {
-		return normalCursor;
-	}
+        if (features == null || features.size() == 0) {
+            // feature count == 0 Zoom to the full extend
+            return;
+        } else if (features.size() == 1) {
 
-	/**
-	 * Setzt den "normalen" Cursor. Dieser kann neben dem default "pointer" z.B.
-	 * auch ein Sanduhr-Wartecursor sein.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	public void setNormalCursor(Cursor normalCursor) {
-		this.normalCursor = normalCursor;
-	}
+            // feature count == 1 Just move the window to the point and zoom 'a
+            // bit'
+            Feature singleFeature = (Feature) features.iterator().next();
 
-	// /**
-	// * Prueft, ob es sich bei einem Layer um ein Raster-Layer handelt.
-	// * Raster-Layer zeichnen sich dadurch aus, dass die zugrunde liegende
-	// * {@link FeatureCollection} nur ein Feature enthaelt, das genau ein
-	// Attribut
-	// * vom Type {@link org.geotools.feature.type.FeatureAttributeType} hat,
-	// welches
-	// * wiederum genau zwei Attribute hat:<br>
-	// * Eines vom Typ {@link
-	// org.opengis.spatialschema.geometry.geometry.Polygon}
-	// * und eines vom Typ {@link org.opengis.coverage.grid.GridCoverage}.
-	// * @param layer zu ueberpruefendes Layer
-	// */
-	// public static boolean isGridCoverageLayer(MapLayer layer) {
-	// try {
-	// FeatureCollection fc = layer.getFeatureSource().getFeatures();
-	// // Layer muss genau ein Feature beinhalten
-	// if ( fc == null || fc.size() != 1 )
-	// return false;
-	// // Feature muss genau 1 Attribut vom Typ FeatureAttributeType haben
-	// FeatureType ftype = fc.getFeatureType();
-	// if ( ftype == null || ftype.getAttributeCount() != 1 ||
-	// !(ftype.getAttributeType(0) instanceof
-	// org.geotools.feature.type.FeatureAttributeType) )
-	// return false;
-	// // FeatureAttribute muss genau 2 Atrribute haben
-	// org.geotools.feature.type.FeatureAttributeType atype =
-	// (org.geotools.feature
-	// .type.FeatureAttributeType)ftype.getAttributeType(0);
-	// if ( atype == null || atype.getAttributeCount() != 2 )
-	// return false;
-	// // Typ des ersten Attributs muss Polygon sein
-	// if ( !com.vividsolutions.jts.geom.Polygon.class.isAssignableFrom(
-	// atype.getAttributeType(0).getType() ) )
-	// return false;
-	// // Typ des zweiten Attributs muss GridCoverage sein
-	// if ( !org.opengis.coverage.grid.GridCoverage.class.isAssignableFrom(
-	// atype.getAttributeType(1).getType() ) )
-	// return false;
-	//
-	// } catch (Exception err) {
-	// }
-	// return true;
-	// }
+            if (singleFeature.getDefaultGeometry().getCoordinates().length > 1) {
+                // System.out.println("Zoomed to only pne poylgon");
+                // Poly
+                // TODO max width vs. height
+                width = features.getBounds().getWidth() * 3;
+                height = ratio * width;
+            } else {
+                // System.out.println("Zoomed in a bit becasue only one point");
+                // width *= .9;
+                // height *= .9;
+            }
 
-	/**
-	 * Nuetzlich wenn die Componente gedruckt wird. Dann werden wird der
-	 * Hintergrund auf WEISS gesetzt.
-	 * 
-	 * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
-	 *         Kr&uuml;ger</a>
-	 */
-	@Override
-	public void print(Graphics g) {
-		Color orig = getBackground();
-		setBackground(Color.WHITE);
+            Coordinate centre = features.getBounds().centre();
+            if (!mapCRS.equals(fCRS)) {
+                // only to calculations if the CRS differ
+                try {
+                    MathTransform fToMap;
+                    fToMap = CRS.findMathTransform(fCRS, mapCRS);
+                    // centre is transformed to the mapCRS
+                    centre = JTS.transform(centre, null, fToMap);
+                } catch (FactoryException e) {
+                    LOGGER.error(e);
+                } catch (TransformException e) {
+                    LOGGER.error(e);
+                }
+            }
 
-		// wrap in try/finally so that we always restore the state
-		try {
-			super.print(g);
-		} finally {
-			setBackground(orig);
-		}
-	}
+            Coordinate newLeftBottom = new Coordinate(centre.x - width / 2.,
+                    centre.y - height / 2.);
+            Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
+                    centre.y + height / 2.);
 
-	/**
-	 * Sets the mapArea to smartly present the given features. Note: The method
-	 * does not call {@link #repaint()} on the {@link JMapPane}.
-	 */
-	public void zoomTo(org.geotools.feature.Feature feature) {
-		final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
-				.getFeatureType());
-		mfc.add(feature);
-		zoomTo(mfc);
-	}
+            Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
 
-	/**
-	 * Sets the mapArea to best possibly present the given features. If only one
-	 * single point is given, the window is moved over the point.
-	 * 
-	 * Note: The method does not call {@link #repaint()} on the {@link JMapPane}
-	 * .
-	 * 
-	 * @param features
-	 *            if <code>null</code> or size==0, the function doesn nothing.
-	 */
-	public void zoomTo(FeatureCollection features) {
+            setMapArea(newMapArea);
 
-		CoordinateReferenceSystem mapCRS = getContext()
-				.getCoordinateReferenceSystem();
-		CoordinateReferenceSystem fCRS = features.getSchema()
-				.getDefaultGeometry().getCoordinateSystem();
-		// if (! mapCRS.equals(fCRS)) {
-		// throw new
-		// RuntimeException("Projecting the features to show to the map CRS is not yet implemented.");
-		// }
+        } else {
+            ReferencedEnvelope fBounds = features.getBounds();
 
-		double width = mapArea.getWidth();
-		double height = mapArea.getHeight();
-		double ratio = height / width;
+            Envelope bounds;
+            if (!mapCRS.equals(fCRS)) {
+                bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
+            } else {
+                bounds = fBounds;
+            }
+            // BB umrechnen von Layer-CRS in Map-CRS
 
-		if (features == null || features.size() == 0) {
-			// feature count == 0 Zoom to the full extend
-			return;
-		} else if (features.size() == 1) {
+            // Expand a bit
+            bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
 
-			// feature count == 1 Just move the window to the point and zoom 'a
-			// bit'
-			Feature singleFeature = (Feature) features.iterator().next();
+            setMapArea(bounds);
+        }
+    }
 
-			if (singleFeature.getDefaultGeometry().getCoordinates().length > 1) {
-				// System.out.println("Zoomed to only pne poylgon");
-				// Poly
-				// TODO max width vs. height
-				width = features.getBounds().getWidth() * 3;
-				height = ratio * width;
-			} else {
-				// System.out.println("Zoomed in a bit becasue only one point");
-				// width *= .9;
-				// height *= .9;
-			}
+    /**
+     * The {@link GeomFilterGenerator} prepares a {@link BinarySpatialOperator} filter
+     * for multiple use. Only the "right" argument is prepared. The "left" argument
+     * (the geometry attribute of the {@link FeatureSource} to filter) is
+     * first set on calling {@link #adaptFilter(FeatureSource)} for a specific
+     * {@link FeatureSource}. This method also takes care to recreate the filter
+     * (or its "right" argument) if the given {@link FeatureSource} has another
+     * {@link CoordinateReferenceSystem} than the base constraint.<br>
+     * The type of filter (e.g. distance or bounding box) is specified by
+     * the subclass implemenation of {@link #prepareFilter(CoordinateReferenceSystem)}.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     */
+    private static abstract class GeomFilterGenerator {
+      /** Holds the {@link CoordinateReferenceSystem} the filter constraint
+       *  bases on. */
+      protected CoordinateReferenceSystem baseCRS = null;
+      /** Caches the base filter constraint for several
+       *  {@link CoordinateReferenceSystem CoordinateReferenceSystems}. */
+      protected Map<CoordinateReferenceSystem, GeometryFilterImpl> filterCache = new HashMap<CoordinateReferenceSystem, GeometryFilterImpl>();
 
-			Coordinate centre = features.getBounds().centre();
-			if (!mapCRS.equals(fCRS)) {
-				// only to calculations if the CRS differ
-				try {
-					MathTransform fToMap;
-					fToMap = CRS.findMathTransform(fCRS, mapCRS);
-					// centre is transformed to the mapCRS
-					centre = JTS.transform(centre, null, fToMap);
-					;
-				} catch (FactoryException e) {
-					LOGGER.error(e);
-				} catch (TransformException e) {
-					LOGGER.error(e);
-				}
-			}
+      /**
+       * Creates a new filter generator
+       * @param crs {@link CoordinateReferenceSystem} the base constraint ("right"
+       *            filter argument is relative to)
+       */
+      public GeomFilterGenerator(CoordinateReferenceSystem crs) {
+        this.baseCRS = crs;
+      }
 
-			Coordinate newLeftBottom = new Coordinate(centre.x - width / 2.,
-					centre.y - height / 2.);
-			Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
-					centre.y + height / 2.);
+      /**
+       * Creates a filter containing the base constraint ("right" argument)
+       * transformed to the given {@link CoordinateReferenceSystem}.
+       * @param crs the {@link CoordinateReferenceSystem} the base constraint is
+       *            transformed to
+       */
+      protected abstract GeometryFilterImpl prepareFilter(CoordinateReferenceSystem crs);
 
-			Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
+      /**
+       * Completes the filter with its "left" argument for a concrete
+       * {@link FeatureSource}. If the {@link FeatureSource FeatureSource's}
+       * CRS differs from the CRS the base constraint is specified in, first
+       * a new filter is created by calling {@link #prepareFilter(CoordinateReferenceSystem)}.
+       * @param fs {@link FeatureSource} the filter is adaped to
+       * @return
+       */
+      public GeometryFilterImpl adaptFilter(FeatureSource fs) {
+        GeometryAttributeType     geomAttr = fs.getSchema().getDefaultGeometry();
+        CoordinateReferenceSystem fsCRS    = geomAttr.getCoordinateSystem();
+        GeometryFilterImpl        filter   = filterCache.get(fsCRS);
+        if ( filter == null ) {
+          filter = prepareFilter(fsCRS);
+          filterCache.put(fsCRS, filter);
+        }
+        Expression geometry = ff.createAttributeExpression(geomAttr.getLocalName());
+        filter.setExpression1(geometry);
+        return filter;
+      }
 
-			setMapArea(newMapArea);
+    }
 
-		} else {
-			ReferencedEnvelope fBounds = features.getBounds();
+    /**
+     * {@link GeomFilterGenerator} for a bounding box constraint.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     */
+    private static class BoundingBoxFilterGenerator extends GeomFilterGenerator {
+      /** Holds the base constraint (bounding box {@link Envelope}) relative to
+       *  the {@linkplain GeomFilterGenerator#baseCRS base CRS}. */
+      protected Envelope baseEnv = null;
 
-			Envelope bounds;
-			if (!mapCRS.equals(fCRS)) {
-				bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
-			} else {
-				bounds = fBounds;
-			}
-			// BB umrechnen von Layer-CRS in Map-CRS
+      /**
+       * Creates a new filter generator.
+       * @param baseEnv defines the bounding box
+       * @param crs     defines the CRS of the bounding box
+       */
+      public BoundingBoxFilterGenerator(Envelope baseEnv, CoordinateReferenceSystem crs) {
+        super(crs);
+        this.baseEnv = baseEnv;
+      }
 
-			// Expand a bit
-			bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
+      /**
+       * Prepares a filter with the bounding box transformed to the
+       * given {@link CoordinateReferenceSystem} as the "right" argument.
+       * @param crs the {@link CoordinateReferenceSystem} the bounding box is
+       *            transformed to
+       */
+      protected GeometryFilterImpl prepareFilter(CoordinateReferenceSystem crs) {
+        Envelope bbEnv = baseEnv;
+        if ( !baseCRS.equals(crs) )
+          bbEnv = JTSUtil.transformEnvelope(baseEnv, baseCRS, crs);
+          // Filter fuer Envelope zusammenstellen
+          Expression bbox = FilterUtil.FILTER_FAC.createBBoxExpression(bbEnv);
+          GeometryFilterImpl bboxFilter = (GeometryFilterImpl) FilterUtil.FILTER_FAC.createGeometryFilter(AbstractFilter.GEOMETRY_BBOX);
+          // GeometryFilterImpl bboxFilter = (GeometryFilterImpl)ff.createGeometryFilter(AbstractFilter.GEOMETRY_WITHIN);
+          bboxFilter.setExpression2(bbox);
+          return bboxFilter;
+        }
+      }
 
-			setMapArea(bounds);
-		}
-	}
+    /**
+     * {@link GeomFilterGenerator} for a "near distance" constraint.
+     * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+     */
+    private static class NearPointFilterGenerator extends GeomFilterGenerator {
+      /** Holds the base constraint (coordinate) relative to
+       *  the {@linkplain GeomFilterGenerator#baseCRS base CRS}. */
+      protected Coordinate basePoint = null;
+      /** Holds the distance "around" the base point relative to
+       *  the {@linkplain GeomFilterGenerator#baseCRS base CRS}. */
+      protected double     baseDist  = 0.0;
+      /** Holds a point which is in distance {@link #baseDist} to the
+       * {@link #basePoint}. */
+      protected Coordinate basePoint2 = null;
 
+      /**
+       * Creates a new filter generator.
+       * @param basePoint defines the point for the "near point" constraint
+       * @param dist      defines the distance around the base point
+       * @param crs       defines the CRS of base point
+       */
+      public NearPointFilterGenerator(Coordinate basePoint, double dist, CoordinateReferenceSystem crs) {
+        super(crs);
+        this.basePoint  = basePoint;
+        this.baseDist   = dist;
+        // Create a point which is in distance "dist" to the base point
+        this.basePoint2 = new Coordinate(basePoint.x+dist, basePoint.y);
+      }
+
+      /**
+       * Creates a new filter generator.
+       * @param basePoint defines the point for the "near point" constraint
+       * @param dist      defines the distance around the base point
+       * @param crs       defines the CRS of base point
+       */
+      public NearPointFilterGenerator(Point2D basePoint, double dist, CoordinateReferenceSystem crs) {
+        this( new Coordinate(basePoint.getX(),basePoint.getY()),dist,crs);
+      }
+
+      /**
+       * Prepares a filter with the base point and distance transformed to the
+       * given {@link CoordinateReferenceSystem} as the "right" argument.
+       * @param crs the {@link CoordinateReferenceSystem} the point and distance is
+       *            transformed to
+       */
+      protected GeometryFilterImpl prepareFilter(CoordinateReferenceSystem crs) {
+        Coordinate nearPoint = basePoint;
+        double     nearDist  = baseDist;
+        if ( !baseCRS.equals(crs) ) {
+          nearPoint = JTSUtil.transformCoordinate(basePoint, baseCRS, crs);
+          // Transform the distance (maybe "dirty")
+          // --> transform the point2 and calculate the
+          //     distance to the tranformed base point
+          Coordinate nearPoint2 = JTSUtil.transformCoordinate(basePoint2, baseCRS, crs);
+          nearDist = Math.abs(nearPoint.x - nearPoint2.x);
+        }
+        // Filter fuer Point zusammenstellen
+        final Geometry    geometry      = FilterUtil.GEOMETRY_FAC.createPoint(nearPoint);
+        final DWithinImpl dwithinFilter = (DWithinImpl)FilterUtil.FILTER_FAC.createGeometryDistanceFilter(DWithinImpl.GEOMETRY_DWITHIN);
+        dwithinFilter.setDistance(nearDist);
+        dwithinFilter.setExpression2(FilterUtil.FILTER_FAC.createLiteralExpression(geometry));
+
+        return dwithinFilter;
+      }
+
+    }
 }



More information about the Schmitzm-commits mailing list