[Schmitzm-commits] r509 - in branches/1.0-gt2-2.6/src: gtmig/org/geotools/swing schmitzm/geotools schmitzm/geotools/feature schmitzm/geotools/gui schmitzm/geotools/io schmitzm/geotools/map/event schmitzm/geotools/styling schmitzm/jfree schmitzm/jfree/chart schmitzm/jfree/chart/renderer schmitzm/swing skrueger/geotools skrueger/geotools/labelsearch skrueger/geotools/selection skrueger/swing
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Thu Nov 5 09:51:39 CET 2009
Author: alfonx
Date: 2009-11-05 09:51:33 +0100 (Thu, 05 Nov 2009)
New Revision: 509
Added:
branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableXMapPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapPaneEvent.java
Removed:
branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneEvent.java
Modified:
branches/1.0-gt2-2.6/src/schmitzm/geotools/GTUtil.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/JTSUtil.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/feature/FeatureUtil.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureLayerFilterDialog.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureTablePane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoMapPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoPositionLabel.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GridPanel.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorToolBar.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredEditorFrame.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapFrame.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapActionControlPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapContextControlPane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapPaneStatusBar.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/RasterPositionLabel.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableFeatureTablePane.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/io/GeoImportUtil.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/FeatureSelectedEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GeneralSelectionEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageSelectedEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageValueSelectedEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JEditorPaneEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneListener.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapAreaChangedEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ObjectSelectionEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ScaleChangedEvent.java
branches/1.0-gt2-2.6/src/schmitzm/geotools/styling/StylingUtil.java
branches/1.0-gt2-2.6/src/schmitzm/jfree/JFreeChartUtil.java
branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/SelectableChartPanel.java
branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java
branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java
branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java
branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java
branches/1.0-gt2-2.6/src/schmitzm/swing/SwingUtil.java
branches/1.0-gt2-2.6/src/skrueger/geotools/MapPaneToolBar.java
branches/1.0-gt2-2.6/src/skrueger/geotools/MapView.java
branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/LabelSearch.java
branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchMapDialog.java
branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchResultFeature.java
branches/1.0-gt2-2.6/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
branches/1.0-gt2-2.6/src/skrueger/swing/CancellableDialogManager.java
branches/1.0-gt2-2.6/src/skrueger/swing/CancellableTabbedDialogAdapter.java
Log:
new XMapPane and SelectableMapPane to replace and restructure JMapPanes
Deleted: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -1,1073 +0,0 @@
-/*
- * GeoTools - OpenSource mapping toolkit
- * http://geotools.org
- * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- */
-package gtmig.org.geotools.swing;
-
-/**
- * <b>Xulu:<br>
- * Code taken from gt-2.4.5 to make some changes (marked with {@code xulu}),
- * which can not be realized in a subclass:</b>
- * <ul>
- * <li>{@link #getMapArea()} declared as {@code final}<li>
- * <li>some variables declared as {@code protected}</li>
- * <li>minimal/maximal zoom scale</li>
- * <li>zoom in and zoom out via mouse click realized by setMapArea(..)</li>
- * </ul>
- * <br><br>
- * A simple map container that is a JPanel with a map in. provides simple
- * pan,zoom, highlight and selection The mappane stores an image of the map
- * (drawn from the context) and an image of the slected feature(s) to speed up
- * rendering of the highlights. Thus the whole map is only redrawn when the bbox
- * changes, selection is only redrawn when the selected feature changes.
- *
- *
- * @author Ian Turton
- *
- */
-
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.LayoutManager;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.event.InputEvent;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseMotionListener;
-import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.swing.JPanel;
-
-import org.apache.log4j.Logger;
-import org.geotools.map.MapContext;
-import org.geotools.map.event.MapLayerListEvent;
-import org.geotools.map.event.MapLayerListListener;
-import org.geotools.renderer.GTRenderer;
-import org.geotools.renderer.label.LabelCacheImpl;
-import org.geotools.renderer.lite.LabelCache;
-import org.geotools.renderer.lite.StreamingRenderer;
-import org.opengis.filter.FilterFactory2;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-
-import schmitzm.geotools.JTSUtil;
-import schmitzm.swing.SwingUtil;
-
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.Envelope;
-import com.vividsolutions.jts.geom.GeometryFactory;
-
-public class JMapPane extends JPanel implements MouseListener,
- MouseMotionListener, PropertyChangeListener, MapLayerListListener {
- private static Logger LOGGER = Logger.getLogger(JMapPane.class);
-
- private static final long serialVersionUID = -8647971481359690499L;
-
- public static final int Reset = 0;
-
- public static final int ZoomIn = 1;
-
- public static final int ZoomOut = 2;
-
- public static final int Pan = 3;
-
- public static final int Select = 4;
-
- /**
- * what renders the map
- */
- GTRenderer renderer;
-
- /**
- * the map context to render
- */
- MapContext context;
-
- /**
- * the area of the map to draw
- */
- protected Envelope mapArea;
-
- /**
- * the size of the pane last time we drew
- */
- protected Rectangle oldRect = null;
-
- /** We store the old mapArea for a moment to use it for the
- "quick scaled preview" in case of ZoomOut **/
- protected Envelope oldMapArea = null;
-
- /**
- * the base image of the map
- */
- protected BufferedImage baseImage, panningImage;
-
- /**
- * a factory for filters
- */
- FilterFactory2 ff;
-
- /**
- * a factory for geometries
- */
- GeometryFactory gf = new GeometryFactory(); // FactoryFinder.getGeometryFactory(null);
-
- private int state = ZoomIn;
-
- /**
- * how far to zoom in or out
- */
- private double zoomFactor = 2.0;
-
- boolean changed = true;
-
- LabelCache labelCache = new LabelCacheImpl();
-
- protected boolean reset = false;
-
- int startX;
-
- int startY;
-
- /**
- * If not <code>null</code>, the {@link JMapPane} will not allow to zoom/pan
- * out of that area
- **/
- private Envelope maxExtend = null;
-
- // /**
- // * Is max. 1 or 0 of the 2 axised allowed to extend the maxExtend? If
- // * <code>true</code> the extends has to be fully inside maxExtend
- // **/
- // boolean maxExtendForceMode = true;
-
- private boolean clickable;
-
- int lastX;
-
- int lastY;
-
- private Double maxZoomScale = Double.MIN_VALUE;
- private Double minZoomScale = Double.MAX_VALUE;
-
- /**
- * Wenn true, dann wurde PANNING via mouseDraged-Events begonnen. Dieses
- * Flag wird benutzt um nur einmal den passenden Cursor nur einmal zu
- * setzen.
- */
- private boolean panning_started = false;
-
- /**
- * This color is used as the default background color when painting a map.
- */
- private Color mapBackgroundColor = Color.WHITE;
-
- public JMapPane() {
- this(null, true, null, null);
- }
-
- /**
- * create a basic JMapPane
- *
- * @param render
- * - how to draw the map
- * @param context
- * - the map context to display
- */
- public JMapPane(final GTRenderer render, final MapContext context) {
- this(null, true, render, context);
- }
-
- /**
- * full constructor extending JPanel
- *
- * @param layout
- * - layout (probably shouldn't be set)
- * @param isDoubleBuffered
- * - a Swing thing I don't really understand
- * @param render
- * - what to draw the map with
- * @param context
- * - what to draw
- */
- public JMapPane(final LayoutManager layout, final boolean isDoubleBuffered,
- final GTRenderer render, final MapContext context) {
- super(layout, isDoubleBuffered);
-
- ff = (FilterFactory2) org.geotools.factory.CommonFactoryFinder
- .getFilterFactory(null);
- setRenderer(render);
-
- setContext(context);
-
- this.addMouseListener(this);
- this.addMouseMotionListener(this);
- setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
- }
-
- /**
- * get the renderer
- */
- public GTRenderer getRenderer() {
- return renderer;
- }
-
- public void setRenderer(final GTRenderer renderer) {
- Map<Object, Object> hints = new HashMap<Object, Object>();
-
- this.renderer = renderer;
- // MS: Apply hint also for ShapeFileRenderer
- // if (renderer instanceof StreamingRenderer) {
- hints = renderer.getRendererHints();
- if (hints == null) {
- hints = new HashMap<Object, Object>();
- }
- if (hints.containsKey(StreamingRenderer.LABEL_CACHE_KEY)) {
- labelCache = (LabelCache) hints
- .get(StreamingRenderer.LABEL_CACHE_KEY);
- } else {
- hints.put(StreamingRenderer.LABEL_CACHE_KEY, labelCache);
- }
-
- hints.put("memoryPreloadingEnabled", Boolean.TRUE);
-
- renderer.setRendererHints(hints);
- // }
-
- if (this.context != null) {
- this.renderer.setContext(this.context);
- }
- }
-
- public MapContext getContext() {
- return context;
- }
-
- public void setContext(final MapContext context) {
- if (this.context != null) {
- this.context.removeMapLayerListListener(this);
- }
-
- this.context = context;
-
- if (context != null) {
- this.context.addMapLayerListListener(this);
- }
-
- if (renderer != null) {
- renderer.setContext(this.context);
- }
- }
-
- public Envelope getMapArea() {
- return mapArea;
- }
-
- public void setMapArea(final Envelope mapArea) {
- this.mapArea = mapArea;
- }
-
- public int getState() {
- return state;
- }
-
- public void setState(final int state) {
- this.state = state;
-
- // System.out.println("State: " + state);
- }
-
- public double getZoomFactor() {
- return zoomFactor;
- }
-
- public void setZoomFactor(final double zoomFactor) {
- this.zoomFactor = zoomFactor;
- }
-
- protected void paintComponent(final Graphics g) {
- super.paintComponent(g);
-
- if ((renderer == null) || (mapArea == null)) {
- return;
- }
-
- final Rectangle r = getBounds();
- final Rectangle dr = new Rectangle(r.width, r.height);
-
- if (!r.equals(oldRect) || reset) {
- if (!r.equals(oldRect) && (mapArea == null)) {
- try {
- mapArea = context.getLayerBounds();
- } catch (final IOException e) {
- LOGGER.warn("context.getLayerBounds()", e);
- }
- }
-
- if (mapArea != null) {
- /* either the viewer size has changed or we've done a reset */
- changed = true; /* note we need to redraw */
- reset = false; /* forget about the reset */
- oldRect = r; /* store what the current size is */
-
- mapArea = JTSUtil.fixAspectRatio(r, mapArea, false);
- }
- }
-
- if (!mapArea.equals(oldMapArea)) { /* did the map extent change? */
- changed = true;
- oldMapArea = mapArea;
- // when we tell the context that the bounds have changed WMSLayers
- // can refresh them selves
- context.setAreaOfInterest(mapArea, context
- .getCoordinateReferenceSystem());
- }
-
- if (changed) { /* if the map changed then redraw */
- changed = false;
-
- // The baseImage should not have alpha
- baseImage = new BufferedImage(dr.width, dr.height,
- BufferedImage.TYPE_INT_RGB);
-
- final Graphics2D ig = baseImage.createGraphics();
- ig.setBackground(getMapBackgroundColor());
- ig.fillRect(0, 0, dr.width, dr.height);
-
-// /* System.out.println("rendering"); */
- if (renderer.getContext() != null)
- renderer.setContext(context);
-
- // TODO is this clearing still needed? We already replace all that stuff whenever we change the style. Deactivated 31.10.09.. let's see
-// labelCache.clear(); // work around anoying labelcache bug
-
- // draw the map
- renderer.paint(ig, dr, mapArea);
-
- panningImage = new BufferedImage(dr.width, dr.height, BufferedImage.TYPE_INT_RGB);
-
- }
-
- ((Graphics2D) g).drawImage(baseImage, 0, 0, this);
- }
-
- public void mouseClicked(final MouseEvent e) {
- if (mapArea == null)
- return;
- // System.out.println("before area "+mapArea+"\nw:"+mapArea.getWidth()+"
- // h:"+mapArea.getHeight());
- final Rectangle bounds = this.getBounds();
- final double x = (double) (e.getX());
- final double y = (double) (e.getY());
- final double width = mapArea.getWidth();
- final double height = mapArea.getHeight();
- // xulu.sc
- // double width2 = mapArea.getWidth() / 2.0;
- // double height2 = mapArea.getHeight() / 2.0;
- final double width2 = width / 2.0;
- final double height2 = height / 2.0;
- // xulu.ec
- final double mapX = ((x * width) / (double) bounds.width)
- + mapArea.getMinX();
- final double mapY = (((bounds.getHeight() - y) * height) / (double) bounds.height)
- + mapArea.getMinY();
-
- /*
- * System.out.println(""+x+"->"+mapX);
- * System.out.println(""+y+"->"+mapY);
- */
-
- /*
- * Coordinate ll = new Coordinate(mapArea.getMinX(), mapArea.getMinY());
- * Coordinate ur = new Coordinate(mapArea.getMaxX(), mapArea.getMaxY());
- */
- double zlevel = 1.0;
-
- switch (state) {
- case Pan:
- zlevel = 1.0;
- // xulu.sc SK: return here.. a mouselistener is managing the PANNING
- // break;
- return;
- // xulu.ec
- case ZoomIn:
- zlevel = zoomFactor;
-
- break;
-
- case ZoomOut:
- zlevel = 1.0 / zoomFactor;
-
- break;
- //
- // case Select:
- // doSelection(mapX, mapY, selectionLayer);
- //
- // return;
-
- default:
- return;
- }
-
- final Coordinate ll = new Coordinate(mapX - (width2 / zlevel), mapY
- - (height2 / zlevel));
- final Coordinate ur = new Coordinate(mapX + (width2 / zlevel), mapY
- + (height2 / zlevel));
- // xulu.sc SK: Check for min/max scale
- // mapArea = new Envelope(ll, ur);
- final Envelope newMapArea = new Envelope(ll, ur);
- setMapArea(bestAllowedMapArea(newMapArea));
- // xulu.ec
-
- // sk.ec
-
- // System.out.println("after area "+mapArea+"\nw:"+mapArea.getWidth()+"
- // h:"+mapArea.getHeight());
- repaint();
- }
-
- public void mouseEntered(final MouseEvent e) {
- }
-
- public void mouseExited(final MouseEvent e) {
- }
-
- public void mousePressed(final MouseEvent e) {
- startX = e.getX();
- startY = e.getY();
- lastX = 0;
- lastY = 0;
- }
-
- public void mouseReleased(final MouseEvent e) {
- final int endX = e.getX();
- final int endY = e.getY();
-
- processDrag(startX, startY, endX, endY, e);
- lastX = 0;
- lastY = 0;
-
- /**
- * Es wird nicht (mehr) gepannt!
- */
- panning_started = false;
- }
-
- public void mouseDragged(final MouseEvent e) {
- final Graphics graphics = this.getGraphics();
- final int x = e.getX();
- final int y = e.getY();
-
- if ((state == JMapPane.Pan)
- || ((e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0)) {
- /**
- * SK: Der Cursor wird auf PANNING gesetzt.
- */
- if (panning_started == false) {
- panning_started = true;
- setCursor(SwingUtil.PANNING_CURSOR);
- }
-
- // move the image with the mouse
- if ((lastX > 0) && (lastY > 0)) {
- final int dx = lastX - startX;
- final int dy = lastY - startY;
- // System.out.println("translate "+dx+","+dy);
- final Graphics2D g2 = panningImage.createGraphics();
- g2.setBackground(getMapBackgroundColor());
-
- g2.clearRect(0, 0, this.getWidth(), this.getHeight());
- g2.drawImage(baseImage, dx, dy, this);
- graphics.drawImage(panningImage, 0, 0, this);
- }
-
- lastX = x;
- lastY = y;
- } else
-
- if ((state == JMapPane.ZoomIn) || (state == JMapPane.ZoomOut)) {
-
- graphics.setXORMode(Color.WHITE);
-
- if ((lastX > 0) && (lastY > 0)) {
- drawRectangle(graphics);
- }
-
- // draw new box
- lastX = x;
- lastY = y;
- drawRectangle(graphics);
- }
- // else if (state == JMapPane.Select && selectionLayer != null) {
- //
- // // construct a new bbox filter
- // final Rectangle bounds = this.getBounds();
- //
- // final double mapWidth = mapArea.getWidth();
- // final double mapHeight = mapArea.getHeight();
- //
- // final double x1 = ((this.startX * mapWidth) / (double) bounds.width)
- // + mapArea.getMinX();
- // final double y1 = (((bounds.getHeight() - this.startY) * mapHeight) /
- // (double) bounds.height)
- // + mapArea.getMinY();
- // final double x2 = ((x * mapWidth) / (double) bounds.width)
- // + mapArea.getMinX();
- // final double y2 = (((bounds.getHeight() - y) * mapHeight) / (double)
- // bounds.height)
- // + mapArea.getMinY();
- // final double left = Math.min(x1, x2);
- // final double right = Math.max(x1, x2);
- // final double bottom = Math.min(y1, y2);
- // final double top = Math.max(y1, y2);
- //
- // String name = selectionLayer.getFeatureSource().getSchema()
- // .getDefaultGeometry().getName();
- //
- // if (name == "") {
- // name = "the_geom";
- // }
- // final Filter bb = ff.bbox(ff.property(name), left, bottom, right,
- // top,
- // getContext().getCoordinateReferenceSystem().toString());
- // if (selectionManager != null) {
- // selectionManager.selectionChanged(this, bb);
- // }
- //
- // graphics.setXORMode(Color.green);
- //
- // /*
- // * if ((lastX > 0) && (lastY > 0)) { drawRectangle(graphics); }
- // */
- //
- // // draw new box
- // lastX = x;
- // lastY = y;
- // drawRectangle(graphics);
- // }
-
- }
-
- // sk.cs
- // private void processDrag(int x1, int y1, int x2, int y2) {
- // sk.ce
- protected void processDrag(final int x1, final int y1, final int x2,
- final int y2, final MouseEvent e) {
-
- /****
- * If no layers exist, we ignore the drag.
- */
- if (context.getLayerCount() <= 0) {
- return;
- }
-
- // System.out.println("processing drag from " + x1 + "," + y1 + " -> "
- // + x2 + "," + y2);
- if ((x1 == x2) && (y1 == y2)) {
- if (isClickable()) {
- mouseClicked(new MouseEvent(this, 0, new Date().getTime(), 0,
- x1, y1, y2, false));
- }
-
- return;
- }
-
- final Rectangle bounds = this.getBounds();
-
- final double mapWidth = mapArea.getWidth();
- final double mapHeight = mapArea.getHeight();
-
- final double startX = ((x1 * mapWidth) / (double) bounds.width)
- + mapArea.getMinX();
- final double startY = (((bounds.getHeight() - y1) * mapHeight) / (double) bounds.height)
- + mapArea.getMinY();
- final double endX = ((x2 * mapWidth) / (double) bounds.width)
- + mapArea.getMinX();
- final double endY = (((bounds.getHeight() - y2) * mapHeight) / (double) bounds.height)
- + mapArea.getMinY();
-
- if ((state == JMapPane.Pan) || (e.getButton() == MouseEvent.BUTTON3)) {
- // move the image with the mouse
- // calculate X offsets from start point to the end Point
- final double deltaX1 = endX - startX;
-
- // System.out.println("deltaX " + deltaX1);
- // new edges
- final double left = mapArea.getMinX() - deltaX1;
- final double right = mapArea.getMaxX() - deltaX1;
- final double deltaY1 = endY - startY;
-
- // System.out.println("deltaY " + deltaY1);
- final double bottom = mapArea.getMinY() - deltaY1;
- final double top = mapArea.getMaxY() - deltaY1;
- final Coordinate ll = new Coordinate(left, bottom);
- final Coordinate ur = new Coordinate(right, top);
- // xulu.sc
- // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
-
- setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
- // xulu.ec
- } else if (state == JMapPane.ZoomIn) {
-
- // Zu kleine Flächen sollen nicht gezoomt werden.
- // sk.bc
- if ((Math.abs(x1 - x2) * Math.abs(y2 - y1)) < 150)
- return;
- // sk.ec
-
- drawRectangle(this.getGraphics());
- // make the dragged rectangle (in map coords) the new BBOX
- final double left = Math.min(startX, endX);
- final double right = Math.max(startX, endX);
- final double bottom = Math.min(startY, endY);
- final double top = Math.max(startY, endY);
- final Coordinate ll = new Coordinate(left, bottom);
- final Coordinate ur = new Coordinate(right, top);
- // xulu.sc
-
- // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
- setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
-
- } else if (state == JMapPane.ZoomOut) {
- drawRectangle(this.getGraphics());
-
- // make the dragged rectangle in screen coords the new map size?
- final double left = Math.min(startX, endX);
- final double right = Math.max(startX, endX);
- final double bottom = Math.min(startY, endY);
- final double top = Math.max(startY, endY);
- final double nWidth = (mapWidth * mapWidth) / (right - left);
- final double nHeight = (mapHeight * mapHeight) / (top - bottom);
- final double deltaX1 = left - mapArea.getMinX();
- final double nDeltaX1 = (deltaX1 * nWidth) / mapWidth;
- final double deltaY1 = bottom - mapArea.getMinY();
- final double nDeltaY1 = (deltaY1 * nHeight) / mapHeight;
- final Coordinate ll = new Coordinate(mapArea.getMinX() - nDeltaX1,
- mapArea.getMinY() - nDeltaY1);
- final double deltaX2 = mapArea.getMaxX() - right;
- final double nDeltaX2 = (deltaX2 * nWidth) / mapWidth;
- final double deltaY2 = mapArea.getMaxY() - top;
- final double nDeltaY2 = (deltaY2 * nHeight) / mapHeight;
- final Coordinate ur = new Coordinate(mapArea.getMaxX() + nDeltaX2,
- mapArea.getMaxY() + nDeltaY2);
- // xulu.sc
- // mapArea = fixAspectRatio(this.getBounds(), new Envelope(ll, ur));
- setMapArea(bestAllowedMapArea(new Envelope(ll, ur)));
-
- // xulu.ec
- }
- // else if (state == JMapPane.Select && selectionLayer != null) {
- // final double left = Math.min(startX, endX);
- // final double right = Math.max(startX, endX);
- // final double bottom = Math.min(startY, endY);
- // final double top = Math.max(startY, endY);
- //
- // String name = selectionLayer.getFeatureSource().getSchema()
- // .getDefaultGeometry().getLocalName();
- //
- // if (name == "") {
- // name = "the_geom";
- // }
- // final Filter bb = ff.bbox(ff.property(name), left, bottom, right,
- // top,
- // getContext().getCoordinateReferenceSystem().toString());
- // // System.out.println(bb.toString());
- // if (selectionManager != null) {
- // selectionManager.selectionChanged(this, bb);
- // }
- // /*
- // * FeatureCollection fc; selection = null; try { fc =
- // * selectionLayer.getFeatureSource().getFeatures(bb); selection =
- // * fc; } catch (IOException e) { e.printStackTrace(); }
- // */
- // }
-
- // xulu.so
- // setMapArea(mapArea);
- // xulu.eo
- repaint();
- }
-
- private boolean isClickable() {
- return clickable;
- }
-
- public void propertyChange(final PropertyChangeEvent evt) {
- final String prop = evt.getPropertyName();
-
- if (prop.equalsIgnoreCase("crs")) {
- context.setAreaOfInterest(context.getAreaOfInterest(),
- (CoordinateReferenceSystem) evt.getNewValue());
- }
- }
-
- public boolean isReset() {
- return reset;
- }
-
- public void setReset(final boolean reset) {
- this.reset = reset;
- }
-
- public void layerAdded(final MapLayerListEvent event) {
- changed = true;
-
- if (context.getLayers().length == 1) { // the first one
-
- try {
- // xulu.sc
- // mapArea = context.getLayerBounds();
- mapArea = context.getAreaOfInterest();
- if (mapArea == null)
- mapArea = context.getLayerBounds();
- // xulu.ec
- } catch (final IOException e) {
- LOGGER.error(e);
- }
-
- reset = true;
- }
-
- repaint();
- }
-
- public void layerRemoved(final MapLayerListEvent event) {
- changed = true;
- repaint();
- }
-
- public void layerChanged(final MapLayerListEvent event) {
- changed = true;
- // System.out.println("layer changed - repaint");
- repaint();
- }
-
- public void layerMoved(final MapLayerListEvent event) {
- changed = true;
- repaint();
- }
-
- protected void drawRectangle(final Graphics graphics) {
- // undraw last box/draw new box
- final int left = Math.min(startX, lastX);
- final int right = Math.max(startX, lastX);
- final int top = Math.max(startY, lastY);
- final int bottom = Math.min(startY, lastY);
- final int width = right - left;
- final int height = top - bottom;
- // System.out.println("drawing rect("+left+","+bottom+","+ width+","+
- // height+")");
- graphics.drawRect(left, bottom, width, height);
- }
-
- /**
- * if clickable is set to true then a single click on the map pane will zoom
- * or pan the map.
- *
- * @param clickable
- */
- public void setClickable(final boolean clickable) {
- this.clickable = clickable;
- }
-
- public void mouseMoved(final MouseEvent e) {
- }
-
- // xulu.sn
- /**
- * Korrigiert den {@link Envelope} aka {@code mapArea} auf die beste
- * erlaubte Flaeche damit die Massstabsbeschaenkungen noch eingehalten
- * werden, FALLS der uebergeben Envelope nicht schon gueltig sein sollte.<br/>
- * Since 21. April 09: Before thecalculation starts, the aspect ratio is
- * corrected. This change implies, that setMapArea() will most of the time
- * not allow setting to a wrong aspectRatio.
- *
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- * Krüger</a>
- */
- public Envelope bestAllowedMapArea(Envelope env) {
- if (getWidth() == 0)
- return env;
- if (env == null)
- return env;
-
- Envelope newArea = null;
-
- /**
- * Correct the aspect Ratio before we check the rest. Otherwise we might
- * easily fail. We allow to grow here, because we don't check against
- * the maxExtend
- */
- env = JTSUtil.fixAspectRatio(this.getBounds(), env, true);
-
- final double scale = env.getWidth() / getWidth();
- final double centerX = env.getMinX() + env.getWidth() / 2.;
- final double centerY = env.getMinY() + env.getHeight() / 2.;
- double newWidth2 = 0;
- double newHeight2 = 0;
- if (scale < getMaxZoomScale()) {
- // ****************************************************************************
- // Wir zoomen weiter rein als erlaubt => Anpassen des envelope
- // ****************************************************************************
- newWidth2 = getMaxZoomScale() * getWidth() / 2.;
- newHeight2 = getMaxZoomScale() * getHeight() / 2.;
- } else if (scale > getMinZoomScale()) {
- // ****************************************************************************
- // Wir zoomen weiter raus als erlaubt => Anpassen des envelope
- // ****************************************************************************
- newWidth2 = getMinZoomScale() * getWidth() / 2.;
- newHeight2 = getMinZoomScale() * getHeight() / 2.;
- } else {
- // ****************************************************************************
- // Die mapArea / der Envelope ist ist gueltig! Keine Aenderungen
- // ****************************************************************************
- newArea = env;
- }
-
- if (newArea == null) {
-
- final Coordinate ll = new Coordinate(centerX - newWidth2, centerY
- - newHeight2);
- final Coordinate ur = new Coordinate(centerX + newWidth2, centerY
- + newHeight2);
-
- newArea = new Envelope(ll, ur);
- }
-
- Envelope maxAllowedExtend = getMaxExtend();
- while (maxAllowedExtend != null && !maxAllowedExtend.contains(newArea)
- && newArea != null && !newArea.isNull()
- && !Double.isNaN(newArea.getMinX())
- && !Double.isNaN(newArea.getMaxX())
- && !Double.isNaN(newArea.getMinY())
- && !Double.isNaN(newArea.getMaxY())) {
- /*
- * If a maxExtend is set, we have to honour that...
- */
-
- // Exceeds top? Move down and maybe cut
- if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) {
- double divY = newArea.getMaxY() - maxAllowedExtend.getMaxY();
- // LOGGER.debug("Moving area down by " + divY);
-
- newArea = new Envelope(new Coordinate(newArea.getMinX(),
- newArea.getMinY() - divY), new Coordinate(newArea
- .getMaxX(), newArea.getMaxY() - divY));
-
- if (newArea.getMinY() < maxAllowedExtend.getMinY()) {
- // LOGGER.debug("Now it exeeds the bottom border.. cut!");
- // And cut the bottom if it moved out of the area
- newArea = new Envelope(new Coordinate(newArea.getMinX(),
- maxAllowedExtend.getMinY()), new Coordinate(newArea
- .getMaxX(), newArea.getMaxY()));
-
- // LOGGER.debug("and fix aspect ratio");
-
- newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
- false);
- }
- }
-
- // Exceeds bottom? Move up and maybe cut
- if (newArea.getMinY() < maxAllowedExtend.getMinY()) {
- double divY = newArea.getMinY() - maxAllowedExtend.getMinY();
- // LOGGER.debug("Moving area up by " + divY);
-
- newArea = new Envelope(new Coordinate(newArea.getMinX(),
- newArea.getMinY() - divY), new Coordinate(newArea
- .getMaxX(), newArea.getMaxY() - divY));
-
- if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) {
- // LOGGER.debug("Now it exeeds the top border.. cut!");
- // And cut the bottom if it moved out of the area
- newArea = new Envelope(new Coordinate(newArea.getMinX(),
- newArea.getMinY()), new Coordinate(newArea
- .getMaxX(), maxAllowedExtend.getMaxY()));
-
- // LOGGER.debug("and fix aspect ratio");
-
- newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
- false);
- }
- }
-
- // Exceeds to the right? move and maybe cut
- if (newArea.getMaxX() > maxAllowedExtend.getMaxX()) {
-
- // Move left..
- double divX = newArea.getMaxX() - maxAllowedExtend.getMaxX();
- // LOGGER.debug("Moving area left by " + divX);
-
- newArea = new Envelope(new Coordinate(newArea.getMinX() - divX,
- newArea.getMinY()), new Coordinate(newArea.getMaxX()
- - divX, newArea.getMaxY()));
-
- if (newArea.getMinX() < maxAllowedExtend.getMinX()) {
- // LOGGER.debug("Now it exeeds the left border.. cut!");
- // And cut the left if it moved out of the area
- newArea = new Envelope(new Coordinate(maxAllowedExtend
- .getMinX(), newArea.getMinY()), new Coordinate(
- newArea.getMaxX(), newArea.getMaxY()));
-
- // LOGGER.debug("and fix aspect ratio");
-
- newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
- false);
- }
- }
-
- // Exceeds to the left? move and maybe cut
- if (newArea.getMinX() < maxAllowedExtend.getMinX()) {
-
- // Move right..
- double divX = newArea.getMinX() - maxAllowedExtend.getMinX();
- // LOGGER.debug("Moving area right by " + divX);
-
- newArea = new Envelope(new Coordinate(newArea.getMinX() - divX,
- newArea.getMinY()), new Coordinate(newArea.getMaxX()
- - divX, newArea.getMaxY()));
-
- if (newArea.getMaxX() > maxAllowedExtend.getMaxX()) {
- // LOGGER.debug("Now it exeeds the right border.. cut!");
- // And cut the left if it moved out of the area
- newArea = new Envelope(new Coordinate(newArea.getMinX(),
- newArea.getMinY()), new Coordinate(maxAllowedExtend
- .getMaxX(), newArea.getMaxY()));
-
- // LOGGER.debug("and fix aspect ratio");
-
- newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
- false);
- }
- }
-
- }
-
- return newArea;
- }
-
- /**
- * Retuns the minimum allowed zoom scale. This is the bigger number value of
- * the two. Defaults to {@link Double}.MAX_VALUE
- *
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- * Krüger</a>
- */
- public Double getMinZoomScale() {
- return minZoomScale;
- }
-
- /**
- * Retuns the maximum allowed zoom scale. This is the smaller number value
- * of the two. Defaults to {@link Double}.MIN_VALUE
- *
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- * Krüger</a>
- */
- public Double getMaxZoomScale() {
- return maxZoomScale;
- }
-
- /**
- * Set the maximum allowed zoom scale. This is the smaller number value of
- * the two. If <code>null</code> is passed, Double.MINVALUE are used which
- * mean there is no restriction.
- *
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- * Krüger</a>
- */
- public void setMaxZoomScale(final Double maxZoomScale) {
- this.maxZoomScale = maxZoomScale == null ? Double.MIN_VALUE
- : maxZoomScale;
- }
-
- /**
- * Set the minimum (nearest) allowed zoom scale. This is the bigger number
- * value of the two. If <code>null</code> is passed, Double.MAXVALUE are
- * used which mean there is no restriction.
- *
- *
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- * Krüger</a>
- */
- public void setMinZoomScale(final Double minZoomScale) {
- this.minZoomScale = minZoomScale == null ? Double.MAX_VALUE
- : minZoomScale;
- }
-
- /**
- * Defines an evelope of the viwable area. The JMapPane will never show
- * anything outside of this extend.
- *
- * @param maxExtend
- * <code>null</code> to not have this restriction.
- */
- public void setMaxExtend(Envelope maxExtend) {
- this.maxExtend = maxExtend;
- }
-
- /**
- * Returns the evelope of the viewable area. The JMapPane will never show
- * anything outside of this extend. If this has been set to
- * <code>null</code> via {@link #setMaxExtend(Envelope)}, it tries to return
- * quickly the context's bounds. It it takes to long to determine the
- * context bounds, <code>null</code> is returned.
- *
- * @param maxExtend
- * <code>null</code> to not have this restriction.
- */
-
- public Envelope getMaxExtend() {
- if (maxExtend == null) {
- try {
- return JTSUtil.fixAspectRatio(this.getBounds(),
- // Kartenbereich um 10% vergroessern
- JTSUtil.expandEnvelope(context.getLayerBounds(), 0.1),
- true);
- } catch (IOException e) {
- LOGGER
- .warn(
- "maxExtend == null; failed to getLayerBounds of context",
- e);
- }
- }
- return maxExtend;
- }
-
- /**
- * Set the background color of the map.
- * @param if <code>null</code>, white is used.
- */
- public void setMapBackgroundColor(Color bgColor) {
- if (bgColor == null) bgColor = Color.WHITE;
- this.mapBackgroundColor = bgColor;
- }
-
- /**
- * Returns the background {@link Color} of the map pane. Default is white.
- **/
- public Color getMapBackgroundColor() {
- return mapBackgroundColor;
- }
-
-}
Copied: branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java (from rev 506, branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java)
===================================================================
--- branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/JMapPane.java 2009-10-31 12:15:37 UTC (rev 506)
+++ branches/1.0-gt2-2.6/src/gtmig/org/geotools/swing/XMapPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -0,0 +1,2245 @@
+/*
+ * GeoTools - OpenSource mapping toolkit
+ * http://geotools.org
+ * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ */
+package gtmig.org.geotools.swing;
+
+/**
+ * This class is 50% copied from GeoTools 2.6.x JMapPane. GeoTools is LGPL, SCHMITZM also.<br/>
+ * In addition to
+ */
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Cursor;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.Timer;
+
+import org.apache.log4j.Logger;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.geometry.jts.JTS;
+import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.map.DefaultMapContext;
+import org.geotools.map.MapContext;
+import org.geotools.map.MapLayer;
+import org.geotools.map.event.MapLayerEvent;
+import org.geotools.map.event.MapLayerListEvent;
+import org.geotools.map.event.MapLayerListListener;
+import org.geotools.map.event.MapLayerListener;
+import org.geotools.referencing.CRS;
+import org.geotools.renderer.GTRenderer;
+import org.geotools.renderer.label.LabelCacheImpl;
+import org.geotools.renderer.lite.LabelCache;
+import org.geotools.swing.JMapPane;
+import org.geotools.swing.event.MapMouseEvent;
+import org.geotools.swing.event.MapPaneEvent;
+import org.geotools.swing.event.MapPaneListener;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.referencing.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.TransformException;
+
+import schmitzm.geotools.GTUtil;
+import schmitzm.geotools.JTSUtil;
+import schmitzm.geotools.gui.SelectableXMapPane;
+import schmitzm.geotools.map.event.JMapPaneListener;
+import schmitzm.geotools.map.event.MapLayerAdapter;
+import schmitzm.swing.SwingUtil;
+import skrueger.geotools.RenderingExecutor;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jts.geom.Geometry;
+
+public class XMapPane extends JPanel implements PropertyChangeListener {
+ private static Logger LOGGER = Logger.getLogger(XMapPane.class);
+
+ /**
+ * Sets whether a layer is regarded or ignored on {@link #SELECT_TOP},
+ * {@link #SELECT_ALL} and {@link #SELECT_ONE_FROM_TOP} actions.
+ *
+ * @param layer
+ * a layer
+ * @param selectable
+ * if {@code false} the layer is ignored during the upper
+ * mentioned actions. If <code>null</code>, the default (true)
+ * will be used.
+ */
+ public void setMapLayerSelectable(MapLayer layer, Boolean selectable) {
+ if (selectable == null)
+ mapLayerSelectable.remove(layer);
+ else
+ mapLayerSelectable.put(layer, selectable);
+ }
+
+ /**
+ * Holds a flag for each layer, whether it is regarded or ignored on
+ * {@link #SELECT_TOP}, {@link #SELECT_ALL} and {@link #SELECT_ONE_FROM_TOP}
+ * actions.
+ */
+ final protected HashMap<MapLayer, Boolean> mapLayerSelectable = new HashMap<MapLayer, Boolean>();
+
+ /**
+ * Returns whether a layer is regarded or ignored on {@link #SELECT_TOP},
+ * {@link #SELECT_ALL} and {@link #SELECT_ONE_FROM_TOP} actions. Returns
+ * <code>true</code> if the selectability has not been defined.
+ *
+ * @param layer
+ * a layer
+ */
+ public boolean isMapLayerSelectable(MapLayer layer) {
+ Boolean selectable = mapLayerSelectable.get(layer);
+ return selectable == null ? true : selectable;
+ }
+
+ /**
+ * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl
+ * moeglich!
+ *
+ * @see #setState(int)
+ */
+ public static final int PAN = 1;
+ /**
+ * Flag fuer Modus "Heran zoomen".
+ *
+ * @see #setState(int)
+ * @see #setState(int)
+ */
+ public static final int ZOOM_IN = 2;
+ /**
+ * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich!
+ *
+ * @see #setState(int)
+ */
+ public static final int ZOOM_OUT = 3;
+ /**
+ * Flag fuer Modus
+ * "SimpleFeature-Auswahl auf dem obersten (sichtbaren) Layer".
+ *
+ * @see #setState(int)
+ * @see #setState(int)
+ */
+ public static final int SELECT_TOP = 4;
+ /**
+ * Flag fuer Modus "SimpleFeature-Auswahl auf allen (sichtbaren) Layern".
+ *
+ * @see #setState(int)
+ * @see #setState(int)
+ */
+ public static final int SELECT_ALL = 103;
+ /**
+ * Flag fuer Modus
+ * "Auswahl nur eines Features, das erste sichtbare von Oben".
+ *
+ * @see #setState(int)
+ * @see #setState(int)
+ */
+ public static final int SELECT_ONE_FROM_TOP = 104;
+
+ public static final long DEFAULT_REPAINTING_DELAY = 200;
+
+ protected skrueger.geotools.RenderingExecutor bgExecuter;
+
+ /**
+ * the map context to render
+ */
+ MapContext localContext;
+ /**
+ * the map context to render
+ */
+ MapContext bgContext;
+
+ /**
+ * the area of the map to draw
+ */
+ protected Envelope mapArea = null;
+ /**
+ * We store the old mapArea for a moment to use it for the
+ * "quick scaled preview" in case of ZoomOut
+ **/
+ protected Envelope oldMapArea = null;
+
+ /**
+ * the size of the pane last time we drew
+ */
+ protected Rectangle oldRect = null;
+
+ /**
+ * The Renderer for the Background uses this Image. When set to null, please
+ * dispose the {@link Graphics2D}
+ */
+ protected BufferedImage bgImage;
+
+ /**
+ * The Renderer for the LocalLayers uses this Image. When set to null,
+ * please dispose this {@link Graphics2D}
+ */
+ volatile protected BufferedImage localImage;
+
+ /**
+ * compass and icon are rendered into this image
+ */
+// protected BufferedImage gadgetsImage;
+
+ /**
+ * The default state is ZOOM_IN, hence by default the
+ * {@link #zoomMapPaneMouseListener} is also enabled.
+ **/
+ private int state = ZOOM_IN;
+
+ /**
+ * 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 MapMouseEvent)
+ try {
+ return ((MapMouseEvent) e).getMapPosition().toPoint2D();
+ } catch (Exception err) {
+ LOGGER
+ .error(
+ "return ((GeoMouseEvent) e).getMapCoordinate(null).toPoint2D();",
+ err);
+ }
+
+ // aktuelle Geo-Position ueber Transformation des JMapPane berechnen
+ if (e != null && e.getSource() instanceof XMapPane) {
+
+ final XMapPane xMapPane = (XMapPane) e.getSource();
+
+ if (!xMapPane.isWellDefined()) return null;
+
+ AffineTransform at = xMapPane.getScreenToWorld();
+ if (at != null)
+ return at.transform(e.getPoint(), null);
+ return null;
+ }
+ throw new IllegalArgumentException(
+ "MouseEvent has to be of instance MapMouseEvent or come from an XMapPane");
+ }
+
+ /**
+ * A flag indicating that the shown image is invalid and needs to be
+ * re-rendered.
+ */
+ protected boolean mapImageInvalid = true;
+
+ protected LabelCache labelCache = new LabelCacheImpl();
+
+ /**
+ * If not <code>null</code>, the {@link XMapPane} will not allow to zoom/pan
+ * out of that area
+ **/
+ private Envelope maxExtend = null;
+
+ private Double maxZoomScale = Double.MIN_VALUE;
+ private Double minZoomScale = Double.MAX_VALUE;
+
+ /**
+ * This color is used as the default background color when painting a map.
+ */
+ private Color mapBackgroundColor = Color.WHITE;
+
+ /**
+ * This {@link MouseListener} is managing all zoom related tasks
+ */
+ public final ZoomXMapPaneMouseListener zoomMapPaneMouseListener = new ZoomXMapPaneMouseListener(
+ this);
+
+ /**
+ * A flag indicating, that the image size has changed and the buffered
+ * images are not big enough any more
+ **/
+ protected boolean paneResized = false;
+
+ /**
+ * While threads are working, we call {@link XMapPane#updateFinalImage()}
+ * regularly and repaint(). This {@link Timer} is stoppen when all renderers
+ * finished.
+ */
+ final private Timer repainterTimer;
+
+ /**
+ * The flag {@link #requestStartRendering} can be set to true by events.
+ * This {@link Timer} checks the flag regularly and starts one renderer
+ * thread.
+ */
+ final private Timer startRenderThreadsTimer;
+
+ private Map<Object, Object> rendererHints;
+
+ public Map<Object, Object> getRendererHints() {
+ return rendererHints;
+ }
+
+ /**
+ * Nuetzlich wenn die Componente gedruckt (z.B. wenn ein Screenshot gemacht
+ * wird) wird. Dann werden wird der Hintergrund auf WEISS gesetzt.
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ @Override
+ public void print(Graphics g) {
+ Color orig = getBackground();
+ setBackground(Color.WHITE);
+
+ // wrap in try/finally so that we always restore the state
+ try {
+ super.print(g);
+ } finally {
+ setBackground(orig);
+ }
+ }
+
+ /**
+ * full constructor extending JPanel
+ *
+ * @param rendererHints
+ *
+ * @param layout
+ * - layout (probably shouldn't be set)
+ * @param isDoubleBuffered
+ * - a Swing thing I don't really understand
+ * @param render
+ * - what to draw the map with
+ * @param localContext
+ * - {@link MapContext} of layer to render.
+ */
+ public XMapPane(final MapContext localContext,
+ Map<Object, Object> rendererHints) {
+ super(true);
+
+ setRendererHints(rendererHints);
+
+ setOpaque(true);
+
+ setLocalContext(localContext);
+
+ /**
+ * Adding the #zoomMapPaneMouseListener
+ */
+ this.addMouseListener(zoomMapPaneMouseListener);
+ this.addMouseMotionListener(zoomMapPaneMouseListener);
+ this.addMouseWheelListener(zoomMapPaneMouseListener);
+
+ /*
+ * We use a Timer object to avoid rendering delays and flickering when
+ * the user is drag-resizing the parent container of this map pane.
+ *
+ * Using a ComponentListener doesn't work because, unlike a JFrame, the
+ * pane receives a stream of events during drag-resizing.
+ */
+ resizingPaintDelay = DEFAULT_RESIZING_PAINT_DELAY;
+ resizeTimer = new Timer(resizingPaintDelay, new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ paneResized = true;
+
+ if (!isWellDefined())
+ return;
+
+ Rectangle bounds = getVisibleRect();
+
+ Envelope geoMapArea = tranformWindowToGeo(bounds.x, bounds.y,
+ bounds.x + bounds.width, bounds.y + bounds.height);
+
+ setMapArea(bestAllowedMapArea(geoMapArea));
+ }
+ });
+ resizeTimer.setRepeats(false);
+ this.addComponentListener(new ComponentAdapter() {
+
+ @Override
+ public void componentResized(ComponentEvent e) {
+ if (bgExecuter != null)
+ bgExecuter.cancelTask();
+ if (localExecuter != null)
+ localExecuter.cancelTask();
+ resizeTimer.restart();
+ }
+
+ });
+
+ repainterTimer = new Timer((int) DEFAULT_REPAINTING_DELAY,
+ new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ updateFinalImage();
+ XMapPane.this.repaint(DEFAULT_REPAINTING_DELAY);
+ }
+ });
+ repainterTimer.setInitialDelay(1000);
+ repainterTimer.setRepeats(true);
+
+ startRenderThreadsTimer = new Timer(200, new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ synchronized (requestStartRendering) {
+ if (requestStartRendering && isValid())
+ startRendering();
+ requestStartRendering = false;
+ }
+ }
+ });
+ startRenderThreadsTimer.start();
+
+ }
+
+ // TODO doku
+ public XMapPane() {
+ this(null, null);
+ }
+
+ /**
+ * 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 SelectableXMapPane} .
+ *
+ * @param features
+ * if <code>null</code> or size==0, the function doesn nothing.
+ */
+ public void zoomTo(
+ FeatureCollection<SimpleFeatureType, SimpleFeature> features) {
+
+ CoordinateReferenceSystem mapCRS = getContext()
+ .getCoordinateReferenceSystem();
+ CoordinateReferenceSystem fCRS = features.getSchema()
+ .getGeometryDescriptor().getCoordinateReferenceSystem();
+
+ double width = mapArea.getWidth();
+ double height = mapArea.getHeight();
+ double ratio = height / width;
+
+ if (features == null || features.size() == 0) {
+ // feature count == 0 Zoom to the full extend
+ return;
+ } else if (features.size() == 1) {
+
+ // feature count == 1 Just move the window to the point and zoom 'a
+ // bit'
+ SimpleFeature singleFeature = (SimpleFeature) features.iterator()
+ .next();
+
+ if (((Geometry) 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;
+ }
+
+ 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("Looking for a Math transform", e);
+ } catch (TransformException e) {
+ LOGGER.error("Looking for a Math transform", e);
+ }
+ }
+
+ Coordinate newLeftBottom = new Coordinate(centre.x - width / 2.,
+ centre.y - height / 2.);
+ Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
+ centre.y + height / 2.);
+
+ Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
+
+ setMapArea(newMapArea);
+
+ } else {
+ ReferencedEnvelope fBounds = features.getBounds();
+
+ Envelope bounds;
+ if (!mapCRS.equals(fCRS)) {
+ bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
+ } else {
+ bounds = fBounds;
+ }
+ // BB umrechnen von Layer-CRS in Map-CRS
+
+ // Expand a bit
+ bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
+
+ setMapArea(bounds);
+ }
+ }
+
+ private void setRendererHints(Map<Object, Object> rendererHints) {
+ this.rendererHints = rendererHints;
+ }
+
+ /**
+ * Return <code>true</code> if a CRS and a {@link #mapArea} are set and the
+ * {@link XMapPane} is visible and has bounds set.
+ */
+ public boolean isWellDefined() {
+
+ try {
+
+ if (getContext() == null)
+ return false;
+ if (getContext().getLayerCount() <= 0)
+ return false;
+ if (getMapArea() == null)
+ return false;
+ if (getBounds().getWidth() == 0)
+ return false;
+ if (getBounds().getHeight() == 0)
+ return false;
+ } catch (Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Default delay (milliseconds) before the map will be redrawn when resizing
+ * the pane. This is to avoid flickering while drag-resizing.
+ */
+ public static final int DEFAULT_RESIZING_PAINT_DELAY = 500; // delay in
+ // milliseconds
+
+ private Timer resizeTimer;
+ private int resizingPaintDelay;
+ /**
+ * We store the old transform for a moment to use it for the
+ * "quick scaled preview" in case of ZoomIn
+ **/
+ protected AffineTransform oldScreenToWorld = null;
+
+ /**
+ * Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen
+ * MapPane-Funktion
+ */
+ protected Cursor staticCursor = null;
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Abhaengig von selState wird der Cursor gesetzt
+ */
+ public void updateCursorAndRepaintTimer() {
+
+ if (bgExecuter != null && bgExecuter.isRunning()
+ || localExecuter != null && localExecuter.isRunning()) {
+ setCursor(WAIT_CURSOR);
+ return;
+ } else {
+ // Allow one last rendering
+ if (repainterTimer.isRunning()) {
+ repainterTimer.stop();
+ updateFinalImage();
+ repaint();
+ }
+ }
+
+ // wenn manueller Cursor gesetzt ist, dann diesen verwenden (unabhaengig
+ // von der aktuellen Aktion
+ if (this.staticCursor != null) {
+ setCursor(staticCursor);
+ return;
+ }
+ if (getCursor() == SwingUtil.PANNING_CURSOR) {
+ // This cursor will reset itself
+ return;
+ }
+
+ // Je nach Aktion den Cursor umsetzen
+ switch (state) {
+ 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;
+ case PAN:
+ setCursor(SwingUtil.PAN_CURSOR);
+ break;
+ default:
+ setCursor(normalCursor);
+ break;
+ }
+ }
+
+ //
+ // /**
+ // * 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üger</a>
+ // */
+ // public Cursor getNormalCursor() {
+ // return normalCursor;
+ // }
+ //
+ // /**
+ // * 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üger</a>
+ // */
+ // public void setNormalCursor(Cursor normalCursor) {
+ // this.normalCursor = normalCursor;
+ // }
+
+ /**
+ * Berechnet die Transformation zwischen Fenster- und Karten-Koordinaten
+ * neu.
+ */
+ protected void resetTransforms() {
+ if (getMapArea() == null || getWidth() == 0 || getHeight() == 0)
+ return;
+
+ // We store the last Transform
+ oldScreenToWorld = screenToWorld;
+
+ this.screenToWorld = 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());
+
+ try {
+ this.worldToScreen = screenToWorld.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ LOGGER.error(e);
+ }
+ }
+
+ /**
+ * Transformation zwischen Fenster-Koordinaten und Karten-Koordinaten
+ * (lat/lon)
+ */
+ protected AffineTransform screenToWorld = null;
+
+ private AffineTransform worldToScreen;
+
+ /**
+ * Listens to changes of the "local" {@link MapContext} and triggers
+ * repaints where needed.
+ */
+ private MapLayerListListener localContextListener = new MapLayerListListener() {
+
+ @Override
+ public void layerAdded(final MapLayerListEvent event) {
+ event.getLayer().addMapLayerListener(localMapLayerListener);
+
+ if (localContext.getLayers().length == 1) { // the first one
+ // if the Area of Interest is unset, the LayerBounds are used
+ if (!setMapArea(localContext.getAreaOfInterest()))
+ repaint();
+
+ return;
+ }
+
+ // We need to redraw, even in case that the mapArea didn't change
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+
+ }
+
+ @Override
+ public void layerRemoved(final MapLayerListEvent event) {
+ if (event.getLayer() != null)
+ event.getLayer().removeMapLayerListener(localMapLayerListener);
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerChanged(final MapLayerListEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerMoved(final MapLayerListEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+ };
+
+ /**
+ * Listens to changes of the "background" {@link MapContext} and triggers
+ * repaints where needed.
+ */
+ private MapLayerListListener bgContextListener = new MapLayerListListener() {
+
+ @Override
+ public void layerAdded(final MapLayerListEvent event) {
+ event.getLayer().addMapLayerListener(bgMapLayerListener);
+
+ if (localContext.getLayers().length == 0
+ && bgContext.getLayers().length == 1) { // the first one and
+ // localContext is
+ // empty
+ if (!setMapArea(localContext.getAreaOfInterest()))
+ requestStartRendering();
+ return;
+ }
+
+ // We need to redraw, even in case that the mapArea didn't change
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+
+ }
+
+ @Override
+ public void layerRemoved(final MapLayerListEvent event) {
+ if (event.getLayer() != null)
+ event.getLayer().removeMapLayerListener(bgMapLayerListener);
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerChanged(final MapLayerListEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerMoved(final MapLayerListEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+ };
+
+ /**
+ * Listens to each layer in the local {@link MapContext} for changes and
+ * triggers repaints.
+ */
+ protected MapLayerListener localMapLayerListener = new MapLayerAdapter() {
+
+ @Override
+ public void layerShown(MapLayerEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerHidden(MapLayerEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerChanged(MapLayerEvent event) {
+ // Change of SLD for example
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+ };
+
+ /**
+ * Listens to each layer in the local {@link MapContext} for changes and
+ * triggers repaints.
+ */
+ protected MapLayerListener bgMapLayerListener = new MapLayerAdapter() {
+
+ @Override
+ public void layerShown(MapLayerEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerHidden(MapLayerEvent event) {
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+
+ @Override
+ public void layerChanged(MapLayerEvent event) {
+ // Change of SLD for example
+ // mapImageInvalid = true;
+ // repaint();
+ requestStartRendering();
+ }
+ };
+
+ /**
+ * 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 getScreenToWorld() {
+ if (screenToWorld == null)
+ resetTransforms();
+ // nur Kopie der Transformation zurueckgeben!
+ if (screenToWorld == null)
+ return null;
+ return new AffineTransform(screenToWorld);
+ }
+
+ public AffineTransform getWorldToScreenTransform() {
+ if (worldToScreen == null) {
+ resetTransforms();
+ }
+ // nur Kopie der Transformation zurueckgeben!
+ return new AffineTransform(worldToScreen);
+ }
+
+ public MapContext getContext() {
+ if (localContext == null) {
+ this.localContext = new DefaultMapContext();
+ this.localContext.addMapLayerListListener(localContextListener);
+ }
+ return localContext;
+ }
+
+ public MapContext getBgContext() {
+ return bgContext;
+ }
+
+ /**
+ *
+ * @param context
+ */
+ public void setLocalContext(final MapContext context) {
+ // Remove the default listener from the old context
+ if (this.localContext != null) {
+ this.localContext.removeMapLayerListListener(localContextListener);
+
+ // adding listener to all layers
+ for (MapLayer mapLayer : localContext.getLayers()) {
+ mapLayer.removeMapLayerListener(localMapLayerListener);
+ }
+ }
+
+ this.localContext = context;
+
+ if (context != null) {
+ setMapArea(localContext.getAreaOfInterest());
+
+ this.localContext.addMapLayerListListener(localContextListener);
+
+ // adding listener to all layers
+ for (MapLayer mapLayer : localContext.getLayers()) {
+ mapLayer.addMapLayerListener(localMapLayerListener);
+ }
+ }
+
+ mapImageInvalid = true;
+ repaint();
+ }
+
+ public void setBgContext(final MapContext context) {
+
+ // Remove the default listener from the old context
+ if (this.bgContext != null) {
+ this.bgContext.removeMapLayerListListener(bgContextListener);
+
+ // adding listener to all layers
+ for (MapLayer mapLayer : bgContext.getLayers()) {
+ mapLayer.removeMapLayerListener(bgMapLayerListener);
+ }
+ }
+
+ this.bgContext = context;
+
+ if (context != null) {
+ setMapArea(bgContext.getAreaOfInterest());
+
+ this.bgContext.addMapLayerListListener(bgContextListener);
+
+ // adding listener to all layers
+ for (MapLayer mapLayer : bgContext.getLayers()) {
+ mapLayer.addMapLayerListener(bgMapLayerListener);
+ }
+ }
+ mapImageInvalid = true;
+ repaint();
+ }
+
+ /**
+ * Returns a copy of the mapArea
+ *
+ * @return
+ */
+ public Envelope getMapArea() {
+ if (mapArea == null) {
+ final Rectangle paneBounds = getBounds();
+
+ try {
+ mapArea = localContext.getLayerBounds();
+ } catch (final IOException e) {
+ LOGGER.warn("context.getLayerBounds()", e);
+ }
+
+ if (mapArea != null) {
+ /* either the viewer size has changed or we've done a reset */
+ mapImageInvalid = true; /* note we need to redraw */
+ oldRect = paneBounds; /* store what the current size is */
+ mapArea = bestAllowedMapArea(mapArea);
+ }
+ }
+
+ if (mapArea == null)
+ return null;
+
+ return new Envelope(mapArea);
+ }
+
+ /**
+ * @param newMapArea
+ * @return <code>true</code> if the mapArea has been changed and a repaint
+ * has been triggered.
+ */
+ public boolean setMapArea(final Envelope newMapArea) {
+
+ if (newMapArea == null
+ || bestAllowedMapArea(newMapArea).equals(mapArea)) {
+ // No change.. no need to repaint
+ return false;
+ }
+
+ // Testen, ob der Unterschied nur im minimalen Rundungsfehlerbereich
+ // liegt
+ if (mapArea != null) {
+ Envelope candNew = bestAllowedMapArea(newMapArea);
+ double tolX = mapArea.getWidth() / 1000.;
+ double tolY = mapArea.getHeight() / 1000.;
+ if ((candNew.getMinX() - tolX < mapArea.getMinX())
+ && (mapArea.getMinX() < candNew.getMinX() + tolX)
+ && (candNew.getMaxX() - tolX < mapArea.getMaxX())
+ && (mapArea.getMaxX() < candNew.getMaxX() + tolX)
+
+ && (candNew.getMinY() - tolY < mapArea.getMinY())
+ && (mapArea.getMinY() < candNew.getMinY() + tolY)
+ && (candNew.getMaxY() - tolY < mapArea.getMaxY())
+ && (mapArea.getMaxY() < candNew.getMaxY() + tolY)
+
+ ) {
+ // The two mapAreas only differ my 1/1000th.. ignore
+
+ return false;
+ }
+ }
+
+ oldMapArea = mapArea;
+
+ System.out.println("requested setting to \\t" + newMapArea);
+ this.mapArea = bestAllowedMapArea(newMapArea);
+ System.out.println("set to \\t\\ŧ" + newMapArea);
+
+ if (localContext != null) {
+ localContext.setAreaOfInterest(mapArea, localContext
+ .getCoordinateReferenceSystem());
+ }
+ if (bgContext != null) {
+ bgContext.setAreaOfInterest(mapArea, localContext
+ .getCoordinateReferenceSystem());
+ }
+ resetTransforms();
+ mapImageInvalid = true;
+ mapAreaChanged = true;
+ repaint();
+ return true;
+ }
+
+ public int getState() {
+ return state;
+ }
+
+ /**
+ * Enables/Disables the ZOOM Mouse Listener. Upates the Cursor and stops the
+ * repaint Timer if
+ *
+ * @param state
+ */
+ public void setState(final int state) {
+ this.state = state;
+
+ zoomMapPaneMouseListener.setEnabled((state == ZOOM_IN
+ || state == ZOOM_OUT || state == PAN));
+
+ // Je nach Aktion den Cursor umsetzen
+ updateCursorAndRepaintTimer();
+ }
+
+ /** Cursor wenn kein Mausbutton gedrueckt wird. default oder SwingUtil.PAN **/
+ protected static Cursor normalCursor = Cursor
+ .getPredefinedCursor(Cursor.DEFAULT_CURSOR);
+
+ public static final Cursor WAIT_CURSOR = Cursor
+ .getPredefinedCursor(Cursor.WAIT_CURSOR);
+
+ public static final int NONE = -123;
+
+ private RenderingExecutor localExecuter;
+
+ private BufferedImage finalImage;
+
+ /**
+ * A flag set it {@link #setMapArea(Envelope)} to indicated the
+ * {@link #paintComponent(Graphics)} method, that the image on-screen is
+ * associated with {@link #oldMapArea} and may hence be scaled for a quick
+ * preview.<br/>
+ * The flag is reset
+ **/
+ private boolean mapAreaChanged = false;
+
+ private JFrame finalImageFrame;
+
+ private volatile Boolean requestStartRendering = false;
+ private BufferedImage preFinalImage;
+
+ protected void paintComponent(final Graphics g) {
+ // Maybe update the cursor
+ updateCursorAndRepaintTimer();
+
+ if (!acceptsRepaintCalls)
+ return;
+
+ boolean paintedSomething = false;
+
+ if (mapImageInvalid) { /* if the map changed then redraw */
+
+ mapImageInvalid = false; // Reset for next round
+
+ // If the new mapArea and the oldMapArea intersect, we can draw some
+ // quick scaled preview to make the user feel that something is
+ // happening.
+ if (mapAreaChanged && oldMapArea != null
+ && getMapArea().intersects(oldMapArea)
+ & !getMapArea().equals(oldMapArea)) {
+
+ mapAreaChanged = false;
+
+ if (getMapArea().covers(oldMapArea)) {
+ setQuickPreviewHint(ZOOM_OUT);
+ paintedSomething = drawScaledPreviewImage_Zoom((Graphics2D) g);
+ } else if (oldMapArea.covers(getMapArea())) {
+ setQuickPreviewHint(ZOOM_IN);
+ paintedSomething = drawScaledPreviewImage_Zoom((Graphics2D) g);
+ }
+
+ }
+
+ if (paneResized) {
+ paneResized = false;
+ preFinalImage = null;
+ finalImage = null;
+ localImage = null;
+ bgImage = null;
+// gadgetsImage = null;
+ }
+
+ // Start the Threads and Timers to render the image
+ requestStartRendering();
+
+ }
+
+ if (!paintedSomething) {
+
+ // TODO Should just paint the getFinalImage(). Update should be
+ // called by timer every 300ms, and the repaint() until all threads
+ // are done.
+ g.drawImage(getFinalImage(), 0, 0, this);
+
+ paintedSomething = true;
+ }
+
+ }
+
+ /**
+ * Cancels all running renderers and sets the flag to start new ones. <br/>
+ *
+ * @see #startRenderThreadsTimer
+ */
+ private void requestStartRendering() {
+ if (bgExecuter != null)
+ bgExecuter.cancelTask();
+ if (localExecuter != null)
+ localExecuter.cancelTask();
+ requestStartRendering = true;
+ }
+
+ /**
+ * 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 = getScreenToWorld();
+ 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 Geo-Koordinaten-Bereich in Fenster-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
+ * @param winToGeotransform
+ * Eine Window to Geo transform. If <code>null</code>,
+ * {@link #getScreenToWorld()} is used.
+ */
+ public Envelope tranformGeoToWindow(double ox, double oy, double px,
+ double py, AffineTransform winToGeotransform) {
+ AffineTransform at = winToGeotransform == null ? getScreenToWorld()
+ : winToGeotransform;
+ Point2D geoO;
+ try {
+ geoO = at.inverseTransform(new Point2D.Double(ox, oy), null);
+ Point2D geoP = at
+ .inverseTransform(new Point2D.Double(px, py), null);
+ return new Envelope(geoO.getX(), geoP.getX(), geoO.getY(), geoP
+ .getY());
+ } catch (NoninvertibleTransformException e) {
+ LOGGER.error(e);
+ return new Envelope(ox, oy, px, py);
+ }
+ }
+
+ /**
+ * Diretly paints scaled preview into the {@link SelectableXMapPane}. Used
+ * to give the user something to look at while we are rendering. Method
+ * should be called after {@link #setMapArea(Envelope)} has been set to the
+ * new mapArea and transform has been reset.<br/>
+ * This method does nothing if the {@link #lastRenderingDuration} is smaller
+ * then a trashhold.
+ *
+ * @param g
+ * Graphics2D to paint the preview into
+ *
+ * @param state
+ * Max be {@link #ZOOM_IN} or {@link #ZOOM_OUT}
+ */
+ protected boolean drawScaledPreviewImage_Zoom(Graphics2D graphics) {
+
+ if (quickPreviewHint == 0)
+ return false;
+
+ graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_OFF);
+ graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_SPEED);
+
+ if (oldMapArea == null)
+ return false;
+
+ Rectangle visibleArea = getVisibleRect();
+
+ // Calculate the oldMapArea in the current WindowCoordinates:
+ Envelope oldMapWindow = tranformGeoToWindow(oldMapArea.getMinX(),
+ oldMapArea.getMinY(), oldMapArea.getMaxX(), oldMapArea
+ .getMaxY(), null);
+
+ int xx1 = (int) Math.round(oldMapWindow.getMinX());
+ int yy1 = (int) Math.round(oldMapWindow.getMinY());
+ int xx2 = (int) Math.round(oldMapWindow.getMaxX());
+ int yy2 = (int) Math.round(oldMapWindow.getMaxY());
+
+ graphics.drawImage(getPreFinalImage(), xx1, yy1, xx2, yy2,
+ (int) visibleArea.getMinX(), (int) visibleArea.getMinY(),
+ (int) visibleArea.getMaxX(), (int) visibleArea.getMaxY(),
+ getMapBackgroundColor(), null);
+
+
+ Rectangle painedArea = new Rectangle(xx1, yy1, xx2 - xx1, yy2 - yy1);
+
+ SwingUtil.clearAround(graphics, painedArea, visibleArea);
+
+ addGadgets(graphics);
+// graphics.drawImage(getGadgetsImage(), 0,0, (int) visibleArea.getMaxX(), (int) visibleArea.getMaxY(),null);
+
+ quickPreviewHint = 0;
+
+ graphics.dispose();
+ // Something has been drawn
+ return true;
+ }
+
+ final static Font waitFont = new Font("Arial", Font.BOLD, 30);
+
+ /**
+ * Paints some optinal stuff into the given {@link Graphics2D}. Usually called as the last paint on the mapImage.
+ */
+ private void addGadgets(Graphics2D graphics) {
+
+ if (mapImage != null)
+ graphics.drawImage(mapImage,
+ getBounds().width - mapImage.getWidth() - 10,
+ getBounds().height - mapImage.getHeight() - 10, this);
+
+ // If still rendering, paint a gray shadow or so...
+ if (bgExecuter != null && bgExecuter.isRunning()
+ || localExecuter != null && localExecuter.isRunning()) {
+ graphics.setColor(Color.BLACK);
+
+ graphics.setFont(waitFont);
+ graphics.drawString("Wait...", 40, 70);
+ }
+
+ }
+
+ /**
+ * Accumulates all three images
+ *
+ * @return
+ */
+ synchronized protected BufferedImage updateFinalImage() {
+
+ final Graphics2D finalG = (Graphics2D) getFinalImage().getGraphics();
+ finalG.setBackground(getMapBackgroundColor());
+
+
+ // Render the two map images first, into the preFinalImage
+ {
+ final Graphics2D preFinalG = (Graphics2D) getPreFinalImage().getGraphics();
+ preFinalG.setBackground(getMapBackgroundColor());
+
+ preFinalG.drawImage(getBgImage(), 0, 0,
+ getMapBackgroundColor(), null);
+ // // Draw the local layers image
+ preFinalG.drawImage(getLocalImage(), 0, 0, null);
+ preFinalG.dispose();
+ }
+
+ finalG.drawImage(getPreFinalImage(), imageOrigin.x, imageOrigin.y,
+ getMapBackgroundColor(), null);
+
+ // System.out.println(new Date().getTime() - startTime +
+ // "ms for update");
+ //
+ // if (finalImageFrame == null) {
+ // finalImageFrame = new JFrame();
+ // finalImageFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ // SwingUtil.setRelativeFramePosition(finalImageFrame, 0, 0);
+ // }
+ // finalImageFrame.setContentPane(new JLabel(new
+ // ImageIcon(finalImage)));
+ // finalImageFrame.pack();
+ // finalImageFrame.setVisible(true);
+
+ final int finalImageHeight = getFinalImage().getHeight(null);
+ final int finalImageWidth = getFinalImage().getWidth(null);
+
+ Rectangle painedArea = new Rectangle(imageOrigin.x, imageOrigin.y,
+ finalImageWidth, finalImageHeight);
+ SwingUtil.clearAround(finalG, painedArea, getVisibleRect());
+
+ addGadgets(finalG);
+// finalG.drawImage(getGadgetsImage(), 0, 0, null);
+
+ finalG.dispose();
+
+ return finalImage;
+ }
+
+ /*
+ * Set alpha composite. For example, pass in 1.0f to have 100% opacity pass
+ * in 0.25f to have 25% opacity.
+ */
+ private AlphaComposite makeComposite(float alpha) {
+ int type = AlphaComposite.SRC_OVER;
+ return (AlphaComposite.getInstance(type, alpha));
+ }
+
+ private Image getFinalImage() {
+
+ if (finalImage == null) {
+ finalImage = null;
+ Rectangle curPaintArea = getVisibleRect();
+ finalImage = new BufferedImage(curPaintArea.width,
+ curPaintArea.height, BufferedImage.TYPE_INT_RGB);
+
+ requestStartRendering();
+ }
+ return finalImage;
+ }
+
+ private Image getPreFinalImage() {
+
+ if (preFinalImage == null) {
+ preFinalImage = null;
+ Rectangle curPaintArea = getVisibleRect();
+
+ preFinalImage = new BufferedImage(curPaintArea.width,
+ curPaintArea.height, BufferedImage.TYPE_INT_RGB);
+
+ requestStartRendering();
+ }
+ return preFinalImage;
+ }
+
+ /**
+ * While dragging, the {@link #updateFinalImage()} method is translating the
+ * cached images while setting it together.
+ **/
+ Point imageOrigin = new Point(0, 0);
+
+ /**
+ * Starts rendering on one or two threads
+ */
+ private void startRendering() {
+
+ if (!isWellDefined())
+ return;
+
+ if (bgExecuter != null)
+ // Stop all renderers
+ bgExecuter.cancelTask();
+
+ if (localExecuter != null)
+ localExecuter.cancelTask();
+ //
+ //
+ // LOGGER.debug("stopping any running renderes:");
+ // int count = 0;
+ // while (bgExecuter.isRunning() || localExecuter.isRunning()) {
+ // LOGGER.debug("waiting for threads to stop");
+ //
+ // bgExecuter.cancelTask();
+ // localExecuter.cancelTask();
+ //
+ // count++;
+ //
+ // try {
+ // Thread.sleep(100);
+ // } catch (InterruptedException e) {
+ // LOGGER.error(e);
+ // }
+ //
+ // if (count > 100) {
+ // throw new RuntimeException(
+ // "Unable to stop rendering thread for 10secs");
+ // }
+ // }
+ // LOGGER.debug(" threads stopped after " + count / 10. + "secs");
+
+ Rectangle curPaintArea = getVisibleRect();
+
+ // allow a single pixel margin at the right and bottom edges
+ curPaintArea.width -= 1;
+ curPaintArea.height -= 1;
+
+ labelCache.clear();
+
+ /**
+ */
+
+ /**
+ * We have to set new renderer
+ */
+
+ if (getBgContext() != null) {
+ bgExecuter = new RenderingExecutor(this);
+ LOGGER.debug("starting bg renderer:");
+ // /* System.out.println("rendering"); */
+ final GTRenderer createGTRenderer = GTUtil.createGTRenderer(
+ localContext, getRendererHints());
+ createGTRenderer.setJava2DHints(getJava2dHints());
+ bgExecuter.submit(getBgContext().getAreaOfInterest(), curPaintArea,
+ (Graphics2D) getBgImage().getGraphics(), createGTRenderer);
+ }
+
+ if (getContext() != null) {
+ localExecuter = new RenderingExecutor(this);
+ LOGGER.debug("starting local renderer:");
+ final GTRenderer createGTRenderer = GTUtil.createGTRenderer(
+ localContext, getRendererHints());
+ createGTRenderer.setJava2DHints(getJava2dHints());
+ localExecuter.submit(getContext().getAreaOfInterest(),
+ curPaintArea, (Graphics2D) getLocalImage().getGraphics(),
+ createGTRenderer);
+ }
+
+ updateCursorAndRepaintTimer();
+
+ // start regular repaints until all renderers are done.
+ repainterTimer.setRepeats(true);
+ repainterTimer.restart();
+
+ }
+
+ /**
+ * Lazyly initializes a {@link BufferedImage} for the background renderer.
+ */
+ private BufferedImage getBgImage() {
+
+ if (bgImage == null) {
+ LOGGER.debug("creating a new background image");
+
+ Rectangle curPaintArea = getVisibleRect();
+ // allow a single pixel margin at the right and bottom edges
+ curPaintArea.width -= 1;
+ curPaintArea.height -= 1;
+
+ bgImage = new BufferedImage(curPaintArea.width + 1,
+ curPaintArea.height + 1, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ return bgImage;
+ }
+
+ /** An (transparent) image to paint over the map in the lower right corner **/
+ private BufferedImage mapImage = null;
+
+ private boolean acceptsRepaintCalls = true;
+
+ /**
+ * 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;
+// gadgetsImage = null;
+ }
+
+ /**
+ * Lazyly initializes a {@link BufferedImage} for the background renderer.
+ */
+ private BufferedImage getLocalImage() {
+
+ if (localImage == null) {
+ LOGGER.debug("creating a new local image");
+
+ Rectangle curPaintArea = getVisibleRect();
+ // allow a single pixel margin at the right and bottom edges
+ curPaintArea.width -= 1;
+ curPaintArea.height -= 1;
+
+ localImage = new BufferedImage(curPaintArea.width + 1,
+ curPaintArea.height + 1, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ return localImage;
+ }
+//
+// /**
+// * Lazyly initializes a {@link BufferedImage} for the background renderer.
+// */
+// private BufferedImage getGadgetsImage() {
+//
+// if (gadgetsImage == null) {
+// LOGGER.debug("creating a new gadgets image");
+//
+// Rectangle curPaintArea = getVisibleRect();
+// // allow a single pixel margin at the right and bottom edges
+// curPaintArea.width -= 1;
+// curPaintArea.height -= 1;
+//
+// gadgetsImage = new BufferedImage(curPaintArea.width + 1,
+// curPaintArea.height + 1, BufferedImage.TYPE_INT_ARGB);
+//
+// if (mapImage != null)
+// gadgetsImage.getGraphics().drawImage(mapImage,
+// curPaintArea.width - mapImage.getWidth() - 10,
+// curPaintArea.height - mapImage.getHeight() - 10, this);
+//
+// }
+//
+// return gadgetsImage;
+// }
+
+ /**
+ * Called by the {@linkplain XMapPane.RenderingTask} when rendering has been
+ * completed Publishes a {@linkplain MapPaneEvent} of type {@code
+ * MapPaneEvent.Type.RENDERING_STOPPED} to listeners.
+ *
+ * @see MapPaneListener#onRenderingStopped(org.geotools.swing.event.MapPaneEvent)
+ */
+ public void onRenderingCompleted() {
+ System.out.println("onRenderingCompleted");
+
+ updateFinalImage();
+
+ repaint();
+
+ }
+
+ /**
+ * Called by the {@linkplain XMapPane.RenderingTask} when rendering was
+ * cancelled. Publishes a {@linkplain MapPaneEvent} of type {@code
+ * MapPaneEvent.Type.RENDERING_STOPPED} to listeners.
+ *
+ * @see MapPaneListener#onRenderingStopped(org.geotools.swing.event.MapPaneEvent)
+ */
+ public void onRenderingCancelled() {
+ LOGGER.debug("Rendering cancelled");
+ }
+
+ /**
+ * Called by the {@linkplain XMapPane.RenderingTask} when rendering failed.
+ * Publishes a {@linkplain MapPaneEvent} of type {@code
+ * MapPaneEvent.Type.RENDERING_STOPPED} to listeners.
+ *
+ * @param renderingError
+ * The error that occured during rendering
+ *
+ * @see MapPaneListener#onRenderingStopped(org.geotools.swing.event.MapPaneEvent)
+ */
+ public void onRenderingFailed(Exception renderingError) {
+ // MapPaneEvent ev = new MapPaneEvent(this,
+ // MapPaneEvent.Type.RENDERING_STOPPED);
+ // publishEvent(ev);
+ LOGGER.warn("Rendering failed", renderingError);
+ updateFinalImage();
+ repaint();
+
+ }
+
+ /**
+ * Called when a rendering request has been rejected. This will be common,
+ * such as when the user pauses during drag-resizing fo the map pane. The
+ * base implementation does nothing. It is provided for sub-classes to
+ * override if required.
+ */
+ public void onRenderingRejected() {
+ LOGGER.warn("Rendering rejected");
+ repaint();
+ }
+
+ @Override
+ public void propertyChange(final PropertyChangeEvent evt) {
+ final String prop = evt.getPropertyName();
+
+ if (prop.equalsIgnoreCase("crs")) {
+ localContext.setAreaOfInterest(localContext.getAreaOfInterest(),
+ (CoordinateReferenceSystem) evt.getNewValue());
+ }
+ }
+
+ // xulu.sn
+ /**
+ * Korrigiert den {@link Envelope} aka {@code mapArea} auf die beste
+ * erlaubte Flaeche damit die Massstabsbeschaenkungen noch eingehalten
+ * werden, FALLS der uebergeben Envelope nicht schon gueltig sein sollte.<br/>
+ * Since 21. April 09: Before thecalculation starts, the aspect ratio is
+ * corrected. This change implies, that setMapArea() will most of the time
+ * not allow setting to a wrong aspectRatio.
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public Envelope bestAllowedMapArea(Envelope env) {
+ if (getWidth() == 0)
+ return env;
+ if (env == null)
+ return null;
+
+ Envelope newArea = null;
+
+ /**
+ * Correct the aspect Ratio before we check the rest. Otherwise we might
+ * easily fail. We allow to grow here, because we don't check against
+ * the maxExtend
+ */
+ Rectangle curPaintArea = getVisibleRect();
+
+ env = JTSUtil.fixAspectRatio(curPaintArea, env, true);
+
+ final double scale = env.getWidth() / getWidth();
+ final double centerX = env.getMinX() + env.getWidth() / 2.;
+ final double centerY = env.getMinY() + env.getHeight() / 2.;
+ double newWidth2 = 0;
+ double newHeight2 = 0;
+ if (scale < getMaxZoomScale()) {
+ // ****************************************************************************
+ // Wir zoomen weiter rein als erlaubt => Anpassen des envelope
+ // ****************************************************************************
+ newWidth2 = getMaxZoomScale() * getWidth() / 2.;
+ newHeight2 = getMaxZoomScale() * getHeight() / 2.;
+ } else if (scale > getMinZoomScale()) {
+ // ****************************************************************************
+ // Wir zoomen weiter raus als erlaubt => Anpassen des envelope
+ // ****************************************************************************
+ newWidth2 = getMinZoomScale() * getWidth() / 2.;
+ newHeight2 = getMinZoomScale() * getHeight() / 2.;
+ } else {
+ // ****************************************************************************
+ // Die mapArea / der Envelope ist ist gueltig! Keine Aenderungen
+ // ****************************************************************************
+ newArea = env;
+ }
+
+ if (newArea == null) {
+
+ final Coordinate ll = new Coordinate(centerX - newWidth2, centerY
+ - newHeight2);
+ final Coordinate ur = new Coordinate(centerX + newWidth2, centerY
+ + newHeight2);
+
+ newArea = new Envelope(ll, ur);
+ }
+
+ Envelope maxAllowedExtend = getMaxExtend();
+ while (maxAllowedExtend != null && !maxAllowedExtend.contains(newArea)
+ && newArea != null && !newArea.isNull()
+ && !Double.isNaN(newArea.getMinX())
+ && !Double.isNaN(newArea.getMaxX())
+ && !Double.isNaN(newArea.getMinY())
+ && !Double.isNaN(newArea.getMaxY())) {
+ /*
+ * If a maxExtend is set, we have to honour that...
+ */
+
+ // Exceeds top? Move down and maybe cut
+ if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) {
+ double divY = newArea.getMaxY() - maxAllowedExtend.getMaxY();
+ // LOGGER.debug("Moving area down by " + divY);
+
+ newArea = new Envelope(new Coordinate(newArea.getMinX(),
+ newArea.getMinY() - divY), new Coordinate(newArea
+ .getMaxX(), newArea.getMaxY() - divY));
+
+ if (newArea.getMinY() < maxAllowedExtend.getMinY()) {
+ // LOGGER.debug("Now it exeeds the bottom border.. cut!");
+ // And cut the bottom if it moved out of the area
+ newArea = new Envelope(new Coordinate(newArea.getMinX(),
+ maxAllowedExtend.getMinY()), new Coordinate(newArea
+ .getMaxX(), newArea.getMaxY()));
+
+ // LOGGER.debug("and fix aspect ratio");
+
+ newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
+ false);
+ }
+ }
+
+ // Exceeds bottom? Move up and maybe cut
+ if (newArea.getMinY() < maxAllowedExtend.getMinY()) {
+ double divY = newArea.getMinY() - maxAllowedExtend.getMinY();
+ // LOGGER.debug("Moving area up by " + divY);
+
+ newArea = new Envelope(new Coordinate(newArea.getMinX(),
+ newArea.getMinY() - divY), new Coordinate(newArea
+ .getMaxX(), newArea.getMaxY() - divY));
+
+ if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) {
+ // LOGGER.debug("Now it exeeds the top border.. cut!");
+ // And cut the bottom if it moved out of the area
+ newArea = new Envelope(new Coordinate(newArea.getMinX(),
+ newArea.getMinY()), new Coordinate(newArea
+ .getMaxX(), maxAllowedExtend.getMaxY()));
+
+ // LOGGER.debug("and fix aspect ratio");
+
+ newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
+ false);
+ }
+ }
+
+ // Exceeds to the right? move and maybe cut
+ if (newArea.getMaxX() > maxAllowedExtend.getMaxX()) {
+
+ // Move left..
+ double divX = newArea.getMaxX() - maxAllowedExtend.getMaxX();
+ // LOGGER.debug("Moving area left by " + divX);
+
+ newArea = new Envelope(new Coordinate(newArea.getMinX() - divX,
+ newArea.getMinY()), new Coordinate(newArea.getMaxX()
+ - divX, newArea.getMaxY()));
+
+ if (newArea.getMinX() < maxAllowedExtend.getMinX()) {
+ // LOGGER.debug("Now it exeeds the left border.. cut!");
+ // And cut the left if it moved out of the area
+ newArea = new Envelope(new Coordinate(maxAllowedExtend
+ .getMinX(), newArea.getMinY()), new Coordinate(
+ newArea.getMaxX(), newArea.getMaxY()));
+
+ // LOGGER.debug("and fix aspect ratio");
+
+ newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
+ false);
+ }
+ }
+
+ // Exceeds to the left? move and maybe cut
+ if (newArea.getMinX() < maxAllowedExtend.getMinX()) {
+
+ // Move right..
+ double divX = newArea.getMinX() - maxAllowedExtend.getMinX();
+ // LOGGER.debug("Moving area right by " + divX);
+
+ newArea = new Envelope(new Coordinate(newArea.getMinX() - divX,
+ newArea.getMinY()), new Coordinate(newArea.getMaxX()
+ - divX, newArea.getMaxY()));
+
+ if (newArea.getMaxX() > maxAllowedExtend.getMaxX()) {
+ // LOGGER.debug("Now it exeeds the right border.. cut!");
+ // And cut the left if it moved out of the area
+ newArea = new Envelope(new Coordinate(newArea.getMinX(),
+ newArea.getMinY()), new Coordinate(maxAllowedExtend
+ .getMaxX(), newArea.getMaxY()));
+
+ // LOGGER.debug("and fix aspect ratio");
+
+ newArea = JTSUtil.fixAspectRatio(this.getBounds(), newArea,
+ false);
+ }
+ }
+
+ }
+
+ return newArea;
+ }
+
+ /**
+ * Retuns the minimum allowed zoom scale. This is the bigger number value of
+ * the two. Defaults to {@link Double}.MAX_VALUE
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public Double getMinZoomScale() {
+ return minZoomScale;
+ }
+
+ /**
+ * Retuns the maximum allowed zoom scale. This is the smaller number value
+ * of the two. Defaults to {@link Double}.MIN_VALUE
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public Double getMaxZoomScale() {
+ return maxZoomScale;
+ }
+
+ /**
+ * Set the maximum allowed zoom scale. This is the smaller number value of
+ * the two. If <code>null</code> is passed, Double.MINVALUE are used which
+ * mean there is no restriction.
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public void setMaxZoomScale(final Double maxZoomScale) {
+ this.maxZoomScale = maxZoomScale == null ? Double.MIN_VALUE
+ : maxZoomScale;
+ }
+
+ /**
+ * Set the minimum (nearest) allowed zoom scale. This is the bigger number
+ * value of the two. If <code>null</code> is passed, Double.MAXVALUE are
+ * used which mean there is no restriction.
+ *
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public void setMinZoomScale(final Double minZoomScale) {
+ this.minZoomScale = minZoomScale == null ? Double.MAX_VALUE
+ : minZoomScale;
+ }
+
+ /**
+ * Defines an evelope of the viwable area. The JMapPane will never show
+ * anything outside of this extend.
+ *
+ * @param maxExtend
+ * <code>null</code> to not have this restriction.
+ */
+ public void setMaxExtend(Envelope maxExtend) {
+ this.maxExtend = maxExtend;
+ }
+
+ /**
+ * Returns the evelope of the viewable area. The JMapPane will never show
+ * anything outside of this extend. If this has been set to
+ * <code>null</code> via {@link #setMaxExtend(Envelope)}, it tries to return
+ * quickly the context's bounds. It it takes to long to determine the
+ * context bounds, <code>null</code> is returned.
+ *
+ * @param maxExtend
+ * <code>null</code> to not have this restriction.
+ */
+
+ public Envelope getMaxExtend() {
+ if (maxExtend == null) {
+ final ReferencedEnvelope layerBounds = GTUtil
+ .getVisibleLayoutBounds(localContext);
+ if (layerBounds == null) {
+ // TODO Last fallback could be the CRS valid area
+ return null;
+ }
+
+ // Kartenbereich um 10% vergroessern
+ return JTSUtil.fixAspectRatio(this.getBounds(), JTSUtil
+ .expandEnvelope(layerBounds, 0.1), true);
+ }
+ return maxExtend;
+ }
+
+ /**
+ * Set the background color of the map.
+ *
+ * @param if <code>null</code>, white is used.
+ */
+ public void setMapBackgroundColor(Color bgColor) {
+ if (bgColor == null)
+ bgColor = Color.WHITE;
+ this.mapBackgroundColor = bgColor;
+ }
+
+ /**
+ * Returns the background {@link Color} of the map pane. Default is white.
+ **/
+ public Color getMapBackgroundColor() {
+ return mapBackgroundColor;
+ }
+
+ /**
+ *
+ * @param b
+ */
+ public void setPainting(boolean b) {
+ acceptsRepaintCalls = b;
+ }
+
+ /**
+ * Fuegt der Map einen Listener hinzu.
+ *
+ * @param l
+ * neuer Listener
+ */
+ public void addMapPaneListener(JMapPaneListener l) {
+ mapPaneListeners.add(l);
+ }
+
+ /**
+ * Liste der angeschlossenen Listener, die auf Aktionen des MapPanes
+ * lauschen.
+ */
+ protected Vector<JMapPaneListener> mapPaneListeners = new Vector<JMapPaneListener>();
+
+ /**
+ * A flag indicating if dispose() was already called. If true, then further
+ * use of this {@link SelectableXMapPane} is undefined.
+ */
+ private boolean disposed = false;
+
+ /**
+ * Entfernt einen Listener von der Map.
+ *
+ * @param l
+ * zu entfernender Listener
+ */
+ public void removeMapPaneListener(JMapPaneListener l) {
+ mapPaneListeners.remove(l);
+ }
+
+ /** Stored the time used for the last real rendering in ms. **/
+ private long lastRenderingDuration = Long.MAX_VALUE;
+
+ // if null, no quick preview will be shown
+ private int quickPreviewHint = 0;
+
+ /**
+ * For every rendering thread started,
+ * {@link GTUtil#createGTRenderer(MapContext)} is called to create a new
+ * renderer. These Java2D rendering hints are passed to the
+ * {@link GTRenderer}. The java2dHints are the same for all renderers (bg
+ * and local).
+ */
+ private RenderingHints java2dHints;
+
+ /**
+ * Returns in milli seconds the time the last rending of the
+ * {@link SelectableXMapPane} took. #Long.MAX_VALUE if the JMapPane has not
+ * been rendered yet.
+ */
+ public long getLastRenderingDuration() {
+ return lastRenderingDuration;
+ }
+
+ /**
+ * 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üger</a>
+ */
+ public void dispose() {
+ if (isDisposed())
+ return;
+
+ disposed = true;
+
+ if (bgExecuter != null) {
+ bgExecuter.cancelTask();
+ }
+
+ if (localExecuter != null) {
+ localExecuter.cancelTask();
+ }
+
+ startRenderThreadsTimer.stop();
+ repainterTimer.stop();
+
+ if (bgImage != null)
+ bgImage.flush();
+ if (localImage != null)
+ localImage.flush();
+// if (gadgetsImage != null)
+// gadgetsImage.flush();
+ if (finalImage != null)
+ finalImage.flush();
+ if (preFinalImage != null)
+ preFinalImage.flush();
+
+ // if (dragWaitCursorListener != null)
+ // this.removeMouseListener(dragWaitCursorListener);
+ // if (mouseWheelZoomListener != null)
+ // this.removeMouseWheelListener(mouseWheelZoomListener);
+
+ // Alle mapPaneListener entfernen
+ mapPaneListeners.clear();
+
+ removeMouseMotionListener(zoomMapPaneMouseListener);
+ removeMouseListener(zoomMapPaneMouseListener);
+
+ if (localContext != null)
+ getContext().clearLayerList();
+ if (bgContext != null)
+ getBgContext().clearLayerList();
+
+ removeAll();
+ }
+
+ /**
+ * A flag indicating if dispose() has already been called. If true, then
+ * further use of this {@link SelectableXMapPane} is undefined.
+ */
+ private boolean isDisposed() {
+ return disposed;
+ }
+
+ public void setQuickPreviewHint(int quickPreviewHint) {
+ this.quickPreviewHint = quickPreviewHint;
+
+ }
+
+ public void setJava2dHints(RenderingHints java2dHints) {
+ this.java2dHints = java2dHints;
+ }
+
+ public RenderingHints getJava2dHints() {
+ return java2dHints;
+ }
+
+ /**
+ * Zooms towards a point.
+ *
+ * @param center
+ * position in window coordinates
+ * @param zoomFaktor
+ * > 1 for zoom in, < 1 for zoom out. Default is 1.33.
+ */
+ public void zoomTo(Point center, Double zoomFaktor) {
+ if (zoomFaktor == null || zoomFaktor == 0.)
+ zoomFaktor = 2.;
+
+ Point2D gcenter = getScreenToWorld().transform(center, null);
+ center = null;
+
+ if (
+ Double.isNaN(gcenter.getX()) || Double.isNaN(gcenter.getY())
+ ||
+ Double.isInfinite(gcenter.getX()) || Double.isInfinite(gcenter.getY())
+
+ ) {
+ // Not inside valid CRS area! cancel
+ return;
+ }
+
+ final Envelope mapArea = getMapArea();
+
+ Envelope newMapArea = new Envelope(mapArea);
+ newMapArea
+ .expandBy((mapArea.getWidth() * zoomFaktor - mapArea
+ .getWidth()) / 2., (mapArea.getHeight()
+ * zoomFaktor - mapArea.getHeight()) / 2.);
+
+ // Move the newMapArea above the new center
+ newMapArea.translate(gcenter.getX() - mapArea.centre().x, gcenter.getY()
+ - mapArea.centre().y);
+
+ setMapArea(newMapArea);
+ }
+
+ /**
+ * Zooms towards a point.
+ *
+ * @param center
+ * position in window coordinates
+ * @param zoomFactor
+ * > 1 for zoom in, < 1 for zoom out. Default is 1.33
+ */
+ public void zoomTo(Point center) {
+ zoomTo(center, null);
+ }
+
+ public void mouseDragged(Point startPos, Point lastPos, MouseEvent event) {
+
+ if ((getState() == XMapPane.PAN)
+ || ((event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0)) {
+
+ if (getCursor() != SwingUtil.PANNING_CURSOR) {
+ setCursor(SwingUtil.PANNING_CURSOR);
+
+ // While panning, we deactivate the rendering. So the tasts are
+ // ready to start when the panning os done.
+ if (bgExecuter != null)
+ bgExecuter.cancelTask();
+ if (localExecuter != null)
+ localExecuter.cancelTask();
+ }
+
+ if (lastPos.x > 0 && lastPos.y > 0) {
+ final int dx = event.getX() - lastPos.x;
+ final int dy = event.getY() - lastPos.y;
+
+ // TODO Stop dragging when the drag would not be valid...
+ // boolean dragValid = true;
+ // // check if this panning results in a valid mapArea
+ // {
+ // Rectangle winBounds = xMapPane.getBounds();
+ // winBounds.translate(xMapPane.imageOrigin.x,
+ // -xMapPane.imageOrigin.y);
+ // Envelope newMapAreaBefore = xMapPane.tranformWindowToGeo(
+ // winBounds.x, winBounds.y, winBounds.x
+ // + winBounds.width, winBounds.y
+ // + winBounds.height);
+ //
+ //
+ // winBounds = xMapPane.getBounds();
+ // Point testIng = new Point(xMapPane.imageOrigin);
+ // testIng.translate(dx, dy);
+ // winBounds.translate(testIng.x, -testIng.y);
+ // Envelope newMapAreaAfter = xMapPane.tranformWindowToGeo(
+ // winBounds.x, winBounds.y, winBounds.x
+ // + winBounds.width, winBounds.y
+ // + winBounds.height);
+ //
+ // // If the last drag doesn't change the MapArea anymore cancel
+ // it.
+ // if (xMapPane.bestAllowedMapArea(newMapAreaAfter).equals(
+ // xMapPane.bestAllowedMapArea(newMapAreaBefore))){
+ // dragValid = false;
+ // return;
+ // }
+ // }
+
+ imageOrigin.translate(dx, dy);
+ updateFinalImage();
+ repaint();
+ }
+
+ } else if ((getState() == XMapPane.ZOOM_IN)
+ || (getState() == XMapPane.ZOOM_OUT)
+ || (getState() == XMapPane.SELECT_ALL)
+ || (getState() == XMapPane.SELECT_TOP)
+ // || (getState() == XMapPane.SELECT_ONE_FROM_TOP)
+ ) {
+ final Graphics graphics = getGraphics();
+
+ drawRectangle(graphics, startPos, event.getPoint());
+
+ if ((lastPos.x > 0) && (lastPos.y > 0)) {
+ drawRectangle(graphics, startPos, lastPos);
+ }
+
+ }
+
+ }
+
+ /**
+ * Draws a rectangle in XOR mode from the origin at {@link #startPos} to the
+ * given point. All in screen coordinates.
+ */
+ protected void drawRectangle(final Graphics graphics, Point startPos,
+ Point e) {
+ // undraw last box/draw new box
+ final int left = Math.min(startPos.x, e.x);
+ final int right = Math.max(startPos.x, e.x);
+ final int top = Math.max(startPos.y, e.y);
+ final int bottom = Math.min(startPos.y, e.y);
+ final int width = right - left;
+ final int height = top - bottom;
+
+ if (width == 0 && height == 0)
+ return;
+
+ graphics.setXORMode(Color.WHITE);
+ graphics.drawRect(left, bottom, width, height);
+ }
+
+ /**
+ * Finalizes a PAN action
+ */
+ public void performPan() {
+ Rectangle winBounds = getBounds();
+ winBounds.translate(-imageOrigin.x, -imageOrigin.y);
+ Envelope newMapArea = tranformWindowToGeo(winBounds.x, winBounds.y,
+ winBounds.x + winBounds.width, winBounds.y + winBounds.height);
+
+ imageOrigin.x = 0;
+ imageOrigin.y = 0;
+
+ if (!setMapArea(newMapArea)){
+ updateFinalImage();
+ repaint();
+ }
+
+ if (getCursor() == SwingUtil.PANNING_CURSOR)
+ setCursor(SwingUtil.PAN_CURSOR);
+ }
+
+}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/GTUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/GTUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/GTUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,248 +29,428 @@
******************************************************************************/
package schmitzm.geotools;
-import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.log4j.Logger;
+import org.geotools.data.FeatureSource;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.jts.JTS;
+import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.MapContext;
+import org.geotools.map.MapLayer;
import org.geotools.referencing.CRS;
import org.geotools.renderer.GTRenderer;
+import org.geotools.renderer.label.LabelCacheImpl;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.renderer.shape.ShapefileRenderer;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.geometry.Envelope;
+import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.TransformException;
-import com.vividsolutions.jts.geom.Coordinate;
-
/**
* Diese Klasse enthaelt allgemeine Funktionen fuer die Arbeit mit Geotools.
- * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ *
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
+ * (University of Bonn/Germany)
* @version 1.0
*/
public class GTUtil {
- private static Logger LOGGER = Logger.getLogger( GTUtil.class.getName() );
+ private static Logger LOGGER = Logger.getLogger(GTUtil.class.getName());
- /**
- * Specifies the types of renderer used by {@link GTUtil#createGTRenderer()}.
- */
- public static enum GTRendererType {
- /** {@link GTUtil#createGTRenderer()} uses {@link StreamingRenderer}. */
- StreamingRenderer,
- /** {@link GTUtil#createGTRenderer()} uses {@link ShapefileRenderer}. */
- ShapefileRenderer
- }
- /** Holds the renderer type instantiated by
- * {@link GTUtil#createGTRenderer()}. */
- private static GTRendererType rendererType = GTRendererType.ShapefileRenderer;
-
- /** Konstante fuer das CRS "WGS84" (erzeugt als "EPSG:4326")*/
- public static CoordinateReferenceSystem WGS84 = null;
+ /**
+ * Specifies the types of renderer used by {@link GTUtil#createGTRenderer()}
+ * .
+ */
+ public static enum GTRendererType {
+ /** {@link GTUtil#createGTRenderer()} uses {@link StreamingRenderer}. */
+ StreamingRenderer,
+ /** {@link GTUtil#createGTRenderer()} uses {@link ShapefileRenderer}. */
+ ShapefileRenderer
+ }
- private static HashMap<Object, Object> defaultRendererHints;
+ /**
+ * Holds the renderer type instantiated by {@link GTUtil#createGTRenderer()}
+ * .
+ */
+ private static GTRendererType rendererType = GTRendererType.ShapefileRenderer;
- // Initialisierung der CRS-Konstanten
- static {
- try {
- WGS84 = CRS.decode("EPSG:4326",true); // lat/lon (WGS84)
- } catch (Exception err) {
- LOGGER.warn("Exception while creating default WGS84 from code 'EPSG:4326'");
- }
- }
+ /** Konstante fuer das CRS "WGS84" (erzeugt als "EPSG:4326") */
+ public static CoordinateReferenceSystem WGS84 = null;
- /**
- * Erzeugt ein {@link CoordinateReferenceSystem} aus einer String-Definition.
- * Akzeptiert wird ein EPSG-Code "EPSG:..." oder eine WKT-Definition des CRS
- * @param crsDef Definition fuer das CRS.
- * @return {@code null}, falls der String nicht zu einem CRS dekodiert werden
- * kann
- */
- public static CoordinateReferenceSystem createCRS(String crsDef) {
- if ( crsDef == null || crsDef.trim().equals("") )
- return null;
+ private static HashMap<Object, Object> defaultRendererHints;
- CoordinateReferenceSystem crs = null;
- try {
- // Akzeptiert wird: EPSG-Code
- if (crsDef.startsWith("EPSG:"))
- crs = createCRS_EPSG( crsDef );
- else
- crs = CRS.parseWKT( crsDef );
- } catch (Exception err) {
- LOGGER.error("Error while creating CRS",err);
- }
- return crs;
- }
+ // Initialisierung der CRS-Konstanten
+ static {
+ try {
+ WGS84 = CRS.decode("EPSG:4326", true); // lat/lon (WGS84)
+ } catch (Exception err) {
+ LOGGER
+ .warn("Exception while creating default WGS84 from code 'EPSG:4326'");
+ }
+ }
- /**
- * Erzeugt ein {@link CoordinateReferenceSystem} aus einem (EPSG-)Code.
- * Entspricht {@link CRS#decode(String,boolean) CRS#decode(String,true)}.
- * Exceptions werden jedoch abgefangen und stattdessen {@code null} zurueckgegeben.
- * @param code Code fuer das CRS.
- */
- public static CoordinateReferenceSystem createCRS_EPSG(String code) {
- try {
- return CRS.decode(code,true);
- } catch (Exception err) {
- LOGGER.error("Error while creating CRS",err);
- return null;
- }
- }
+ /**
+ * Erzeugt ein {@link CoordinateReferenceSystem} aus einer
+ * String-Definition. Akzeptiert wird ein EPSG-Code "EPSG:..." oder eine
+ * WKT-Definition des CRS
+ *
+ * @param crsDef
+ * Definition fuer das CRS.
+ * @return {@code null}, falls der String nicht zu einem CRS dekodiert
+ * werden kann
+ */
+ public static CoordinateReferenceSystem createCRS(String crsDef) {
+ if (crsDef == null || crsDef.trim().equals(""))
+ return null;
- /**
- * Erzeugt ein UTM-CoordinateReferenceSystem.
- * @param zone UTM-Zone
- */
- public static CoordinateReferenceSystem createCRS_UTM(int zone) {
- DecimalFormat format_99 = new DecimalFormat("00");
- return createCRS( "EPSG:326"+format_99.format(zone) );
- }
+ CoordinateReferenceSystem crs = null;
+ try {
+ // Akzeptiert wird: EPSG-Code
+ if (crsDef.startsWith("EPSG:"))
+ crs = createCRS_EPSG(crsDef);
+ else
+ crs = CRS.parseWKT(crsDef);
+ } catch (Exception err) {
+ LOGGER.error("Error while creating CRS", err);
+ }
+ return crs;
+ }
- /**
- * Erzeugt einen {@link Envelope2D} aus einem {@link Rectangle2D} .
- * @param env Georeferenz und Ausdehnung
- * @param crs CoordinateReferenceSystem
- */
- public static Envelope2D createEnvelope2D(Rectangle2D env, CoordinateReferenceSystem crs) {
- return new Envelope2D(crs, env.getX(), env.getY(), env.getWidth(),
- env.getHeight());
- }
+ /**
+ * Erzeugt ein {@link CoordinateReferenceSystem} aus einem (EPSG-)Code.
+ * Entspricht {@link CRS#decode(String,boolean) CRS#decode(String,true)}.
+ * Exceptions werden jedoch abgefangen und stattdessen {@code null}
+ * zurueckgegeben.
+ *
+ * @param code
+ * Code fuer das CRS.
+ */
+ public static CoordinateReferenceSystem createCRS_EPSG(String code) {
+ try {
+ return CRS.decode(code, true);
+ } catch (Exception err) {
+ LOGGER.error("Error while creating CRS", err);
+ return null;
+ }
+ }
- /**
- * Liefert alle zur Verfuegung stehenden {@linkplain CoordinateReferenceSystem CRS} fuer eine
- * Authority.
- * @param authority Authority fuer die die CRS geliefert werden (z.B. {@code "EPSG"})
- * @param longitudeFirst {@code true} erzwingt die Achsenordnung (longitude, latitude). Siehe
- * {@link CRS#decode(String, boolean)} (Bemerkung: {@code false} bedeutet
- * System-Default, <b>nicht</b> (latitude, longitude)!)
- * @param suppressWarnings wenn {@code true} werden Warnmeldungen unterdrueckt
- * @return eine nach dem CRS-Namen geordnete Map
- */
- public static final SortedMap<String,CoordinateReferenceSystem> getAvailableCRSByName(String authority, boolean longitudeFirst, boolean suppressWarnings) {
- SortedMap<String,CoordinateReferenceSystem> mapByCode = getAvailableCRSByCode(authority, longitudeFirst, suppressWarnings);
- TreeMap<String,CoordinateReferenceSystem> mapByName = new TreeMap<String, CoordinateReferenceSystem>();
- for (String code : mapByCode.keySet()) {
- CoordinateReferenceSystem crs = mapByCode.get(code);
- mapByName.put( crs.getName().toString()+" ["+code+"]", crs );
- }
- return mapByName;
- }
+ /**
+ * Erzeugt ein UTM-CoordinateReferenceSystem.
+ *
+ * @param zone
+ * UTM-Zone
+ */
+ public static CoordinateReferenceSystem createCRS_UTM(int zone) {
+ DecimalFormat format_99 = new DecimalFormat("00");
+ return createCRS("EPSG:326" + format_99.format(zone));
+ }
- /**
- * Liefert alle zur Verfuegung stehenden {@linkplain CoordinateReferenceSystem CRS} fuer eine
- * Authority.
- * @param authority Authority fuer die die CRS geliefert werden (z.B. {@code "EPSG"})
- * @param longitudeFirst {@code true} erzwingt die Achsenordnung (longitude, latitude). Siehe
- * {@link CRS#decode(String, boolean)} (Bemerkung: {@code false} bedeutet
- * System-Default, <b>nicht</b> (latitude, longitude)!)
- * @param suppressWarnings wenn {@code true} werden Warnmeldungen unterdrueckt
- * @return eine nach dem CRS-Code geordnete Map
- */
- public static final SortedMap<String,CoordinateReferenceSystem> getAvailableCRSByCode(String authority, boolean longitudeFirst, boolean suppressWarnings) {
- TreeMap<String,CoordinateReferenceSystem> map = new TreeMap<String, CoordinateReferenceSystem>();
- for (String code : (Set<String>)CRS.getSupportedCodes(authority)) {
- if ( !code.startsWith(authority) )
- code = authority + ":" + code;
- try {
- CoordinateReferenceSystem crs = CRS.decode(code, longitudeFirst);
- map.put(code, crs);
- } catch (Exception err) {
- if ( !suppressWarnings )
- LOGGER.warn("CRS could not be decoded: "+code);
- }
- }
- return map;
- }
-
+ /**
+ * Erzeugt einen {@link Envelope2D} aus einem {@link Rectangle2D} .
+ *
+ * @param env
+ * Georeferenz und Ausdehnung
+ * @param crs
+ * CoordinateReferenceSystem
+ */
+ public static Envelope2D createEnvelope2D(Rectangle2D env,
+ CoordinateReferenceSystem crs) {
+ return new Envelope2D(crs, env.getX(), env.getY(), env.getWidth(), env
+ .getHeight());
+ }
+ /**
+ * Liefert alle zur Verfuegung stehenden
+ * {@linkplain CoordinateReferenceSystem CRS} fuer eine Authority.
+ *
+ * @param authority
+ * Authority fuer die die CRS geliefert werden (z.B. {@code
+ * "EPSG"})
+ * @param longitudeFirst
+ * {@code true} erzwingt die Achsenordnung (longitude, latitude).
+ * Siehe {@link CRS#decode(String, boolean)} (Bemerkung: {@code
+ * false} bedeutet System-Default, <b>nicht</b> (latitude,
+ * longitude)!)
+ * @param suppressWarnings
+ * wenn {@code true} werden Warnmeldungen unterdrueckt
+ * @return eine nach dem CRS-Namen geordnete Map
+ */
+ public static final SortedMap<String, CoordinateReferenceSystem> getAvailableCRSByName(
+ String authority, boolean longitudeFirst, boolean suppressWarnings) {
+ SortedMap<String, CoordinateReferenceSystem> mapByCode = getAvailableCRSByCode(
+ authority, longitudeFirst, suppressWarnings);
+ TreeMap<String, CoordinateReferenceSystem> mapByName = new TreeMap<String, CoordinateReferenceSystem>();
+ for (String code : mapByCode.keySet()) {
+ CoordinateReferenceSystem crs = mapByCode.get(code);
+ mapByName.put(crs.getName().toString() + " [" + code + "]", crs);
+ }
+ return mapByName;
+ }
- /**
- * Berechnet den Schnitt zweier {@link Envelope Envelopes}.
- * @param env1 erster Envelope
- * @param env2 zweiter Envelope
- * @param crs {@link CoordinateReferenceSystem} fuer den Schnitt-Envelope
- */
- public static Envelope intersectEnvelope(Envelope env1, Envelope env2, CoordinateReferenceSystem crs) {
- // Envelopes in JTS umwandeln
- com.vividsolutions.jts.geom.Envelope env1JTS = new com.vividsolutions.jts.geom.Envelope(
- env1.getMinimum(0),env1.getMaximum(0),env1.getMinimum(1),env1.getMaximum(1));
- com.vividsolutions.jts.geom.Envelope env2JTS = new com.vividsolutions.jts.geom.Envelope(
- env2.getMinimum(0),env2.getMaximum(0),env2.getMinimum(1),env2.getMaximum(1));
- com.vividsolutions.jts.geom.Envelope intersetionEnvJTS = env1JTS.intersection(env2JTS);
- // Subset nur bzgl. des Bereichs in dem auch das Raster liegt
- return JTS.getEnvelope2D(intersetionEnvJTS,crs);
- }
+ /**
+ * Liefert alle zur Verfuegung stehenden
+ * {@linkplain CoordinateReferenceSystem CRS} fuer eine Authority.
+ *
+ * @param authority
+ * Authority fuer die die CRS geliefert werden (z.B. {@code
+ * "EPSG"})
+ * @param longitudeFirst
+ * {@code true} erzwingt die Achsenordnung (longitude, latitude).
+ * Siehe {@link CRS#decode(String, boolean)} (Bemerkung: {@code
+ * false} bedeutet System-Default, <b>nicht</b> (latitude,
+ * longitude)!)
+ * @param suppressWarnings
+ * wenn {@code true} werden Warnmeldungen unterdrueckt
+ * @return eine nach dem CRS-Code geordnete Map
+ */
+ public static final SortedMap<String, CoordinateReferenceSystem> getAvailableCRSByCode(
+ String authority, boolean longitudeFirst, boolean suppressWarnings) {
+ TreeMap<String, CoordinateReferenceSystem> map = new TreeMap<String, CoordinateReferenceSystem>();
+ for (String code : (Set<String>) CRS.getSupportedCodes(authority)) {
+ if (!code.startsWith(authority))
+ code = authority + ":" + code;
+ try {
+ CoordinateReferenceSystem crs = CRS
+ .decode(code, longitudeFirst);
+ map.put(code, crs);
+ } catch (Exception err) {
+ if (!suppressWarnings)
+ LOGGER.warn("CRS could not be decoded: " + code);
+ }
+ }
+ return map;
+ }
- /**
- * Creates a {@link GTRenderer}. This method can be used all over
- * a project, so the renderer can be switched easily.
- * @param mapContext a {@link MapContext} (can be {@code null})
- */
- public static GTRenderer createGTRenderer(MapContext mapContext) {
- GTRenderer renderer = createGTRenderer();
- if ( mapContext != null )
- renderer.setContext(mapContext);
- return renderer;
- }
+ /**
+ * Berechnet den Schnitt zweier {@link Envelope Envelopes}.
+ *
+ * @param env1
+ * erster Envelope
+ * @param env2
+ * zweiter Envelope
+ * @param crs
+ * {@link CoordinateReferenceSystem} fuer den Schnitt-Envelope
+ */
+ public static Envelope intersectEnvelope(Envelope env1, Envelope env2,
+ CoordinateReferenceSystem crs) {
+ // Envelopes in JTS umwandeln
+ com.vividsolutions.jts.geom.Envelope env1JTS = new com.vividsolutions.jts.geom.Envelope(
+ env1.getMinimum(0), env1.getMaximum(0), env1.getMinimum(1),
+ env1.getMaximum(1));
+ com.vividsolutions.jts.geom.Envelope env2JTS = new com.vividsolutions.jts.geom.Envelope(
+ env2.getMinimum(0), env2.getMaximum(0), env2.getMinimum(1),
+ env2.getMaximum(1));
+ com.vividsolutions.jts.geom.Envelope intersetionEnvJTS = env1JTS
+ .intersection(env2JTS);
+ // Subset nur bzgl. des Bereichs in dem auch das Raster liegt
+ return JTS.getEnvelope2D(intersetionEnvJTS, crs);
+ }
- /**
- * Creates a {@link GTRenderer}. This method can be used all over
- * a project, so the renderer can be switched easily.
- */
- public static GTRenderer createGTRenderer() {
- switch ( rendererType ) {
- case ShapefileRenderer: return new ShapefileRenderer();
- case StreamingRenderer: return new StreamingRenderer();
- }
- throw new UnsupportedOperationException("Renderer type not supported: "+rendererType);
- }
-
- /**
- * Sets the renderer used by {@link #createGTRenderer()}.
- * @param rType renderer type
- * @see GTRendererType
- */
- public static void setGTRendererType(GTRendererType rType) {
- rendererType = rType;
- }
-
- /**
- * Returns the renderer used by {@link #createGTRenderer()}.
- * @see GTRendererType
- */
- public static GTRendererType getGTRendererType() {
- return rendererType;
- }
-
/**
+ * Creates a {@link GTRenderer}. This method can be used all over a project,
+ * so the renderer can be switched easily.
+ *
+ * @param mapContext
+ * a {@link MapContext} (can be {@code null})
+ */
+ public static GTRenderer createGTRenderer(MapContext mapContext) {
+ GTRenderer renderer = createGTRenderer();
+ if (mapContext != null)
+ renderer.setContext(mapContext);
+ return renderer;
+ }
+
+ /**
+ * Creates a {@link GTRenderer}. This method can be used all over a project,
+ * so the renderer can be switched easily.
+ *
+ * @param mapContext
+ * a {@link MapContext} (can be {@code null})
+ * @param additionalRenderingHints
+ * A list of hints that will overload the default hints. May be
+ * <code>null</code>
+ */
+ public static GTRenderer createGTRenderer(MapContext mapContext,
+ Map<Object, Object> additionalRenderingHints) {
+ GTRenderer renderer = createGTRenderer();
+ if (mapContext != null)
+ renderer.setContext(mapContext);
+
+ if (additionalRenderingHints != null)
+ renderer.getRendererHints().putAll(additionalRenderingHints);
+
+ return renderer;
+ }
+
+ /**
+ * Creates a {@link GTRenderer}. This method can be used all over a project,
+ * so the renderer can be switched easily. The {@link GTRenderer} is
+ * initialized with the default renering hints for the kind of renderer.<br/>
+ *
+ * @see #getDefaultGTRendererHints(GTRenderer)
+ */
+ public static GTRenderer createGTRenderer() {
+ switch (rendererType) {
+ case ShapefileRenderer:
+ final ShapefileRenderer shapefileRenderer = new ShapefileRenderer();
+ shapefileRenderer
+ .setRendererHints(getDefaultGTRendererHints(shapefileRenderer));
+ return shapefileRenderer;
+ case StreamingRenderer:
+ final StreamingRenderer streamingRenderer = new StreamingRenderer();
+ streamingRenderer
+ .setRendererHints(getDefaultGTRendererHints(streamingRenderer));
+ return streamingRenderer;
+ }
+ throw new UnsupportedOperationException("Renderer type not supported: "
+ + rendererType);
+ }
+
+ /**
+ * Sets the renderer used by {@link #createGTRenderer()}.
+ *
+ * @param rType
+ * renderer type
+ * @see GTRendererType
+ */
+ public static void setGTRendererType(GTRendererType rType) {
+ rendererType = rType;
+ }
+
+ /**
+ * Returns the renderer used by {@link #createGTRenderer()}.
+ *
+ * @see GTRendererType
+ */
+ public static GTRendererType getGTRendererType() {
+ return rendererType;
+ }
+
+ /**
+ * Returns the default RendererHints for a given {@link GTRenderer}. By
+ * 2009/11/01 the {@link StreamingRenderer} needs
+ * {@link StreamingRenderer.MEMORY_PRE_LOADING_KEY} false, whereas
+ * {@link ShapefileRenderer} need its set to true.
+ *
+ * @param renderer
+ * is <code>null</code>, the default {@link GTRendererType} is
+ * used.
+ */
+ public static HashMap<Object, Object> getDefaultGTRendererHints(
+ GTRenderer renderer) {
+ // if (defaultRendererHints == null){
+ defaultRendererHints = new HashMap<Object, Object>();
+
+ /**
+ * This hint avoids "Bursa Wolf Parameters missing" exceptions while
+ * zooming which slow down the rendering process. The exceptions
+ * appeared for example in maps that consisted only of layers of DHDN2
+ * CRS.
+ */
+ defaultRendererHints.put(
+ StreamingRenderer.SCALE_COMPUTATION_METHOD_KEY,
+ StreamingRenderer.SCALE_OGC);
+
+ defaultRendererHints.put(StreamingRenderer.OPTIMIZE_FTS_RENDERING_KEY,
+ Boolean.TRUE);
+
+ if (renderer instanceof ShapefileRenderer) {
+ defaultRendererHints.put(StreamingRenderer.MEMORY_PRE_LOADING_KEY,
+ Boolean.TRUE);
+ } else {
+ defaultRendererHints.put(StreamingRenderer.MEMORY_PRE_LOADING_KEY,
+ Boolean.FALSE);
+ }
+
+ defaultRendererHints.put(StreamingRenderer.OPTIMIZED_DATA_LOADING_KEY,
+ Boolean.TRUE);
+
+ defaultRendererHints.put(StreamingRenderer.LABEL_CACHE_KEY,
+ new LabelCacheImpl());
+
+ // public static final String DPI_KEY = "dpi";
+ // public static final String DECLARED_SCALE_DENOM_KEY =
+ // "declaredScaleDenominator";
+ // public static final String OPTIMIZED_DATA_LOADING_KEY =
+ // "optimizedDataLoadingEnabled";
+ // public static final String SCALE_COMPUTATION_METHOD_KEY =
+ // "scaleComputationMethod";
+
+ // }
+ return (HashMap<Object, Object>) defaultRendererHints.clone();
+ }
+
+ /**
+ * Very similar to {@link MapContext#getLayerBounds()}, this may return
+ * <code>null</code>. Different to {@link MapContext#getLayerBounds()}, this
+ * instance only looks at visible layers.
+ *
+ * @param localContext
* @return
*/
- public static HashMap<Object, Object> getDefaultGTRendererHints() {
- if (defaultRendererHints == null){
- defaultRendererHints = new HashMap<Object, Object>();
-
- /**
- * This hint avoids "Bursa Wolf Parameters missing" exceptions while
- * zooming which slow down the rendering process. The exceptions
- * appeared for example in maps that consisted only of layers of DHDN2
- * CRS.
+ public static ReferencedEnvelope getVisibleLayoutBounds(MapContext context) {
+ ReferencedEnvelope result = null;
+ CoordinateReferenceSystem crs = context.getAreaOfInterest()
+ .getCoordinateReferenceSystem();
+
+ final int length = context.getLayerCount();
+ MapLayer layer;
+ FeatureSource<SimpleFeatureType, SimpleFeature> fs;
+ ReferencedEnvelope env;
+ CoordinateReferenceSystem sourceCrs;
+
+ for (int i = 0; i < length; i++) {
+ layer = context.getLayer(i);
+
+ if (!layer.isVisible())
+ continue;
+ /*
+ * fs = layer.getFeatureSource(); sourceCrs =
+ * fs.getSchema().getDefaultGeometry() .getCoordinateSystem(); env =
+ * new ReferencedEnvelope(fs.getBounds(), sourceCrs);
*/
- defaultRendererHints.put(
- StreamingRenderer.SCALE_COMPUTATION_METHOD_KEY,
- StreamingRenderer.SCALE_OGC);
-
-
-
+
+ env = layer.getBounds();
+ if (env == null) {
+ continue;
+ } else {
+ try {
+ sourceCrs = env.getCoordinateReferenceSystem();
+ if ((sourceCrs != null) && crs != null
+ && !CRS.equalsIgnoreMetadata(sourceCrs, crs)) {
+ env = env.transform(crs, true);
+ }
+
+ } catch (FactoryException e) {
+ LOGGER
+ .warn(
+ "Data source and map context coordinate system differ, yet it was not possible to get a projected bounds estimate...",
+ e);
+ } catch (TransformException e) {
+ LOGGER
+ .warn(
+ "Data source and map context coordinate system differ, yet it was not possible to get a projected bounds estimate...",
+ e);
+ }
+
+ if (result == null) {
+ result = env;
+ } else {
+ result.expandToInclude(env);
+ }
+ }
}
- return (HashMap<Object, Object>) defaultRendererHints.clone();
+
+ return result;
}
-
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/JTSUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/JTSUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/JTSUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -67,20 +67,22 @@
);
}
- /**
- * Expands an {@link Envelope} by percentage.
- * @param env the {@link Envelope}
- * @param pct percentage (e.g. 0.1 = 10%) to expands the envelope by
- */
- public static Envelope expandEnvelope(Envelope env, double pct) {
- final Envelope expandedEnv = new Envelope(env);
- expandedEnv.expandBy(
- env.getWidth() * pct,
- env.getHeight() * pct
- );
- return expandedEnv;
- }
+ /**
+ * Expands an {@link Envelope} by percentage.
+ *
+ * @param env
+ * the {@link Envelope}
+ * @param pct
+ * percentage (e.g. 0.1 = 10%) to expands the envelope by.
+ * Negative values are allowed.
+ */
+ public static Envelope expandEnvelope(Envelope env, double pct) {
+ final Envelope expandedEnv = new Envelope(env);
+ expandedEnv.expandBy(env.getWidth() * pct, env.getHeight() * pct);
+ return expandedEnv;
+ }
+
/**
* Transformiert einen JTS-Envelope von einem CRS in ein anderes. Wenn Bursa-Wolf parameter fehlen, wird lenient gerechnet.
* @param sourceEnv JTS-Envelope
@@ -129,7 +131,7 @@
/**
* Returns an {@link Envelope} that has the same aspect ratio as the given rectangle
- * @param r
+ * @param rect
* defines the aspect ratio the map area is fixed with (e.g. a
* gui components size)
* @param mapArea
@@ -138,7 +140,7 @@
* If <code>true</code>, than the area will be enlarged to match
* the aspect ratio. If <code>false</code>, it will only shrink.
*/
- public static Envelope fixAspectRatio(final Rectangle r, final Envelope mapArea,
+ public static Envelope fixAspectRatio(final Rectangle rect, final Envelope mapArea,
boolean grow) {
// no map area to fix the aspect ratio for
if (mapArea == null) {
@@ -146,19 +148,19 @@
return null;
}
// no component size to fix the aspect ratio with
- if ( r == null || r.width == 0 || r.height == 0 ) {
+ if ( rect == null || rect.width == 0 || rect.height == 0 ) {
LOGGER.warn("Empty rectangle in method fixAspectRatio, returning an unmodified mapArea!");
return mapArea;
}
final double mapWidth = mapArea.getWidth(); /* get the extent of the map */
final double mapHeight = mapArea.getHeight();
- final double scaleX = r.getWidth() / mapArea.getWidth(); /*
+ final double scaleX = rect.getWidth() / mapArea.getWidth(); /*
* calculate the
* new scale
*/
- final double scaleY = r.getHeight() / mapArea.getHeight();
+ final double scaleY = rect.getHeight() / mapArea.getHeight();
double scale = 1.0; // stupid compiler!
if ((grow && scaleX < scaleY) || (!grow && scaleX > scaleY)) {
@@ -168,8 +170,8 @@
}
/* calculate the difference in width and height of the new extent */
- final double deltaX = /* Math.abs */((r.getWidth() / scale) - mapWidth);
- final double deltaY = /* Math.abs */((r.getHeight() / scale) - mapHeight);
+ final double deltaX = /* Math.abs */((rect.getWidth() / scale) - mapWidth);
+ final double deltaY = /* Math.abs */((rect.getHeight() / scale) - mapHeight);
/*
* System.out.println("delta x " + deltaX);
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/feature/FeatureUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/feature/FeatureUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/feature/FeatureUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -2024,6 +2024,11 @@
return g.getCentroid();
}
+ public static Object getLayerSourceObject(MapLayer mapLayer) {
+ return getWrappedGeoObject((FeatureSource<SimpleFeatureType, SimpleFeature>) mapLayer
+ .getFeatureSource());
+ }
+
// /**
// * Extrahiert alle Geometrien aus einer FeatureCollection. Fuer jedes
// * Geometry-Attribut der FeatureCollection wird eine GeometrieCollection
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureLayerFilterDialog.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureLayerFilterDialog.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureLayerFilterDialog.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -123,7 +123,7 @@
private String frameTitle = GeotoolsGUIUtil.RESOURCE
.getString(DIALOG_TITLE);
- private JMapPane mapPane = null;
+ private SelectableXMapPane mapPane = null;
private MapLayer layer = null;
/**
@@ -146,7 +146,7 @@
* @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
* Krüger</a>
*/
- public FeatureLayerFilterDialog(Window parent, JMapPane mapPane,
+ public FeatureLayerFilterDialog(Window parent, SelectableXMapPane mapPane,
MapLayer mapLayer) {
this(parent, mapPane, mapLayer, true);
}
@@ -175,7 +175,7 @@
* @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
* Krüger</a>
*/
- protected FeatureLayerFilterDialog(Window parent, JMapPane mapPane,
+ protected FeatureLayerFilterDialog(Window parent, SelectableXMapPane mapPane,
MapLayer mapLayer, boolean initGUI) {
super(parent);
setModal(true);
@@ -306,7 +306,7 @@
* Liefert das MapPane, fuer das {@link FeatureSelectedEvent
* FeatureSelectedEvents} ausgeloest werden.
*/
- public JMapPane getMapPane() {
+ public SelectableXMapPane getMapPane() {
return mapPane;
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureTablePane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureTablePane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/FeatureTablePane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,11 +29,11 @@
******************************************************************************/
package schmitzm.geotools.gui;
+import gtmig.org.geotools.swing.XMapPane;
+
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
-import java.util.HashMap;
-import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JScrollPane;
@@ -48,7 +48,6 @@
import org.apache.log4j.Logger;
import org.geotools.feature.FeatureCollection;
import org.geotools.map.DefaultMapLayer;
-import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.Style;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
@@ -84,7 +83,7 @@
/** Tabellen-Modell der SimpleFeature-Tabelle. */
protected FeatureCollectionTableModel featuresTableModel = null;
/** Preview-Bereich fuer die in der Tabelle selektierten Features. */
- protected JMapPane mapPane = null;
+ protected XMapPane mapPane = null;
/** Style, in dem die Features in der Karte dargestellt werden */
protected Style featureStyle = null;
@@ -223,19 +222,8 @@
setLayout(new BorderLayout());
// MapPane fuer Preview der in der Tabelle selektieren Features
if (geomPreview) {
- this.mapPane = new JMapPane();
+ this.mapPane = new XMapPane();
- /**
- * Add the rendering hint to use the not-so-accurate scale calculations. We
- * don't want annoying Bursa-Wolf-Pameter-missing exception coming
- * from the preview JMapPane
- */
- Map<Object, Object> hints = this.mapPane.getRenderer()
- .getRendererHints();
- if (hints == null)
- hints = new HashMap<Object, Object>();
- hints.put(StreamingRenderer.SCALE_COMPUTATION_METHOD_KEY, StreamingRenderer.SCALE_OGC);
-
// {
// // Bei Links-Klick auf das gesamte Layer zoomen
// public void mouseClicked(MouseEvent e) {
@@ -254,8 +242,7 @@
// };
mapPane.setToolTipText(GeotoolsGUIUtil.R(PREVIEW_MAPPANE_TOOLTIP));
- mapPane.setState(JMapPane.RESET);
- mapPane.setWindowSelectionState(JMapPane.NONE);
+ mapPane.setState(SelectableXMapPane.NONE);
mapPane.setMinimumSize(new Dimension(100, 100));
SwingUtil.setPreferredWidth(mapPane, 200);
mapPane.setBorder(BorderFactory.createLoweredBevelBorder());
@@ -442,6 +429,6 @@
}
// Vorschaukarte aktualisieren
- mapPane.refresh();
+ mapPane.repaint();
}
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoMapPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoMapPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoMapPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -36,15 +36,13 @@
import java.awt.Insets;
import java.util.HashMap;
-import javax.swing.BorderFactory;
-
import org.geotools.map.MapContext;
import org.geotools.renderer.GTRenderer;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.renderer.shape.ShapefileRenderer;
import schmitzm.geotools.GTUtil;
-import schmitzm.geotools.map.event.JMapPaneEvent;
+import schmitzm.geotools.map.event.MapPaneEvent;
import schmitzm.geotools.map.event.JMapPaneListener;
import schmitzm.geotools.map.event.MapAreaChangedEvent;
import schmitzm.geotools.map.event.ScaleChangedEvent;
@@ -52,7 +50,7 @@
import schmitzm.swing.SwingUtil;
/**
- * Das {@code GeoMapPane} erweitert das {@link JMapPane} um einen
+ * Das {@code GeoMapPane} erweitert das {@link SelectableXMapPane} um einen
* Massstab-Balken, sowie ein horizontales und vertikales Koordinaten-Raster
* (Grid), in dem die Geo-Referenz des angezeigten Karten-Bereichs angezeigt wird.
*
@@ -97,7 +95,7 @@
protected HashMap<String, GridBagConstraints> layoutConstraints = new HashMap<String, GridBagConstraints>();
/** Karten-Bereich des {@code GeoMapPane}. */
- protected JMapPane mapPane = null;
+ protected SelectableXMapPane mapPane = null;
/** Massstab-Balken */
private ScalePane scalePane = null;
/**
@@ -117,14 +115,11 @@
*/
private boolean disposed = false;
-
- private static HashMap<Object, Object> defaultRendererHints;
-
/**
* Erzeugt ein neues {@code GeoMapPane}.
*/
public GeoMapPane() {
- this(null, null, null, null, null);
+ this(null, null, null, null);
}
/**
@@ -147,9 +142,11 @@
* which is cool for creating PDF, SVG.. And the much faster
* {@link ShapefileRenderer}. Defaults to {@link GTUtil#createGTRenderer(MapContext)}
*/
- public GeoMapPane(JMapPane mapPane, GridPanel vGrid, GridPanel hGrid,
- ScalePane scalePane, GTRenderer renderer) {
+ public GeoMapPane(SelectableXMapPane mapPane, GridPanel vGrid, GridPanel hGrid,
+ ScalePane scalePane) {
this.scalePane = scalePane;
+
+ setOpaque(true);
if (vGrid != null && !vGrid.isVertical())
throw new IllegalArgumentException(
@@ -159,7 +156,7 @@
"GridPanel for horizontal grid must be of type GridPanel.HORIZONTAL!!");
// Karte
- this.mapPane = (mapPane != null) ? mapPane : new JMapPane(null,null,renderer, null, GTUtil.getDefaultGTRendererHints());
+ this.mapPane = (mapPane != null) ? mapPane : new SelectableXMapPane();
// Koordinaten-Leisten
this.setVertGrid((vGrid != null) ? vGrid : new GridPanel(
GridPanel.VERTICAL, this.mapPane));
@@ -196,12 +193,12 @@
this.setLayout(new GridBagLayout());
// Karten-Darestellung initialisieren
- this.mapPane.setBorder(BorderFactory.createLoweredBevelBorder());
+// this.mapPane.setBorder(BorderFactory.createLoweredBevelBorder());
SwingUtil.setPreferredWidth(this.mapPane, 200);
// MapListener that listens to Scale and MapArea changes
this.mapPane.addMapPaneListener(new JMapPaneListener() {
- public void performMapPaneEvent(JMapPaneEvent e) {
+ public void performMapPaneEvent(MapPaneEvent e) {
if (e instanceof ScaleChangedEvent) {
ScaleChangedEvent sce = (ScaleChangedEvent) e;
getScalePane().setScale(sce.getNewScale());
@@ -231,7 +228,7 @@
/**
* Aktualisiert die Karten-Darstellung.
*
- * @see JMapPane#refresh()
+ * @see SelectableXMapPane#refresh()
*/
public void refreshMap() {
mapPane.refresh();
@@ -251,9 +248,9 @@
}
/**
- * Liefert das {@link JMapPane}, in dem die Karten dargestellt werden.
+ * Liefert das {@link SelectableXMapPane}, in dem die Karten dargestellt werden.
*/
- public final JMapPane getMapPane() {
+ public final SelectableXMapPane getMapPane() {
return mapPane;
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoPositionLabel.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoPositionLabel.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GeoPositionLabel.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -45,15 +45,15 @@
* angezeigt werden. Dabei werden die Koordinaten auf eine bestimmte Anzahl
* an Nachkommastellen gerundet.<br>
* Die Klasse fungiert als {@link MouseListener} und {@link MouseMotionListener} und
- * kann so direkt an ein {@link JMapPane} gekoppelt werden. Die Koordinaten-Darstellung
+ * kann so direkt an ein {@link SelectableXMapPane} gekoppelt werden. Die Koordinaten-Darstellung
* im Label aktualisiert sich somit automatisch, sobald sich die Maus ueber die
* Karte bewegt. Wird ein Kartenbereich selektiert (gedrueckte linke Maustaste),
* werden neben der aktuellen Position auch die Koordinaten des Selektionsstart
* angezeigt.<br>
* <b>Bemerke:</b><br>
- * Eine Instanz des <code>GeoPositionLabel</code> muss dem {@link JMapPane} sowohl
- * als {@linkplain JMapPane#addMouseListener(MouseListener) MouseListener}, als
- * auch als {@linkplain JMapPane#addMouseMotionListener(MouseMotionListener) MouseMotionListener}
+ * Eine Instanz des <code>GeoPositionLabel</code> muss dem {@link SelectableXMapPane} sowohl
+ * als {@linkplain SelectableXMapPane#addMouseListener(MouseListener) MouseListener}, als
+ * auch als {@linkplain SelectableXMapPane#addMouseMotionListener(MouseMotionListener) MouseMotionListener}
* hinzugefuegt werden. Ansonsten bekommt es nicht alle notwendigen Informationen
* mit!
* @see #setFractionDigits(int)
@@ -99,18 +99,18 @@
/**
* Stellt die Koordinaten im Label dar, wenn es sich bei dem Event um
- * ein {@link GeoMouseEvent} handelt oder das Event von einem {@link JMapPane}
+ * ein {@link GeoMouseEvent} handelt oder das Event von einem {@link SelectableXMapPane}
* ausgeloest wurde.<br>
* Wird von {@link #mousePressed(MouseEvent)}, {@link #mouseMoved(MouseEvent)}
* und {@link #mouseDragged(MouseEvent)} aufgerufen.
* @see #createGeoPositionString(Point2D,Point2D)
*/
protected void displayCoordinates(final MouseEvent e) {
- if ( e==null || !(e instanceof MapMouseEvent) && !(e.getSource() instanceof JMapPane) )
+ if ( e==null || !(e instanceof MapMouseEvent) && !(e.getSource() instanceof SelectableXMapPane) )
return;
// aktuelle Geo-Position ermitteln und runden
- final Point2D actCoord = JMapPane.getMapCoordinatesFromEvent(e);
+ final Point2D actCoord = SelectableXMapPane.getMapCoordinatesFromEvent(e);
if ( actCoord == null )
return;
final double actLat = Math.round(actCoord.getX() * fracFactor) / fracFactor;
@@ -172,11 +172,11 @@
/**
* Wird aufgerufen, wenn der Maus-Button gedrueckt wird.
* Handelt es sich bei dem Event um ein {@link GeoMouseEvent} oder das Event
- * von einem {@link JMapPane} ausgeloest wurde, werden die
+ * von einem {@link SelectableXMapPane} ausgeloest wurde, werden die
* aktuellen Koordinaten in {@link #selStartCoord} gespeichert.
*/
public void mousePressed(final MouseEvent e) {
- final Point2D p = JMapPane.getMapCoordinatesFromEvent(e);
+ final Point2D p = SelectableXMapPane.getMapCoordinatesFromEvent(e);
if ( p != null && e.getButton() == MouseEvent.BUTTON1) {
selStartCoord = p;
//MS: on simple click the Envelope-Coordinates should not
@@ -202,7 +202,7 @@
/**
* Wird aufgerufen, sobald die Maus bewegt wird.
* Stellt die Koordinaten im Label dar, wenn es sich bei dem Event um ein
- * {@link GeoMouseEvent} handelt oder das Event von einem {@link JMapPane}
+ * {@link GeoMouseEvent} handelt oder das Event von einem {@link SelectableXMapPane}
* ausgeloest wurde.
*/
public void mouseMoved(final MouseEvent e) {
@@ -212,7 +212,7 @@
/**
* Wird aufgerufen, sobald die Maus bei gedrueckter Taste bewegt wird.
* Stellt die Koordinaten im Label dar, wenn es sich bei dem Event um ein
- * {@link GeoMouseEvent} handelt oder das Event von einem {@link JMapPane}
+ * {@link GeoMouseEvent} handelt oder das Event von einem {@link SelectableXMapPane}
* ausgeloest wurde.
*/
public void mouseDragged(final MouseEvent e) {
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GridPanel.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GridPanel.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/GridPanel.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -48,7 +48,7 @@
/**
* Diese Klasse stellt eine horizontale oder vertikale Koordinaten-Leiste (Grid)
- * dar, die an ein {@link JMapPane} gekoppelt ist.
+ * dar, die an ein {@link SelectableXMapPane} gekoppelt ist.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
@@ -71,7 +71,7 @@
private int orientation = 0;
/** Karte, an der die Koordinaten-Leiste ausgerichtet wird. */
- protected JMapPane mapPane = null;
+ protected SelectableXMapPane mapPane = null;
/** Transformation von Karten-CRS zu CRS des Koordinaten-Rasters */
protected MathTransform mapToGrid = null;
@@ -87,24 +87,24 @@
protected boolean forceXYIndexSwitch = false;
/**
- * Erzeugt eine WGS84-Koordinaten-Leiste fuer ein {@link JMapPane}.
+ * Erzeugt eine WGS84-Koordinaten-Leiste fuer ein {@link SelectableXMapPane}.
* @param orientation Orientierung ({@link #HORIZONTAL} oder {@link #VERTICAL})
* @param mapPane Karte an der die Koordinaten-Leiste ausgerichtet wird
* @see GridPanelFormatter_LatLon1
*/
- public GridPanel(int orientation, JMapPane mapPane) {
+ public GridPanel(int orientation, SelectableXMapPane mapPane) {
this(orientation,mapPane,null);
}
/**
- * Erzeugt eine Koordinaten-Leiste fuer ein {@link JMapPane}.
+ * Erzeugt eine Koordinaten-Leiste fuer ein {@link SelectableXMapPane}.
* @param orientation Orientierung ({@link #HORIZONTAL} oder {@link #VERTICAL})
* @param mapPane Karte an der die Koordinaten-Leiste ausgerichtet wird
* @param formatter definiert das CRS und Koordinaten-Format fuer die Koordinaten
* Leiste (wenn {@code null} wird ein {@link GridPanelFormatter_LatLon1}
* verwendet)
*/
- public GridPanel(int orientation, JMapPane mapPane, GridPanelFormatter formatter) {
+ public GridPanel(int orientation, SelectableXMapPane mapPane, GridPanelFormatter formatter) {
this.orientation = orientation;
this.mapPane = mapPane;
setGridFormatter(formatter);
@@ -210,7 +210,7 @@
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- if ( getParent() == null || mapPane.getMapArea() == null )
+ if ( getParent() == null || !mapPane.isWellDefined())
return;
CoordinateReferenceSystem mapCRS = null; // (aktuelles) CRS des MapPane
@@ -322,7 +322,7 @@
double firstGrid = Math.ceil(mapMin/gridDist)*gridDist; // 1. Abschnitt in Lat bzw. Lon
double[] grid_GCRS = mapMin_GCRS.clone(); // Ausgangspunkt
double[] grid_MCRS = new double[2];
- AffineTransform mapToWin = mapPane.getTransform();
+ AffineTransform mapToWin = mapPane.getScreenToWorld();
for (double gridPos=firstGrid; gridPos<=mapMax; gridPos+=gridDist) {
grid_GCRS[idx] = gridPos;
// In Map-CRS und dann in Fenster-Koordinaten transformieren
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,11 +29,9 @@
******************************************************************************/
package schmitzm.geotools.gui;
-import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
@@ -78,12 +76,12 @@
/**
- * The {@code GeoEditorPane} extends the {@link JMapPane} with functionalities
+ * The {@code GeoEditorPane} extends the {@link SelectableXMapPane} with functionalities
* to create new vector layers by successively click points via mouse.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
-public class JEditorPane extends JMapPane {
+public class JEditorPane extends SelectableXMapPane {
/** Modes, the editor can be perform.
* @see JEditorPane#startEditing(EditorMode, String, Style) */
public static enum EditorMode {
@@ -181,11 +179,6 @@
* Creates a new {@code GeoEditorPane}.
*/
public JEditorPane() {
- this( new BorderLayout(),
- true,
- GTUtil.createGTRenderer(),
- new DefaultMapContext(DefaultGeographicCRS.WGS84)
- );
}
/**
@@ -194,8 +187,8 @@
* <b>The specified parameter all can be {@code null}! In this case
* the respective default component is used.</b>
*/
- public JEditorPane(LayoutManager layout, boolean isDoubleBuffered, GTRenderer renderer, MapContext context) {
- super(layout,isDoubleBuffered,renderer,context);
+ public JEditorPane(MapContext context) {
+ super(context);
this.mapContext = getContext();
// initalize the editor styles
this.editorStyles = new HashMap<GeometryForm, Style>();
@@ -204,7 +197,7 @@
// no standard action on left mouse button, instead: adding points
setState( NONE );
- setWindowSelectionState( ZOOM_IN );
+ setState( ZOOM_IN );
// special map context for the editor layers, so the
// editor layers are not shown in "normal" layer list
this.editorMapContext = new DefaultMapContext( mapContext.getCoordinateReferenceSystem() );
@@ -217,7 +210,7 @@
attrInputOption = new FeatureInputOption(null,true,(SimpleFeature)null);
}
- /**
+/**
* After the actions of the super method, this method paints the
* special editor layers in {@link #editorMapContext}.
*/
@@ -236,7 +229,7 @@
* editor mode.
*/
public void mouseClicked(MouseEvent e) {
- Point2D geoCoord = getTransform().transform(e.getPoint(), null);
+ Point2D geoCoord = getScreenToWorld().transform(e.getPoint(), null);
// Zunaechst Modus auf NULL pruefen, da ansonsten
// NullPointerException in switch-Statement
if ( editorMode == null )
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorToolBar.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorToolBar.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JEditorToolBar.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -45,7 +45,7 @@
import schmitzm.geotools.gui.JEditorPane.EditorMode;
import schmitzm.geotools.map.event.JEditorPaneEvent;
-import schmitzm.geotools.map.event.JMapPaneEvent;
+import schmitzm.geotools.map.event.MapPaneEvent;
import schmitzm.geotools.map.event.JMapPaneListener;
import schmitzm.geotools.map.event.LayerEditCanceledEvent;
import schmitzm.geotools.map.event.LayerEditFinishedEvent;
@@ -101,7 +101,7 @@
this.actionButtons = new TreeMap<Integer,JButton>();
// Create a Listener to sniff the zooms on the JMapPane
this.mapPaneListener = new JMapPaneListener() {
- public void performMapPaneEvent(JMapPaneEvent e) {
+ public void performMapPaneEvent(MapPaneEvent e) {
if ( !(e instanceof JEditorPaneEvent) )
return;
Deleted: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -1,2940 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Martin O. J. Schmitz.
- *
- * This file is part of the SCHMITZM library - a collection of utility
- * classes based on Java 1.6, focusing (not only) on Java Swing
- * and the Geotools library.
- *
- * The SCHMITZM project is hosted at:
- * http://wald.intevation.org/projects/schmitzm/
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License (license.txt)
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * or try this link: http://www.gnu.org/licenses/lgpl.html
- *
- * Contributors:
- * Martin O. J. Schmitz - initial API and implementation
- * Stefan A. Krüger - additional utility classes
- ******************************************************************************/
-package schmitzm.geotools.gui;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.Cursor;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.LayoutManager;
-import java.awt.Point;
-import java.awt.RenderingHints;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Point2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.ImageObserver;
-import java.io.IOException;
-import java.util.Date;
-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;
-import javax.swing.SwingUtilities;
-import javax.swing.event.MouseInputAdapter;
-
-import org.apache.log4j.Logger;
-import org.geotools.coverage.grid.GeneralGridEnvelope;
-import org.geotools.coverage.grid.GridCoverage2D;
-import org.geotools.coverage.grid.GridGeometry2D;
-import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
-import org.geotools.coverage.grid.io.AbstractGridFormat;
-import org.geotools.data.FeatureSource;
-import org.geotools.data.memory.MemoryFeatureCollection;
-import org.geotools.factory.GeoTools;
-import org.geotools.feature.FeatureCollection;
-import org.geotools.filter.AbstractFilter;
-import org.geotools.filter.GeometryFilterImpl;
-import org.geotools.filter.spatial.DWithinImpl;
-import org.geotools.geometry.GeneralEnvelope;
-import org.geotools.geometry.jts.JTS;
-import org.geotools.geometry.jts.ReferencedEnvelope;
-import org.geotools.map.DefaultMapContext;
-import org.geotools.map.MapContext;
-import org.geotools.map.MapLayer;
-import org.geotools.map.event.MapLayerListEvent;
-import org.geotools.parameter.Parameter;
-import org.geotools.referencing.CRS;
-import org.geotools.renderer.GTRenderer;
-import org.geotools.renderer.lite.RendererUtilities;
-import org.geotools.renderer.lite.StreamingRenderer;
-import org.geotools.resources.coverage.FeatureUtilities;
-import org.geotools.resources.image.ImageUtilities;
-import org.geotools.styling.Style;
-import org.geotools.swing.event.MapMouseEvent;
-import org.opengis.coverage.CannotEvaluateException;
-import org.opengis.feature.simple.SimpleFeature;
-import org.opengis.feature.simple.SimpleFeatureType;
-import org.opengis.feature.type.GeometryDescriptor;
-import org.opengis.filter.Filter;
-import org.opengis.filter.FilterFactory;
-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;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.TransformException;
-
-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.io.GeoImportUtil;
-import schmitzm.geotools.map.event.FeatureSelectedEvent;
-import schmitzm.geotools.map.event.GeneralSelectionEvent;
-import schmitzm.geotools.map.event.GridCoverageSelectedEvent;
-import schmitzm.geotools.map.event.GridCoverageValueSelectedEvent;
-import schmitzm.geotools.map.event.JMapPaneEvent;
-import schmitzm.geotools.map.event.JMapPaneListener;
-import schmitzm.geotools.map.event.MapAreaChangedEvent;
-import schmitzm.geotools.map.event.MapLayerListAdapter;
-import schmitzm.geotools.map.event.ScaleChangedEvent;
-import schmitzm.geotools.styling.StylingUtil;
-import schmitzm.swing.SwingUtil;
-
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.Envelope;
-import com.vividsolutions.jts.geom.Geometry;
-import com.vividsolutions.jts.geom.GeometryFactory;
-
-/**
- * Diese Klasse erweitert die Geotools-Klasse
- * {@link org.geotools.swing.JMapPane} um folgende Features:
- * <ul>
- * <li>zusaetzliche Maus-Steuerungen:
- * <ul>
- * <li><b>Linksklick:</b> ueber {@link #setState(int)} eingestellte Aktion</li>
- * <li><b>Rechtsklick:</b> Zoom-Out um Faktor 2 (nur wenn Linksklick auf Zoom-In
- * eingestellt ist)</li>
- * <li><b>Drag mit linker Maustaste:</b> neuen Karten-Bereich selektieren oder
- * Features selektieren (siehe {@link #setWindowSelectionState(int)})</li>
- * <li><b>Drag mit rechter Maustaste:</b> Karten-Bereich verschieben</li>
- * <li><b>Mausrad:</b> Zoom-In/Out ueber aktueller Position (Faktor 1.2)</li>
- * </ul>
- * </li>
- * <li>Ankoppeln von {@link JMapPaneListener} und Ausloesung diverser
- * Ereignisse:
- * <ul>
- * <li><b>{@link ScaleChangedEvent}:</b> Wird ausgeloest, wenn sich die
- * Aufloesung der angezeigten Karte aendert</li>
- * <li><b>{@link MapAreaChangedEvent}:</b> Wird ausgeloest, wenn sich die
- * Aufloesung angezeigte Karte-Ausschnitt aendert</li>
- * <li><b>{@link GeneralSelectionEvent}:</b> Wird ausgeloest, wenn der Anwender
- * einen Bereich aus der Karte ausgewaehlt hat (egal ob dabei gezoomt wurde,
- * Features/Raster selektiert wurden, oder nicht selektiert wurde)</li>
- * <li><b>{@link FeatureSelectedEvent}:</b> Wird ausgeloest, wenn der Anwender
- * Features aus der Karte ausgewaehlt hat</li>
- * <li><b>{@link GridCoverageSelectedEvent}:</b> Wird ausgeloest, wenn der
- * Anwender Raster-Bereiche aus der Karte ausgewaehlt hat</li>
- * </ul>
- * </li>
- * </ul>
- * Sofern eingeschaltet, erfolgt {@linkplain #setHighlight(boolean)
- * Highlighting} immer auf dem obersten sichtbaren Nicht-Raster-Layer.<br>
- * Darueberhinaus besteht ueber {@link #getTransform()} Zugriff auf eine
- * {@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 gtmig.org.geotools.swing.JMapPane {
-
- /** Stored the time used for the last real rendering in ms. **/
- private long lastRenderingDuration = Long.MAX_VALUE;
-
- /**
- * 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 == null || !oldMapArea.equals(mapArea))
- && (getState() == ZOOM_IN || getState() == ZOOM_OUT))
- {
-
- // Draw a quick scaled preview image, so the user is not do bored
- drawScaledPreviewImage_Zoom(getState());
-
- fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea, mapArea));
- }
-
-
- }
-
- /**
- * Diretly paints scaled preview into the {@link JMapPane}. Used to give the
- * user something to look at while we are rendering. Method should be called
- * after {@link #setMapArea(Envelope)} has been set to the new mapArea and
- * transform has been reset.<br/>
- * This method does nothing if the {@link #lastRenderingDuration} is smaller
- * then a trashhold.
- *
- * @param state Max be {@link #ZOOM_IN} or {@link #ZOOM_OUT}
- */
- private void drawScaledPreviewImage_Zoom(int state) {
-
-
- if (state == ZOOM_IN) {
-
-
- if (lastRenderingDuration < 220)
- return;
-
- if (getTransform() != null && getTransform().equals(oldTransform))
- return;
-
- Graphics2D graphics = (Graphics2D) JMapPane.this.getGraphics();
- Envelope gg = tranformGeoToWindow(mapArea.getMinX(), mapArea.getMinY(),
- mapArea.getMaxX(), mapArea.getMaxY(), oldTransform);
-
- graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
- graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_OFF);
- graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
- RenderingHints.VALUE_RENDER_SPEED);
-
- int xx1 = (int) Math.round( gg.getMinX() );
- int yy1 = (int) Math.round(gg.getMinY());
- int xx2 = (int) Math.round(gg.getMaxX());
- int yy2 = (int) Math.round(gg.getMaxY());
-
- graphics.setBackground(getMapBackgroundColor());
- graphics.drawImage(baseImage, 0, 0, JMapPane.this.getWidth(),
- JMapPane.this.getHeight(), xx1, yy1, xx2, yy2, null);
- } else if (state == ZOOM_OUT){
-
- if (lastRenderingDuration < 400) // This number is higher, because the zoom out preview image is uglier (while borders)
- return;
-
- if (mapArea != null && mapArea.equals(oldMapArea))
- return;
-
- Graphics2D graphics = (Graphics2D) JMapPane.this.getGraphics();
- Envelope gg = tranformGeoToWindow(oldMapArea.getMinX(), oldMapArea
- .getMinY(), oldMapArea.getMaxX(), oldMapArea.getMaxY(), null);
-
- graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
- graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_OFF);
- graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
- RenderingHints.VALUE_RENDER_SPEED);
-
- int xx1 = (int) Math.round( gg.getMinX() );
- int yy1 = (int) Math.round( gg.getMinY() );
- int xx2 = (int) Math.round( gg.getMaxX() );
- int yy2 = (int) Math.round( gg.getMaxY() );
-
- graphics.setBackground(getMapBackgroundColor());
- graphics.clearRect(0, 0, JMapPane.this.getWidth(), JMapPane.this
- .getHeight());
- graphics.drawImage(baseImage, xx1, yy1, xx2, yy2, 0, 0, JMapPane.this
- .getWidth(), JMapPane.this.getHeight(), null);
- }
- }
-
- private static final Cursor WAIT_CURSOR = Cursor
- .getPredefinedCursor(Cursor.WAIT_CURSOR);
-
- /** Logger for debug messages. */
- protected static final Logger LOGGER = Logger.getLogger(JMapPane.class);
-
- /** @deprecated ersetzt durch {@link #ZOOM_IN} */
- public static final int ZoomIn = gtmig.org.geotools.swing.JMapPane.ZoomIn;
- /** @deprecated ersetzt durch {@link #ZOOM_OUT} */
- public static final int ZoomOut = gtmig.org.geotools.swing.JMapPane.ZoomOut;
- /** @deprecated ersetzt durch {@link #PAN} */
- public static final int Pan = gtmig.org.geotools.swing.JMapPane.Pan;
- /** @deprecated ersetzt durch {@link #RESET} */
- public static final int Reset = gtmig.org.geotools.swing.JMapPane.Reset;
- /** @deprecated ersetzt durch {@link #SELECT_TOP} */
- public static final int Select = gtmig.org.geotools.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 = gtmig.org.geotools.swing.JMapPane.Reset;
- /**
- * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl
- * moeglich!
- *
- * @see #setState(int)
- */
- public static final int PAN = gtmig.org.geotools.swing.JMapPane.Pan;
- /**
- * Flag fuer Modus "Heran zoomen".
- *
- * @see #setWindowSelectionState(int)
- * @see #setState(int)
- */
- public static final int ZOOM_IN = gtmig.org.geotools.swing.JMapPane.ZoomIn;
- /**
- * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich!
- *
- * @see #setState(int)
- */
- public static final int ZOOM_OUT = gtmig.org.geotools.swing.JMapPane.ZoomOut;
- /**
- * Flag fuer Modus
- * "SimpleFeature-Auswahl auf dem obersten (sichtbaren) Layer".
- *
- * @see #setWindowSelectionState(int)
- * @see #setState(int)
- */
- public static final int SELECT_TOP = gtmig.org.geotools.swing.JMapPane.Select;
- /**
- * Flag fuer Modus "SimpleFeature-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;
-
- /**
- * 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>();
-
- final protected gtmig.org.geotools.swing.MouseSelectionTracker selTracker = new gtmig.org.geotools.swing.MouseSelectionTracker() {
- 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);
- }
-
- 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 FilterFactory ff = FilterUtil.FILTER_FAC2;
-
- /**
- * 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 final MouseWheelListener mouseWheelZoomListener = new MouseWheelListener() {
- public void mouseWheelMoved(MouseWheelEvent e) {
- performMouseWheelEvent(e);
- }
- };;
-
- // /** 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;
-
- /** 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;
-
- private MouseInputAdapter dragWaitCursorListener;
-
- /** An (transparent) image to paint over the map in the lower right corner **/
- private BufferedImage mapImage = null;
-
- /**
- * Holds a flag for each layer, whether it is regarded or ignored on
- * {@link #SELECT_TOP}, {@link #SELECT_ALL} and {@link #SELECT_ONE_FROM_TOP}
- * actions.
- */
- final protected HashMap<MapLayer, Boolean> mapLayerSelectable = new HashMap<MapLayer, Boolean>();
-
- /** We store the old transform for a moment to use it for the
- "quick scaled preview" in case of ZoomIn **/
- protected AffineTransform oldTransform = null;
-
- /**
- * Erzeugt ein neues MapPane.
- *
- * @param layout
- * Layout-Manager fuer die GUI-Komponente (z.B.
- * {@link BorderLayout})
- * @param isDoubleBuffered
- * siehe Konstruktor der
- * {@linkplain org.gtmig.org.geotools.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, null);
- }
-
- /**
- * Erzeugt ein neues MapPane.
- *
- * @param layout
- * Layout-Manager fuer die GUI-Komponente (z.B.
- * {@link BorderLayout})
- * @param isDoubleBuffered
- * siehe Konstruktor der
- * {@linkplain org.gtmig.org.geotools.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}
- * ).
- * @param rendererHints
- * A {@link Map} with hints for the renderer. May be
- * <code>null</code>.
- */
- public JMapPane(LayoutManager layout, Boolean isDoubleBuffered,
- GTRenderer renderer, MapContext context,
- Map<Object, Object> rendererHints) {
- super(layout != null ? layout : new BorderLayout(),
- isDoubleBuffered != null ? isDoubleBuffered : true,
- renderer != null ? renderer : GTUtil.createGTRenderer(),
- // renderer != null ? renderer : new StreamingRenderer(),
- context != null ? context : new DefaultMapContext(GeoImportUtil
- .getDefaultCRS()));
- //
- // // Having problems with StreamingRendere!
- // getRenderer().setContext(getContext());
-
- // 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 hintsJava2d = ImageUtilities.NN_INTERPOLATION_HINT;
- getRenderer().setJava2DHints(hintsJava2d);
-
- if (rendererHints != null) {
- getRenderer().getRendererHints().putAll(rendererHints);
- }
-
- // 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);
-
- 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);
- //
- // // 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());
- }
-
- public void layerAdded(
- 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 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 MapLayerListAdapter() {
- public void layerAdded(MapLayerListEvent e) {
- if (getContext().getLayerCount() == 1) {
- CoordinateReferenceSystem crs = null;
- // CRS aus Layer ermitteln
- try {
- crs = e.getLayer().getFeatureSource().getSchema()
- .getGeometryDescriptor()
- .getCoordinateReferenceSystem();
- // 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());
- Envelope newMapArea = getMaxExtend();
- 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. "
- + GeoImportUtil.getDefaultCRS()
- .getName() + " used.");
- // err.printStackTrace();
- crs = GeoImportUtil.getDefaultCRS();
- }
- // 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.",
- err);
- }
- }
- }
- });
-
- // Solved without just with the access methods
- // // The default is to regard a layer on selection
- // // actions
- // getContext().addMapLayerListListener(
- // new MapLayerListAdapter() {
- // @Override
- // public void layerAdded(MapLayerListEvent e) {
- // setMapLayerSelectable(e.getLayer(),true);
- // }
- // @Override
- // public void layerRemoved(MapLayerListEvent e) {
- // // remove reference to layer
- // mapLayerSelectable.remove(e.getLayer());
- // }
- // });
- }
-
- public JMapPane(LayoutManager layout, boolean isDoubleBuffered,
- GTRenderer renderer, MapContext context) {
- this(layout, isDoubleBuffered, renderer, context, null);
- }
-
- /**
- * 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;
- }
-
- /**
- * 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ü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ü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ü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);
-
- 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ü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 {
-
- // BB umrechnen von Layer-CRS in Map-CRS
- final CoordinateReferenceSystem targetCRS = getContext()
- .getCoordinateReferenceSystem();
- final CoordinateReferenceSystem sourceCRS = layer
- .getFeatureSource().getSchema()
- .getCoordinateReferenceSystem();
-
- Envelope mapAreaNew;
- if (targetCRS != null && sourceCRS != null
- && !CRS.equalsIgnoreMetadata(sourceCRS, targetCRS)) {
- mapAreaNew = JTSUtil.transformEnvelope(layer.getFeatureSource()
- .getBounds(), sourceCRS, targetCRS);
- } else {
- try {
- mapAreaNew = layer.getFeatureSource().getBounds();
- } catch (java.lang.IllegalArgumentException e) {
- LOGGER.error("Can't calc layers bounds...", e);
- mapAreaNew = null;
-
- /**
- *
- 23.10.2009 11:20:50
- * org.geotools.data.shapefile.shp.PolygonHandler read
- * WARNUNG: only one hole in this polygon record ERROR
- * JMapPane zoomToLayer Zoom to layer did not terminate
- * correctly java.lang.IllegalArgumentException: Points of
- * LinearRing do not form a closed linestring at
- * com.vividsolutions
- * .jts.geom.LinearRing.validateConstruction
- * (LinearRing.java:105) at
- * com.vividsolutions.jts.geom.LinearRing
- * .<init>(LinearRing.java:100) at
- * com.vividsolutions.jts.geom
- * .GeometryFactory.createLinearRing
- * (GeometryFactory.java:339) at
- * org.geotools.data.shapefile.
- * shp.PolygonHandler.read(PolygonHandler.java:188) at
- * org.geotools
- * .data.shapefile.shp.ShapefileReader$Record.shape
- * (ShapefileReader.java:106) at
- * org.geotools.data.shapefile.
- * ShapefileAttributeReader.next(
- * ShapefileAttributeReader.java:157) at
- * org.geotools.data.shapefile
- * .indexed.IndexedShapefileAttributeReader
- * .next(IndexedShapefileAttributeReader.java:122) at
- * org.geotools
- * .data.FIDFeatureReader.next(FIDFeatureReader.java:96) at
- * org.geotools.data.FIDFeatureReader.next(FIDFeatureReader.
- * java:55) at org.geotools.data.MaxFeatureReader.next(
- * MaxFeatureReader.java:61) at
- * org.geotools.data.MaxFeatureReader
- * .next(MaxFeatureReader.java:61)
- **/
- }
- }
-
- // 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)
-
- if (mapAreaNew != null) {
- mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1, mapAreaNew
- .getHeight() * 0.1);
- setMapArea(mapAreaNew);
- } else {
- LOGGER
- .warn("Couldn't transformEnvelope when zooming to the layer");
- }
- } catch (Exception err) {
- LOGGER.error("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ü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ü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 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 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 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!");
-
- // 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;
-
- // 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);
- }
-
- /**
- * 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;
- }
- }
-
- /**
- * 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);
- }
-
- /**
- * 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);
- }
-
- /**
- * 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 MapMouseEvent)
- try {
- return ((MapMouseEvent) e).getMapPosition().toPoint2D();
- } catch (Exception err) {
- LOGGER
- .error(
- "return ((GeoMouseEvent) e).getMapCoordinate(null).toPoint2D();",
- err);
- }
-
- // 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;
- }
-
- /**
- * 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) {
- // TODO perform dist withing filter
- return;
- }
-
- // Fenster-Koordinaten in Map-Koordinaten umwandeln
- Envelope env = tranformWindowToGeo(ox, oy, px, py);
-
- // 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(
- new BoundingBoxFilterGenerator(env, getContext()
- .getCoordinateReferenceSystem()), selectState, env);
- if (selectState == SELECT_ALL || !featuresFound)
- findGridCoverageSubsetsAndFireEvents(env, selectState);
- break;
- }
- }
-
- /**
- * Verarbeitet die Mausrad-Aktion, indem gezoomed wird.
- *
- * @param wheelEvt
- * Mausrad-Event
- */
- protected void performMouseWheelEvent(MouseWheelEvent wheelEvt) {
- if (getContext().getLayerCount() == 0)
- return;
-
- int units = wheelEvt.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;
-
- // Fenster-Koordinaten zu Karten-Koordinaten transformieren
- final AffineTransform transform2 = getTransform();
- if (transform2 == null) {
- LOGGER
- .warn("No transform can be created! Skipping MouseWheel performAction.");
- return;
- }
- Point2D mapCoord = transform2.transform(wheelEvt.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));
-
- setWaitCursorDuringNextRepaint(true);
- repaint();
-
- if (units > 0) {
- drawScaledPreviewImage_Zoom(ZOOM_IN);
- } else {
- drawScaledPreviewImage_Zoom(ZOOM_OUT);
- }
- }
-
- /**
- * 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 Geo-Koordinaten-Bereich in Fenster-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
- * @param winToGeotransform Eine Window to Geo transform. If <code>null</code>, {@link #getTransform()} is used.
- */
- public Envelope tranformGeoToWindow(double ox, double oy, double px, double py, AffineTransform winToGeotransform) {
- AffineTransform at = winToGeotransform == null ? getTransform() : winToGeotransform;
- Point2D geoO;
- try {
- geoO = at.inverseTransform(new Point2D.Double(ox, oy), null);
- Point2D geoP = at.inverseTransform(new Point2D.Double(px, py), null);
- return new Envelope(geoO.getX(), geoP.getX(), geoO.getY(), geoP.getY());
- } catch (NoninvertibleTransformException e) {
- LOGGER.error(e);
- return new Envelope(ox,oy,px,py);
- }
- }
-
- /**
- * 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;
-
-
- // We store the last Transform
- oldTransform = transform;
-
- 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;
- }
-
- /**
- * 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üger</a>
- */
- @Override
- public void setMapArea(Envelope env) {
-
- if (env != null && env.equals(mapArea)) {
- // Just return if nothing chnaged
- return;
- }
-
-
- // **********************************************************************
- // 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();
-
- super.setMapArea(env);
-
- 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));
- }
-
- /**
- * 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üger</a>
- */
- public void mouseClicked(MouseEvent e) {
- // wenn noch kein Layer dargestellt wird, nichts machen
- if (getContext().getLayerCount() == 0)
- return;
-
- switch (e.getButton()) {
- // Linksklick --> Eingestellte Funktion
- case MouseEvent.BUTTON1: // SimpleFeature-Auswahl nicht ueber die
- // super-Funktion
- int state = getState();
-
- 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 SimpleFeature verschickt. Und
- * zwar jenes SimpleFeature, 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()));
-
- // 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()) / 2;
-
- final Envelope envelope = new Envelope(geoCoord.getX(),
- geoCoord.getY(), geoCoord.getX(), geoCoord.getY());
-
- //
- // This is a tweak. The NearPointFilterGenerator doesn't work
- // any more in GT2.6... So we use a small BBOX.
- // Well, it's not the
- // NearPointFilterGenerator, but GeoTools that fails. I already
- // invested 3h in this... I guess the bug is in
- // ExtractBoundsFilterVisitor.visit(ProperyName) retuning null.
- // It should return the BBOX of value the named property.
-
- // Hashtable<MapLayer, FeatureCollection<SimpleFeatureType,
- // SimpleFeature>> result = findVisibleFeatures(
- // new NearPointFilterGenerator(geoCoord, dist,
- // getContext().getCoordinateReferenceSystem()),
- // state, envelope);
-
- final Envelope smallBox = new Envelope(geoCoord.getX() - dist,
- geoCoord.getX() - dist, geoCoord.getY() + dist,
- geoCoord.getY() + dist);
-
- Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = findVisibleFeatures(
- new BoundingBoxFilterGenerator(smallBox, getContext()
- .getCoordinateReferenceSystem()), state,
- envelope);
-
- boolean featuresFound = false;
- // Events ausloesen fuer jedes Layer
- for (Enumeration<MapLayer> element = result.keys(); element
- .hasMoreElements();) {
-
- MapLayer layer = element.nextElement();
- FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
- .get(layer);
- FeatureCollection<SimpleFeatureType, SimpleFeature> fcOne;
-
- if (fc != null && !fc.isEmpty()) {
-
- if (fc.size() > 1) {
- // Hier werden alle Features weggeschmissen, bis auf
- // das raeumlich naechste.
-
- SimpleFeature nearestFeature = null;
- Double nearestDist = 0.0;
-
- Iterator<SimpleFeature> fcIt = fc.iterator();
- try {
-
- while (fcIt.hasNext()) {
- SimpleFeature 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 ((nearestFeature == null)
- || (distance < nearestDist)) {
- nearestFeature = f;
- nearestDist = distance;
- }
- } else {
- LOGGER
- .info("!obj instanceof Geometry obj = "
- + obj
- .getClass()
- .getSimpleName());
- }
-
- }
-
- } finally {
- fc.close(fcIt);
- }
-
- fcOne = new MemoryFeatureCollection(fc.getSchema());
- 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 SimpleFeature 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);
- }
-
- break;
- }
- super.mouseClicked(e);
-
- break;
-
- // 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 LinkmapAreas-Klick auf ZOOM_IN eingestellt ist)
- // if ( oldState != ZOOM_IN )
- // return;
- setState(ZOOM_OUT);
- super.mouseClicked(e);
- setState(oldState);
- break;
-
- // Sonst nix
- default:
- return;
- }
-
- setMapArea(mapArea);
-
- if (getState() == ZOOM_IN && e.getButton() == MouseEvent.BUTTON1)
- drawScaledPreviewImage_Zoom(ZOOM_IN);
- else if (getState() == ZOOM_IN && e.getButton() == MouseEvent.BUTTON3)
- drawScaledPreviewImage_Zoom(ZOOM_OUT);
- else if (getState() == ZOOM_OUT&& e.getButton() == MouseEvent.BUTTON3)
- drawScaledPreviewImage_Zoom(ZOOM_OUT);
-
- }
-
- /**
- * 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.gtmig.org.geotools.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ü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 (seriouseChange) {
- if (setWaitCursorDuringNextRepaint) {
-
- 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);
- }
- }
-
- try {
-
-
- // Measuring the time needed to render the mappane.
- long startTime = new Date().getTime();
-
- super.paintComponent(g);
-
- // Only are we interested in the time it takes to do a *real* rendering of the image
- if (seriouseChange)
- lastRenderingDuration = new Date().getTime() - startTime;
-
-
- } catch (Exception e) {
- /**
- * I only need to catch UnknownHostException.. well...
- */
- LOGGER
- .info(
- "Error during JMapPane printComponent. Probably we are offline and reference some online SVGs?",
- e);
- }
- 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) {
- final Graphics baseG2 = (Graphics2D)baseImage.getGraphics();
- baseG2
- .drawImage(
- mapImage,
- baseImage.getWidth() - mapImage.getWidth() - 10,
- baseImage.getHeight() - mapImage.getHeight()
- - 10, this);
-
-
-// // If in debug mode, write the rending time into the display
-// baseG2.setColor(Color.white);
-// baseG2.drawString(lastRenderingDuration+"ms rendring", 50, 50);
-// baseG2.setColor(Color.black);
-// baseG2.drawString(lastRenderingDuration+"ms rendring", 51, 51);
-
- // 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().getGeometryDescriptor()
- .getCoordinateReferenceSystem(), getContext()
- .getCoordinateReferenceSystem());
-
- // 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;
- }
- }
-
- /**
- * 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);
- FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
- .getFeatureSource();
- GeometryFilterImpl filter = new BoundingBoxFilterGenerator(env,
- getContext().getCoordinateReferenceSystem())
- .adaptFilter(featureSource);
- 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 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<SimpleFeatureType, SimpleFeature>> findVisibleFeatures(
- GeomFilterGenerator filterGenerator, int mode, Envelope env) {
- Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>>();
- 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;
-
- // This should never happen, because the check should be performed
- // earlier already
- if (!isMapLayerSelectable(layer)) {
- LOGGER.debug("Ignoring layer " + layer.getTitle()
- + " because it is not declared as selectable!");
- continue;
- }
-
- // LOGGER.debug("mode = " + mode);
-
- // 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<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
- .getFeatureSource();
- final GeometryFilterImpl distancefilter = filterGenerator
- .adaptFilter(featureSource);
-
- /**
- * 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 && !layerFilter.equals(Filter.INCLUDE)) {
- 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<SimpleFeatureType, SimpleFeature> fc = featureSource
- .getFeatures(filter);
-
- if (!fc.isEmpty()) {
- 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;
- }
-
- }
- } catch (IOException err) {
- LOGGER.error("applying the distanceWithin filter", err);
- }
-
- // for ( FeatureCollection fc1 : result.values() )
- // LOGGER.debug("A "+fc1+" "+fc1.isEmpty());
- }
- // for ( FeatureCollection fc1 : result.values() )
- // LOGGER.debug("B "+fc1+" "+fc1.isEmpty());
-
- return result;
- }
-
- /**
- * 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 iterator
- * Filter
- * @param mode
- * Suchmodus
- * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
- */
- protected Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> findFeatures(
- GeomFilterGenerator filterGenerator, int mode, Envelope env) {
- Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>>();
- 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;
-
- // 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;
- }
-
- // 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<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
- .getFeatureSource();
- final GeometryFilterImpl filter = filterGenerator
- .adaptFilter(featureSource);
-
- try {
- // Filter auf Layer des Features anwenden
- // FeatureCollection fc = layer.getFeatureSource().getFeatures(
- // FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
- FeatureCollection<SimpleFeatureType, SimpleFeature> 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.
- fc = filterSLDVisibleOnly(fc, layer.getStyle());
-
- 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) {
- LOGGER.error("Looking for features:", err);
- }
-
- // for ( FeatureCollection fc1 : result.values() )
- // LOGGER.debug("A "+fc1+" "+fc1.isEmpty());
- }
- // for ( FeatureCollection fc1 : result.values() )
- // LOGGER.debug("B "+fc1+" "+fc1.isEmpty());
-
- return result;
- }
-
- /**
- * 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üger</a>
- */
- private MemoryFeatureCollection filterSLDVisibleOnly(
- final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
- final Style style) {
-
- // Der "scaleDenominator" der aktuellen JMapPane
- Double scaleDenominator = RendererUtilities
- .calculateOGCScale(new ReferencedEnvelope(getMapArea(),
- getContext().getCoordinateReferenceSystem()),
- getSize().width, null);
-
- return StylingUtil.filterSLDVisibleOnly(fc, style, scaleDenominator);
- }
-
- /**
- * 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<SimpleFeatureType, SimpleFeature>> result = findVisibleFeatures(
- filterGenerator, mode, env);
-
- // Events ausloesen fuer jedes Layer
- for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
-
- final MapLayer layer = e.nextElement();
-
- final FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
- .get(layer);
- if (fc != null && !fc.isEmpty())
- fireMapPaneEvent(new FeatureSelectedEvent(this, layer, env, fc));
- }
- return !result.isEmpty();
- }
-
- /**
- * 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;
-
- 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;
-
- // 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;
- }
-
- 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
-
- // 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;
- }
-
- /**
- * 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();
- }
-
- /**
- * 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üger</a>
- */
- protected Hashtable<MapLayer, double[]> findGridCoverageValues(
- Point2D point, int mode) {
- Hashtable<MapLayer, double[]> result = new Hashtable<MapLayer, double[]>();
-
- if (point == null)
- return result;
-
- 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);
-
- // LOGGER.info("layerObj = "+layerObj.getClass().getSimpleName());
-
- // 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;
- // }
-
- // 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;
- }
-
- GridCoverage2D sourceGrid;
-
- if (layerObj instanceof AbstractGridCoverage2DReader) {
- // LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
- // );
- AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
- Parameter readGG = new Parameter(
- AbstractGridFormat.READ_GRIDGEOMETRY2D);
-
- ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(
- mapArea, context.getCoordinateReferenceSystem());
-
- readGG.setValue(new GridGeometry2D(new GeneralGridEnvelope(
- getBounds()), mapExtend));
-
- try {
- sourceGrid = (GridCoverage2D) reader
- .read(new GeneralParameterValue[] { readGG });
- } catch (Exception e) {
- LOGGER.error(
- "read(new GeneralParameterValue[] { readGG })", e);
- continue;
- }
- } else {
- // Ein instanceof ist nicht noetig, da sonst schon break oder
- // continue aufgerufen worden waere
- sourceGrid = (GridCoverage2D) layerObj;
- }
-
- // vorher: double[] value = new double[2];
-
- // getNumSampleDimensions gibt die Anzahl der Baender des Rasters
- // zurueck.
- double[] values = new double[sourceGrid.getNumSampleDimensions()];
-
- 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("sourceGrid.evaluate(point, values);", e);
- continue;
- }
-
- // SK: voher wurde nur der erste Wert zurueckgegeben
- // result.put(layer,value[0]);
- // jetzt werden alle werte zueuckgegeben
-
- result.put(layer, values);
- // Beim Modus "oberstes Layer selektieren" die Schleife beenden
- if (mode == SELECT_TOP)
- break;
- }
- return result;
- }
-
- /**
- * 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üger</a>
- */
- protected boolean findGridCoverageValuesAndFireEvents(Point2D point,
- int mode) {
- Hashtable<MapLayer, double[]> result = findGridCoverageValues(point,
- mode);
-
- // 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();
- }
-
- // /**
- // * Bereitet einen BoundingBox-Filter vor. Das "linke" Attribut der
- // * Expression (das SimpleFeature-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
- // * SimpleFeature-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 SimpleFeature-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ü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;
- // }
-
- /**
- * 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 SimpleFeature 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 SimpleFeature beinhalten
- // if ( fc == null || fc.size() != 1 )
- // return false;
- // // SimpleFeature muss genau 1 Attribut mit dem Namen "GridCoverage"
- // haben
- // SimpleFeatureType ftype = fc.getFeatureType();
- // if ( ftype == null || ftype.getAttributeCount() != 1 ||
- // !"GridCoverage".equalsIgnoreCase(ftype.getAttributeType(0).getName())
- // )
- // return false;
- // } catch (Exception err) {
- // }
- // return true;
- }
-
- /**
- * 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 SimpleFeature 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}.
- *
- * @see {@link FeatureUtilities#wrapGridCoverage(GridCoverage2D)} and
- * {@link FeatureUtilities#wrapGridCoverageReader(AbstractGridCoverage2DReader, GeneralParameterValue[])}
- *
- * @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) {
- return FeatureUtil
- .getWrappedGeoObject((FeatureSource<SimpleFeatureType, SimpleFeature>) layer
- .getFeatureSource());
-
- }
-
- /**
- * 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üger</a>
- */
-
- public void dispose() {
- if (isDisposed())
- return;
-
- if (dragWaitCursorListener != null)
- this.removeMouseListener(dragWaitCursorListener);
- if (mouseWheelZoomListener != null)
- this.removeMouseWheelListener(mouseWheelZoomListener);
-
- // Alle mapPaneListener entfernen
- mapPaneListeners.clear();
-
- getContext().clearLayerList();
-
- removeAll();
- disposed = true;
- }
-
- /**
- * 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;
- }
-
- //
- // /**
- // * Werden Rasterlayer waehrend einer PAN Aktion versteckt?
- // * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- // Krü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üger</a>
- // */
- // public void setHideRasterLayersDuringPan(boolean
- // hideRasterLayersDuringPan) {
- // this.hideRasterLayersDuringPan = hideRasterLayersDuringPan;
- // }
-
- public boolean isSetWaitCursorDuringNextRepaint() {
- return setWaitCursorDuringNextRepaint;
- }
-
- /**
- * 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üger</a>
- */
- public void setWaitCursorDuringNextRepaint(
- boolean waitCursorDuringNextRepaint) {
- this.setWaitCursorDuringNextRepaint = waitCursorDuringNextRepaint;
- }
-
- /**
- * 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üger</a>
- */
- public Cursor getNormalCursor() {
- return normalCursor;
- }
-
- /**
- * 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üger</a>
- */
- public void setNormalCursor(Cursor normalCursor) {
- this.normalCursor = normalCursor;
- }
-
- // /**
- // * 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 SimpleFeature 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 SimpleFeature beinhalten
- // if ( fc == null || fc.size() != 1 )
- // return false;
- // // SimpleFeature muss genau 1 Attribut vom Typ FeatureAttributeType haben
- // SimpleFeatureType 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;
- // }
-
- /**
- * Nuetzlich wenn die Componente gedruckt (z.B. wenn ein Screenshot gemacht
- * wird) wird. Dann werden wird der Hintergrund auf WEISS gesetzt.
- *
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
- * Krüger</a>
- */
- @Override
- public void print(Graphics g) {
- Color orig = getBackground();
- setBackground(Color.WHITE);
-
- // wrap in try/finally so that we always restore the state
- try {
- super.print(g);
- } finally {
- setBackground(orig);
- }
- }
-
- /**
- * Sets the mapArea to smartly present the given features. Note: The method
- * does not call {@link #repaint()} on the {@link JMapPane}.
- */
- public void zoomTo(SimpleFeature feature) {
- final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
- .getFeatureType());
- mfc.add(feature);
- zoomTo(mfc);
- }
-
- /**
- * 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<SimpleFeatureType, SimpleFeature> features) {
-
- CoordinateReferenceSystem mapCRS = getContext()
- .getCoordinateReferenceSystem();
- CoordinateReferenceSystem fCRS = features.getSchema()
- .getGeometryDescriptor().getCoordinateReferenceSystem();
- // if (! mapCRS.equals(fCRS)) {
- // throw new
- // RuntimeException(
- // "Projecting the features to show to the map CRS is not yet implemented."
- // );
- // }
-
- double width = mapArea.getWidth();
- double height = mapArea.getHeight();
- double ratio = height / width;
-
- if (features == null || features.size() == 0) {
- // feature count == 0 Zoom to the full extend
- return;
- } else if (features.size() == 1) {
-
- // feature count == 1 Just move the window to the point and zoom 'a
- // bit'
- SimpleFeature singleFeature = (SimpleFeature) features.iterator()
- .next();
-
- if (((Geometry) 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;
- }
-
- 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("Looking for a Math transform", e);
- } catch (TransformException e) {
- LOGGER.error("Looking for a Math transform", e);
- }
- }
-
- Coordinate newLeftBottom = new Coordinate(centre.x - width / 2.,
- centre.y - height / 2.);
- Coordinate newTopRight = new Coordinate(centre.x + width / 2.,
- centre.y + height / 2.);
-
- Envelope newMapArea = new Envelope(newLeftBottom, newTopRight);
-
- setMapArea(newMapArea);
-
- } else {
- ReferencedEnvelope fBounds = features.getBounds();
-
- Envelope bounds;
- if (!mapCRS.equals(fCRS)) {
- bounds = JTSUtil.transformEnvelope(fBounds, fCRS, mapCRS);
- } else {
- bounds = fBounds;
- }
- // BB umrechnen von Layer-CRS in Map-CRS
-
- // Expand a bit
- bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.);
-
- setMapArea(bounds);
- }
- }
-
- /**
- * 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>();
-
- /**
- * 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;
- }
-
- /**
- * 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);
-
- /**
- * 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<SimpleFeatureType, SimpleFeature> fs) {
- GeometryDescriptor geomDescr = fs.getSchema()
- .getGeometryDescriptor();
- CoordinateReferenceSystem fsCRS = geomDescr
- .getCoordinateReferenceSystem();
- GeometryFilterImpl filter = filterCache.get(fsCRS);
- if (filter == null) {
- filter = prepareFilter(fsCRS);
- filterCache.put(fsCRS, filter);
- }
- Expression geometry = ff.property(geomDescr.getLocalName());
- filter.setExpression1(geometry);
- return filter;
- }
-
- }
-
- /**
- * {@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;
-
- /**
- * 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;
- }
-
- /**
- * 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;
- }
- }
-
- /**
- * {@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
- * defNearPointFilterGeneratorines 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);
-
- if (nearPoint == null || nearPoint2 == null)
- throw new RuntimeException("Unable to transform CRS from "
- + baseCRS + " to " + crs);
-
- nearDist = Math.abs(nearPoint.x - nearPoint2.x);
- }
- // Filter fuer Point zusammenstellen
- final Geometry geometry = FilterUtil.GEOMETRY_FAC
- .createPoint(nearPoint);
-
- final DWithinImpl dwithinFilter = new DWithinImpl(
- FilterUtil.FILTER_FAC2, null, null);
- dwithinFilter.setDistance(nearDist);
- dwithinFilter.setExpression2(FilterUtil.FILTER_FAC2
- .literal(geometry));
-
- return dwithinFilter;
- }
-
- }
-
- /**
- * Sets whether a layer is regarded or ignored on {@link #SELECT_TOP},
- * {@link #SELECT_ALL} and {@link #SELECT_ONE_FROM_TOP} actions.
- *
- * @param layer
- * a layer
- * @param selectable
- * if {@code false} the layer is ignored during the upper
- * mentioned actions. If <code>null</code>, the default (true)
- * will be used.
- */
- public void setMapLayerSelectable(MapLayer layer, Boolean selectable) {
- if (selectable == null)
- mapLayerSelectable.remove(layer);
- else
- mapLayerSelectable.put(layer, selectable);
- }
-
- /**
- * Returns whether a layer is regarded or ignored on {@link #SELECT_TOP},
- * {@link #SELECT_ALL} and {@link #SELECT_ONE_FROM_TOP} actions. Returns
- * <code>true</code> if the selectability has not been defined.
- *
- * @param layer
- * a layer
- */
- public boolean isMapLayerSelectable(MapLayer layer) {
- Boolean selectable = mapLayerSelectable.get(layer);
- return selectable == null ? true : selectable;
- }
-
- /**
- * Returns in milli seconds the time the last rending of the
- * {@link JMapPane} took. #Long.MAX_VALUE if the JMapPane has not been
- * rendered yet.
- */
- public long getLastRenderingDuration() {
- return lastRenderingDuration;
- }
-}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredEditorFrame.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredEditorFrame.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredEditorFrame.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -80,7 +80,7 @@
* {@code null} wird eine neue {@link LayeredMapPane}-Instanz erzeugt)
*/
public LayeredEditorFrame(LayeredMapPane lmp, String title) {
- super( lmp != null ? lmp : new LayeredMapPane(new GeoMapPane(new JEditorPane(),null,null,null, null)),title);
+ super( lmp != null ? lmp : new LayeredMapPane(new GeoMapPane(new JEditorPane(),null,null, null)),title);
if ( !(layeredMapPane.geoMapPane.mapPane instanceof JEditorPane) )
throw new IllegalArgumentException("LayeredMapPane must contain a JEditorPane to use in LayeredEditorFrame.");
this.toolBar = new JEditorToolBar( (JEditorPane)layeredMapPane.geoMapPane.mapPane );
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapFrame.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapFrame.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapFrame.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -48,7 +48,7 @@
import schmitzm.geotools.map.event.FeatureSelectedEvent;
import schmitzm.geotools.map.event.GridCoverageSelectedEvent;
-import schmitzm.geotools.map.event.JMapPaneEvent;
+import schmitzm.geotools.map.event.MapPaneEvent;
import schmitzm.geotools.map.event.JMapPaneListener;
import schmitzm.swing.SelectionInputOption;
import schmitzm.swing.SwingUtil;
@@ -61,7 +61,7 @@
* {@link LayeredMapPane#isVisualisable(Object)}-Methode zu entnehmen.<br>
* Das Fenster besteht aus 3 Komponenten:
* <ol>
- * <li>Eine Map ({@link JMapPane}) zu grafischen Darstellung der Layer</li>
+ * <li>Eine Map ({@link SelectableXMapPane}) zu grafischen Darstellung der Layer</li>
* <li>Eine Liste mit Steuerungskomponenten, ueber die die einzelnen Layer
* angesprochen werden koennen (ein/ausblenden, zoomen, ...).</li>
* <li>Eine Status-Zeile, in der die Koordinaten der aktuellen Mausposition
@@ -86,7 +86,7 @@
private JPanel contentPane = null;
/** Karten- und Layer-Kontroll-Bereich. */
protected LayeredMapPane layeredMapPane = null;
- private JMapPane mapPane = null;
+ private SelectableXMapPane mapPane = null;
private MapContext mapContext = null;
/** Status-Balken. */
protected MapPaneStatusBar statusBar = null;
@@ -160,7 +160,7 @@
// Spezielles RasterPositionLabel in dem die Koordinaten des in der
// ComboBox ausgewaehlten Rasters angezeigt werden
RasterPositionLabel rpLabel = new RasterPositionLabel(1) {
- protected MapLayer determineRasterLayer(final JMapPane mapPane) {
+ protected MapLayer determineRasterLayer(final SelectableXMapPane mapPane) {
return rasterComboBox.getValue();
}
};
@@ -191,7 +191,7 @@
featuresFrame.setSize( new Dimension(400,200) );
// Ausgewaehlte Features werden im Detail-Frame angezeigt
mapPane.addMapPaneListener( new JMapPaneListener() {
- public void performMapPaneEvent(JMapPaneEvent e) {
+ public void performMapPaneEvent(MapPaneEvent e) {
// Wenn Features ueber die Maus aus der Karte ausgewaehlt werden,
// oeffnet sich ein Detail-Fenster
if ( e instanceof FeatureSelectedEvent && e.getSourceObject() == mapPane ) {
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/LayeredMapPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -62,7 +62,7 @@
* Das Fenster besteht aus 2 durch einen Divider voneinander getrennten
* Komponenten:
* <ol>
- * <li>Eine Map ({@link JMapPane}) zu grafischen Darstellung der Layer</li>
+ * <li>Eine Map ({@link SelectableXMapPane}) zu grafischen Darstellung der Layer</li>
* <li>Eine Liste mit Steuerungskomponenten, ueber die die einzelnen Layer
* angesprochen werden koennen (ein/ausblenden, zoomen, ...).</li>
* </ol>
@@ -89,7 +89,7 @@
* dargestellt werden */
protected GeoMapPane geoMapPane = null;
private MapContext mapContext = null;
- private JMapPane mapPane = null;
+ private SelectableXMapPane mapPane = null;
private Hashtable<MapLayer,Object> layerObjects = new Hashtable<MapLayer,Object>();
/** Komponente, in der die Layer-Kontrolle dargestellt ist. */
protected MapContextControlPane layerControlList = null;
@@ -148,7 +148,7 @@
/**
* Liefert den Karten-Bereich der Komponente.
*/
- public JMapPane getMapPane() {
+ public SelectableXMapPane getMapPane() {
return mapPane;
}
@@ -263,7 +263,6 @@
}
// Anzeige aktualisieren
- mapPane.setReset(true);
mapPane.repaint();
// Wenn Rendering geklappt hat, zum Layer gehoerendes Objekt merken
@@ -291,7 +290,6 @@
mapPane.setMapArea(fc.getBounds());
// Anzeige aktualisieren
- mapPane.setReset(true);
mapPane.repaint();
// Wenn Rendering geklappt hat, zum Layer gehoerendes Objekt merken
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapActionControlPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapActionControlPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapActionControlPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -46,7 +46,7 @@
/**
* Diese Klasse stellt einen {@link JToolBar} dar, mit dem zwischen den
- * verschiedenen "Klick"- und "Drag"-Aktionen des {@link JMapPane} gewechselt werden
+ * verschiedenen "Klick"- und "Drag"-Aktionen des {@link SelectableXMapPane} gewechselt werden
* kann:
* <ul>
* <li><b>Info:</b>
@@ -112,8 +112,8 @@
public static final String SELECT_TOP = MapActionControlPane.class.getName()+".SELECT_TOP";
- /** {@link JMapPane} das gesteuert wird. */
- protected JMapPane mapPane = null;
+ /** {@link SelectableXMapPane} das gesteuert wird. */
+ protected SelectableXMapPane mapPane = null;
/** Button fuer Info-Aktion. */
protected JToggleButton infoState = null;
/** Button fuer Zoom-Aktion. */
@@ -126,7 +126,7 @@
protected int actionMask = 0;
/**
- * Erzeugt eine horizontale Steuer-Komponente, die (noch) keinem {@link JMapPane}
+ * Erzeugt eine horizontale Steuer-Komponente, die (noch) keinem {@link SelectableXMapPane}
* zugeordnet ist.
*/
public MapActionControlPane() {
@@ -135,20 +135,20 @@
/**
* Erzeugt eine horizontale Steuer-Komponente.
- * @param mapPane {@link JMapPane} das gesteuert wird
+ * @param mapPane {@link SelectableXMapPane} das gesteuert wird
*/
- public MapActionControlPane(JMapPane mapPane) {
+ public MapActionControlPane(SelectableXMapPane mapPane) {
this( mapPane, HORIZONTAL );
}
/**
* Erzeugt eine Steuer-Komponente.
- * @param mapPane {@link JMapPane} das gesteuert wird
+ * @param mapPane {@link SelectableXMapPane} das gesteuert wird
* @param orientation Orientierung der Komponente ({@link #HORIZONTAL}/{@link #VERTICAL})
* @param actionMask definiert, welche Aktionen (in Form von Buttons) angezeigt werden
* (OR-Verknuepfung der {@code ACTION}-Konstanten
*/
- public MapActionControlPane(JMapPane mapPane, int orientation, int actionMask) {
+ public MapActionControlPane(SelectableXMapPane mapPane, int orientation, int actionMask) {
super(orientation);
this.actionMask = actionMask;
// Button erzeugen und in Gruppe einfuegen, damit immer nur
@@ -177,17 +177,17 @@
/**
* Erzeugt eine Steuer-Komponente. Alle Aktionen sind sichtbar.
- * @param mapPane {@link JMapPane} das gesteuert wird
+ * @param mapPane {@link SelectableXMapPane} das gesteuert wird
* @param orientation Orientierung der Komponente ({@link #HORIZONTAL}/{@link #VERTICAL})
*/
- public MapActionControlPane(JMapPane mapPane, int orientation) {
+ public MapActionControlPane(SelectableXMapPane mapPane, int orientation) {
this(mapPane,orientation,ACTION_ALL);
}
/**
* Setzt die Aktivierung der Aktionen entsprechend den Einstellungen
* des {@code JMapPane}.
- * @see JMapPane#getWindowSelectionState()
+ * @see SelectableXMapPane#getWindowSelectionState()
*/
public void resetActions() {
for (int i=0; i<getComponentCount(); i++) {
@@ -199,17 +199,17 @@
// Buttons entsprechend dem MapPane-Status einstellen
infoState.doClick();
if ( mapPane != null ) {
- switch( mapPane.getWindowSelectionState() ) {
- case JMapPane.ZOOM_IN: if ( isActionVisible(ACTION_ZOOM_IN) )
+ switch( mapPane.getState() ) {
+ case SelectableXMapPane.ZOOM_IN: if ( isActionVisible(ACTION_ZOOM_IN) )
zoomState.doClick();
break;
- case JMapPane.SELECT_TOP: if ( isActionVisible(ACTION_SELECT_TOP) )
+ case SelectableXMapPane.SELECT_TOP: if ( isActionVisible(ACTION_SELECT_TOP) )
selectTopState.doClick();
break;
- case JMapPane.SELECT_ALL: if ( isActionVisible(ACTION_SELECT_ALL) )
+ case SelectableXMapPane.SELECT_ALL: if ( isActionVisible(ACTION_SELECT_ALL) )
selectAllState.doClick();
break;
- case JMapPane.NONE: if ( isActionVisible(ACTION_INFO) )
+ case SelectableXMapPane.NONE: if ( isActionVisible(ACTION_INFO) )
infoState.doClick();
break;
}
@@ -225,17 +225,17 @@
}
/**
- * Setzt das {@link JMapPane}, das durch diese Komponente gesteuert wird.
+ * Setzt das {@link SelectableXMapPane}, das durch diese Komponente gesteuert wird.
*/
- public void setMapPane(JMapPane mapPane) {
+ public void setMapPane(SelectableXMapPane mapPane) {
this.mapPane = mapPane;
resetActions();
}
/**
- * Liefert das {@link JMapPane}, das durch diese Komponente gesteuert wird.
+ * Liefert das {@link SelectableXMapPane}, das durch diese Komponente gesteuert wird.
*/
- public JMapPane getMapPane() {
+ public SelectableXMapPane getMapPane() {
return this.mapPane;
}
@@ -292,12 +292,12 @@
* <li>{@code JMapPane.setState( JMapPane.Select )}</li>
* <li>{@code JMapPane.setHighlight( true )}</li>
* </ol>
- * @see JMapPane
+ * @see SelectableXMapPane
* @param e das ActionEvent
*/
public void actionPerformed(ActionEvent e) {
- getMapPane().setWindowSelectionState( JMapPane.NONE );
- getMapPane().setState(JMapPane.NONE);
+ getMapPane().setState( SelectableXMapPane.NONE );
+ getMapPane().setState(SelectableXMapPane.NONE);
}
}
@@ -326,12 +326,12 @@
* <li>{@code JMapPane.setState( JMapPane.ZoomIn )}</li>
* <li>{@code JMapPane.setHighlight( false )}</li>
* </ol>
- * @see JMapPane
+ * @see SelectableXMapPane
* @param e das ActionEvent
*/
public void actionPerformed(ActionEvent e) {
- getMapPane().setWindowSelectionState( JMapPane.ZOOM_IN );
- getMapPane().setState(JMapPane.ZOOM_IN);
+ getMapPane().setState( SelectableXMapPane.ZOOM_IN );
+ getMapPane().setState(SelectableXMapPane.ZOOM_IN);
}
}
@@ -361,12 +361,12 @@
* <li>{@code JMapPane.setState( JMapPane.Select )}</li>
* <li>{@code JMapPane.setHighlight( true )}</li>
* </ol>
- * @see JMapPane
+ * @see SelectableXMapPane
* @param e das ActionEvent
*/
public void actionPerformed(ActionEvent e) {
- getMapPane().setWindowSelectionState( JMapPane.SELECT_TOP );
- getMapPane().setState(JMapPane.SELECT_TOP);
+ getMapPane().setState( SelectableXMapPane.SELECT_TOP );
+ getMapPane().setState(SelectableXMapPane.SELECT_TOP);
}
}
@@ -395,12 +395,12 @@
* <li>{@code JMapPane.setState( JMapPane.Select )}</li>
* <li>{@code JMapPane.setHighlight( true )}</li>
* </ol>
- * @see JMapPane
+ * @see SelectableXMapPane
* @param e das ActionEvent
*/
public void actionPerformed(ActionEvent e) {
- getMapPane().setWindowSelectionState( JMapPane.SELECT_ALL );
- getMapPane().setState(JMapPane.SELECT_ALL);
+ getMapPane().setState( SelectableXMapPane.SELECT_ALL );
+ getMapPane().setState(SelectableXMapPane.SELECT_ALL);
}
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapContextControlPane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapContextControlPane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapContextControlPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -69,7 +69,7 @@
import schmitzm.swing.menu.ConnectedPopupMenu;
/**
- * Diese Komponente ist an ein {@link JMapPane} gekoppelt und stellt die
+ * Diese Komponente ist an ein {@link SelectableXMapPane} gekoppelt und stellt die
* dargestellten Layer in Form eine Liste dar.
*
* @author Martin Schmitz
@@ -259,7 +259,7 @@
public static final String FF_DIALOG_APPLY = FeatureLayerFilterDialog.APPLY_BUTTON;
/** Karte, deren Layer kontrolliert werden. */
- protected JMapPane mapPane = null;
+ protected SelectableXMapPane mapPane = null;
/** Farbpaletten, die durch die Kontrolle zugewiesen werden koennen. */
private ColorMapManager colorMaps = null;
@@ -272,7 +272,7 @@
* Raster-Farbpaletten, die durch die Kontrolle zugewiesen werden
* koennen
*/
- public MapContextControlPane(JMapPane mapPane, ColorMapManager colorMaps) {
+ public MapContextControlPane(SelectableXMapPane mapPane, ColorMapManager colorMaps) {
super();
// this.parentFrame = SwingUtil.getParentWindow(this);
this.mapPane = mapPane;
@@ -422,7 +422,7 @@
hideAllLayers.addActionListener(this);
invertAllLayers.addActionListener(this);
filterLayer.addActionListener(this);
- filterLayer.setEnabled(!JMapPane.isGridCoverageLayer(layer));
+ filterLayer.setEnabled(!SelectableXMapPane.isGridCoverageLayer(layer));
if (filterLayer.isEnabled())
try {
filterDialog = new FeatureLayerFilterDialog(null, mapPane,
@@ -622,7 +622,6 @@
if (colMap != null) {
layer.setStyle(GridUtil.createStyle(colMap, 1.0));
customiseDialogPanel.setColorMap(colMap);
- mapPane.setReset(true);
mapPane.repaint();
((JCheckBoxMenuItem) e.getSource()).setSelected(true);
}
@@ -694,7 +693,7 @@
// FeatureTypeStyle[] fts = layer.getStyle().getFeatureTypeStyles();
// if ( !(fts[0].getRules()[0].getSymbolizers()[0] instanceof
// RasterSymbolizer) ) {
- if (!JMapPane.isGridCoverageLayer(layer)) {
+ if (!SelectableXMapPane.isGridCoverageLayer(layer)) {
this.setEnabled(false);
return;
}
@@ -812,7 +811,6 @@
layer.setStyle(GridUtil.createStyle(StylingUtil
.cloneColorMap(customiseDialogPanel
.getColorMap()), 1.0));
- mapPane.setReset(true);
mapPane.repaint();
menuItemGroup.setUnselected();
// }
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapPaneStatusBar.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapPaneStatusBar.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/MapPaneStatusBar.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -40,7 +40,7 @@
/**
* Stellt ein {@link BorderLayout}-Panel dar, in dem links ein
* {@link RasterPositionLabel} und rechts ein {@link GeoPositionLabel}
- * dargestellt ist. Beide werden automatisch mit einem {@link JMapPane}
+ * dargestellt ist. Beide werden automatisch mit einem {@link SelectableXMapPane}
* gekoppelt, so dass automatisch die Anzeige der Labels aktualisiert wird,
* sobald sich der Cursor ueber die Karte bewegt.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
@@ -57,7 +57,7 @@
* Erzeugt einen neuen Status-Balken.
* @param mapPane Karte mit der die Labels gekoppelt werden
*/
- public MapPaneStatusBar(JMapPane mapPane) {
+ public MapPaneStatusBar(SelectableXMapPane mapPane) {
this(mapPane,null,null);
}
@@ -69,7 +69,7 @@
* @param geoPosLabel Label, in dem die Geo-Koordinaten angezeigt
* werden (wenn {@code null}, wird ein neues {@link GeoPositionLabel} erzeugt).
*/
- public MapPaneStatusBar(JMapPane mapPane, RasterPositionLabel rasterPosLabel, GeoPositionLabel geoPosLabel) {
+ public MapPaneStatusBar(SelectableXMapPane mapPane, RasterPositionLabel rasterPosLabel, GeoPositionLabel geoPosLabel) {
super();
setLayout( new BorderLayout() );
// rechts: Anzeige der aktuellen Welt-Koordinaten
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/RasterPositionLabel.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/RasterPositionLabel.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/RasterPositionLabel.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -46,6 +46,7 @@
import org.opengis.referencing.operation.MathTransform;
import schmitzm.data.WritableGrid;
+import schmitzm.geotools.feature.FeatureUtil;
import schmitzm.geotools.grid.GridUtil;
import schmitzm.swing.CaptionsChangeable;
@@ -54,7 +55,7 @@
* Raster-Koordinaten und der Rasterwert an der entsprechenden Stelle angezeigt
* werden.<br>
* Die Klasse fungiert als {@link MouseMotionListener} und kann so direkt an ein
- * {@link JMapPane} gekoppelt werden. Die Koordinaten-Darstellung im Label
+ * {@link SelectableXMapPane} gekoppelt werden. Die Koordinaten-Darstellung im Label
* aktualisiert sich somit automatisch, sobald sich die Maus ueber die Karte
* bewegt.
*
@@ -117,15 +118,15 @@
/**
* Stellt die Koordinaten und den Wert des obersten (sichtbaren) Rasters im
- * Label dar, wenn das Event von einem {@link JMapPane} ausgeloest wurde.<br>
+ * Label dar, wenn das Event von einem {@link SelectableXMapPane} ausgeloest wurde.<br>
* Wird {@link #mouseMoved(MouseEvent)} und
* {@link #mouseDragged(MouseEvent)} aufgerufen.
*/
protected void displayCoordinates(final MouseEvent e) {
- if (e == null || !(e.getSource() instanceof JMapPane))
+ if (e == null || !(e.getSource() instanceof SelectableXMapPane))
return;
- final JMapPane mapPane = (JMapPane) e.getSource();
+ final SelectableXMapPane mapPane = (SelectableXMapPane) e.getSource();
// oberstes dargestelltes Raster suchen
final MapLayer layer = determineRasterLayer(mapPane);
if (layer == null) {
@@ -133,7 +134,7 @@
return;
}
// Objekt aus Layer herausholen
- final Object layerObj = JMapPane.getLayerSourceObject(layer);
+ final Object layerObj = FeatureUtil.getLayerSourceObject(layer);
if ((layerObj == null)
|| (!(layerObj instanceof GridCoverage2D) && !(layerObj instanceof org.geotools.coverage.grid.io.AbstractGridCoverage2DReader)))
return;
@@ -146,7 +147,7 @@
2);
try {
// Welt-Koordinaten der Mausposition ermitteln (in CRS der Map)
- final Point2D actPos_MapCRS = JMapPane
+ final Point2D actPos_MapCRS = SelectableXMapPane
.getMapCoordinatesFromEvent(e);
if (actPos_MapCRS == null)
return;
@@ -203,7 +204,7 @@
2);
try {
// Welt-Koordinaten der Mausposition ermitteln (in CRS der Map)
- final Point2D actPos_MapCRS = JMapPane
+ final Point2D actPos_MapCRS = SelectableXMapPane
.getMapCoordinatesFromEvent(e);
if (actPos_MapCRS == null)
return;
@@ -217,7 +218,7 @@
// Wert im Raster ermitteln
Hashtable<MapLayer, double[]> foundGridCoverageValues = mapPane
.findGridCoverageValues(actPos_GridCRS.toPoint2D(),
- JMapPane.SELECT_ALL);
+ SelectableXMapPane.SELECT_ALL);
if (foundGridCoverageValues != null
&& foundGridCoverageValues.size() > 0) {
double[] gcValue = foundGridCoverageValues.values()
@@ -249,7 +250,7 @@
* @param mapPane
* MapPane der angezeigten Layer.
*/
- protected MapLayer determineRasterLayer(final JMapPane mapPane) {
+ protected MapLayer determineRasterLayer(final SelectableXMapPane mapPane) {
return mapPane.getTopVisibleGridCoverageLayer();
}
@@ -309,7 +310,7 @@
/**
* Wird aufgerufen, sobald die Maus bewegt wird. Stellt die Koordinaten und
- * den Rasterwert im Label dar, wenn das Event von einem {@link JMapPane}
+ * den Rasterwert im Label dar, wenn das Event von einem {@link SelectableXMapPane}
* ausgeloest wurde.
*
* @see #displayCoordinates(MouseEvent)
@@ -321,7 +322,7 @@
/**
* Wird aufgerufen, sobald die Maus bei gedrueckter Taste bewegt wird.
* Stellt die Koordinaten und den Rasterwert im Label dar, wenn das Event
- * von einem {@link JMapPane} ausgeloest wurde.
+ * von einem {@link SelectableXMapPane} ausgeloest wurde.
*
* @see #displayCoordinates(MouseEvent)
*/
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableFeatureTablePane.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableFeatureTablePane.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableFeatureTablePane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -59,8 +59,8 @@
/**
* Extends the {@link FeatureTablePane} with buttons and functionality to select
- * lines. Can be configured to set the regions on an external a {@link JMapPane}
- * . Can be configured to show a simple preview {@link JMapPane} to the left of
+ * lines. Can be configured to set the regions on an external a {@link SelectableXMapPane}
+ * . Can be configured to show a simple preview {@link SelectableXMapPane} to the left of
* the table.
*
* @author Stefan A. Krüger
@@ -85,7 +85,7 @@
.getResource("resource/icons/mActionZoomToSelected.png"));
- private final JMapPane externalMapPane;
+ private final SelectableXMapPane externalMapPane;
private JLabel statusLabel;
@@ -93,16 +93,16 @@
* @param fc
* {@link FeatureCollection} that holds the data.
* @param geomPreview
- * If <code>true</code>, a preview {@link JMapPane} is attached
+ * If <code>true</code>, a preview {@link SelectableXMapPane} is attached
* to the left of the table.
* @param externalMapPane
* <code>null</code> if this component is NOT linked to an
* external JMapPane. If mapPane == <code>null</code>, the
* "ZoomToSelection" Button is automatically disabled. If a
- * {@link JMapPane} is passed, the "ZoomToSelectedFeature"
+ * {@link SelectableXMapPane} is passed, the "ZoomToSelectedFeature"
* function will be enabled.
*/
- public SelectableFeatureTablePane(FeatureCollection fc, boolean geomPreview, JMapPane externalMapPane) {
+ public SelectableFeatureTablePane(FeatureCollection fc, boolean geomPreview, SelectableXMapPane externalMapPane) {
this(new FeatureCollectionTableModel(fc), geomPreview, externalMapPane);
}
@@ -110,17 +110,17 @@
* @param model
* {@link FeatureCollectionTableModel} that holds the data.
* @param geomPreview
- * If <code>true</code>, a preview {@link JMapPane} is attached
+ * If <code>true</code>, a preview {@link SelectableXMapPane} is attached
* to the left of the table.
* @param externalMapPane
* <code>null</code> if this component is NOT linked to an
* external JMapPane. If mapPane == <code>null</code>, the
* "ZoomToSelection" Button is automatically disabled. If a
- * {@link JMapPane} is passed, the "ZoomToSelectedFeature"
+ * {@link SelectableXMapPane} is passed, the "ZoomToSelectedFeature"
* function will be enabled.
*/
public SelectableFeatureTablePane(FeatureCollectionTableModel model,
- boolean geomPreview, JMapPane externalMapPane) {
+ boolean geomPreview, SelectableXMapPane externalMapPane) {
super(model, null, geomPreview);
this.externalMapPane = externalMapPane;
Copied: branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableXMapPane.java (from rev 506, branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java)
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/JMapPane.java 2009-10-31 12:15:37 UTC (rev 506)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/gui/SelectableXMapPane.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -0,0 +1,1262 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ *
+ * This file is part of the SCHMITZM library - a collection of utility
+ * classes based on Java 1.6, focusing (not only) on Java Swing
+ * and the Geotools library.
+ *
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ *
+ * Contributors:
+ * Martin O. J. Schmitz - initial API and implementation
+ * Stefan A. Krüger - additional utility classes
+ ******************************************************************************/
+package schmitzm.geotools.gui;
+
+import gtmig.org.geotools.swing.GeomFilterGenerator;
+import gtmig.org.geotools.swing.SelectXMapPaneMouseListener;
+import gtmig.org.geotools.swing.XMapPane;
+import gtmig.org.geotools.swing.GeomFilterGenerator.BoundingBoxFilterGenerator;
+
+import java.awt.BorderLayout;
+import java.awt.LayoutManager;
+import java.awt.Point;
+import java.awt.RenderingHints;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Map;
+
+import javax.swing.JList;
+
+import org.apache.log4j.Logger;
+import org.geotools.coverage.grid.GeneralGridEnvelope;
+import org.geotools.coverage.grid.GridCoverage2D;
+import org.geotools.coverage.grid.GridGeometry2D;
+import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
+import org.geotools.coverage.grid.io.AbstractGridFormat;
+import org.geotools.data.FeatureSource;
+import org.geotools.data.memory.MemoryFeatureCollection;
+import org.geotools.factory.GeoTools;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.filter.GeometryFilterImpl;
+import org.geotools.geometry.GeneralEnvelope;
+import org.geotools.geometry.jts.JTS;
+import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.map.DefaultMapContext;
+import org.geotools.map.MapContext;
+import org.geotools.map.MapLayer;
+import org.geotools.parameter.Parameter;
+import org.geotools.referencing.CRS;
+import org.geotools.renderer.GTRenderer;
+import org.geotools.renderer.lite.StreamingRenderer;
+import org.geotools.resources.image.ImageUtilities;
+import org.geotools.swing.utils.MapLayerUtils;
+import org.opengis.coverage.CannotEvaluateException;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.filter.Filter;
+import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+
+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;
+import schmitzm.geotools.map.event.GridCoverageSelectedEvent;
+import schmitzm.geotools.map.event.GridCoverageValueSelectedEvent;
+import schmitzm.geotools.map.event.JMapPaneListener;
+import schmitzm.geotools.map.event.MapAreaChangedEvent;
+import schmitzm.geotools.map.event.MapPaneEvent;
+import schmitzm.geotools.map.event.ScaleChangedEvent;
+import schmitzm.geotools.styling.StylingUtil;
+
+import com.vividsolutions.jts.geom.Envelope;
+
+/**
+ * Diese Klasse erweitert die Geotools-Klasse
+ * {@link org.geotools.swing.JMapPane} um folgende Features:
+ * <ul>
+ * <li>zusaetzliche Maus-Steuerungen:
+ * <ul>
+ * <li><b>Linksklick:</b> ueber {@link #setState(int)} eingestellte Aktion</li>
+ * <li><b>Rechtsklick:</b> Zoom-Out um Faktor 2 (nur wenn Linksklick auf Zoom-In
+ * eingestellt ist)</li>
+ * <li><b>Drag mit linker Maustaste:</b> neuen Karten-Bereich selektieren oder
+ * Features selektieren (siehe {@link #setState(int)})</li>
+ * <li><b>Drag mit rechter Maustaste:</b> Karten-Bereich verschieben</li>
+ * <li><b>Mausrad:</b> Zoom-In/Out ueber aktueller Position (Faktor 1.2)</li>
+ * </ul>
+ * </li>
+ * <li>Ankoppeln von {@link JMapPaneListener} und Ausloesung diverser
+ * Ereignisse:
+ * <ul>
+ * <li><b>{@link ScaleChangedEvent}:</b> Wird ausgeloest, wenn sich die
+ * Aufloesung der angezeigten Karte aendert</li>
+ * <li><b>{@link MapAreaChangedEvent}:</b> Wird ausgeloest, wenn sich die
+ * Aufloesung angezeigte Karte-Ausschnitt aendert</li>
+ * <li><b>{@link GeneralSelectionEvent}:</b> Wird ausgeloest, wenn der Anwender
+ * einen Bereich aus der Karte ausgewaehlt hat (egal ob dabei gezoomt wurde,
+ * Features/Raster selektiert wurden, oder nicht selektiert wurde)</li>
+ * <li><b>{@link FeatureSelectedEvent}:</b> Wird ausgeloest, wenn der Anwender
+ * Features aus der Karte ausgewaehlt hat</li>
+ * <li><b>{@link GridCoverageSelectedEvent}:</b> Wird ausgeloest, wenn der
+ * Anwender Raster-Bereiche aus der Karte ausgewaehlt hat</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * Sofern eingeschaltet, erfolgt {@linkplain #setHighlight(boolean)
+ * Highlighting} immer auf dem obersten sichtbaren Nicht-Raster-Layer.<br>
+ * Darueberhinaus besteht ueber {@link #getScreenToWorld()} Zugriff auf eine
+ * {@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 SelectableXMapPane extends gtmig.org.geotools.swing.XMapPane {
+
+ /** Logger for debug messages. */
+ protected static final Logger LOGGER = Logger
+ .getLogger(SelectableXMapPane.class);
+
+ /**
+ * Flag fuer Modus "Nichts machen".
+ *
+ * @see #setState(int)
+ * @see #setState(int)
+ */
+ public static final int NONE = 100;
+
+ // /** 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>();
+
+ // private MouseInputAdapter dragWaitCursorListener;
+
+ /**
+ * Erzeugt ein neues MapPane.
+ *
+ * @param layout
+ * Layout-Manager fuer die GUI-Komponente (z.B.
+ * {@link BorderLayout})
+ * @param isDoubleBuffered
+ * siehe Konstruktor der
+ * {@linkplain org.SelectableXMapPane.org.geotools.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
+ * Oberklasse}
+ * @param renderer
+ * Renderer fuer die graphische Darestellung (z.B.
+ * {@link StreamingRenderer})
+ * @param localContext
+ * Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+ * ).
+ */
+ public SelectableXMapPane(MapContext context) {
+ this(context, null);
+ }
+
+ /**
+ * Erzeugt ein neues MapPane.
+ *
+ * @param layout
+ * Layout-Manager fuer die GUI-Komponente (z.B.
+ * {@link BorderLayout})
+ * @param isDoubleBuffered
+ * siehe Konstruktor der
+ * {@linkplain org.SelectableXMapPane.org.geotools.swing.JMapPane#JMapPane(LayoutManager,boolean,GTRenderer,MapContext)
+ * Oberklasse}
+ * @param renderer
+ * Renderer fuer die graphische Darestellung (z.B.
+ * {@link StreamingRenderer})
+ * @param localContext
+ * Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+ * ).
+ */
+ public SelectableXMapPane() {
+ this(null, null);
+ }
+
+ /**
+ * This {@link MouseListener} is managing all selection related tasks
+ */
+ protected final SelectXMapPaneMouseListener selectMapPaneMouseListener = new SelectXMapPaneMouseListener(this);
+
+ /**
+ * Erzeugt ein neues MapPane.
+ *
+ * @param renderer
+ * Renderer fuer die graphische Darestellung (z.B.
+ * {@link StreamingRenderer})
+ * @param context
+ * Verwaltung der einzelnen Layer (z.B. {@link DefaultMapContext}
+ * ).
+ * @param rendererHints
+ * A {@link Map} with hints for the renderer. May be
+ * <code>null</code>.
+ */
+ public SelectableXMapPane(MapContext context,
+ Map<Object, Object> rendererHints) {
+ super(null, rendererHints);
+
+ //
+ // // Having problems with StreamingRendere!
+ // getRenderer().setContext(getContext());
+
+ // 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 hintsJava2d = ImageUtilities.NN_INTERPOLATION_HINT;
+ setJava2dHints(hintsJava2d);
+
+ /**
+ * Adding the #selectionMapPaneMouseListener
+ */
+ this.addMouseListener(selectMapPaneMouseListener);
+ this.addMouseMotionListener(selectMapPaneMouseListener);
+ this.addMouseWheelListener(selectMapPaneMouseListener);
+
+ setState(ZOOM_IN);
+
+ //
+ // // CRS wird immer vom ersten in die Karte eingefuegten Layer
+ // uebernommen
+ // // Wenn noch keine MapArea gesetzt wurde, wird diese vom Layer
+ // // uebernommen
+ // getLocalContext().addMapLayerListListener(new MapLayerListAdapter() {
+ // public void layerAdded(MapLayerListEvent e) {
+ // if (getLocalContext().getLayerCount() == 1) {
+ // CoordinateReferenceSystem crs = null;
+ // // CRS aus Layer ermitteln
+ // try {
+ // crs = e.getLayer().getFeatureSource().getSchema()
+ // .getGeometryDescriptor()
+ // .getCoordinateReferenceSystem();
+ // // 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());
+ // Envelope newMapArea = getMaxExtend();
+ // setMapArea(newMapArea);
+ // // in layerAdded(.) der Oberklasse wird
+ // // mapArea nochmal neu gesetzt, wenn das
+ // // erste Layer
+ // // eingefuegt wird
+ // // >> hier nur die AreaOfInterest setzen
+ // getLocalContext().setAreaOfInterest(newMapArea, crs);
+ // }
+ // } catch (Exception err) {
+ // LOGGER
+ // .warn("CRS could not be determined from map layer. "
+ // + GeoImportUtil.getDefaultCRS()
+ // .getName() + " used.");
+ // // err.printStackTrace();
+ // crs = GeoImportUtil.getDefaultCRS();
+ // }
+ // // CRS dem MapContext zuweisen
+ // try {
+ // getLocalContext().setCoordinateReferenceSystem(crs);
+ // // LOGGER.debug("MapContext-CRS set to: "+crs);
+ // } catch (Exception err) {
+ // LOGGER.error(
+ // "CRS could not be assigned to map context.",
+ // err);
+ // }
+ // }
+ // }
+ // });
+
+ // Solved without just with the access methods
+ // // The default is to regard a layer on selection
+ // // actions
+ // getContext().addMapLayerListListener(
+ // new MapLayerListAdapter() {
+ // @Override
+ // public void layerAdded(MapLayerListEvent e) {
+ // setMapLayerSelectable(e.getLayer(),true);
+ // }
+ // @Override
+ // public void layerRemoved(MapLayerListEvent e) {
+ // // remove reference to layer
+ // mapLayerSelectable.remove(e.getLayer());
+ // }
+ // });
+ }
+
+ /**
+ * Triggers to repaint (fast) and re-render (slow) the JMapPane
+ */
+ public void refresh() {
+ mapImageInvalid = true;
+ repaint();
+ }
+
+ /**
+ * Aktiviert oder deaktiviert das AntiAliasing for diese
+ * {@link SelectableXMapPane}. AntiALiasing ist besonders fuer
+ * Textbeschriftung sehr schoen, verbraucht aber auch mehr Performance.
+ *
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ */
+ public void setAntiAliasing(final boolean aa) {
+ // LOGGER.info("Setting AntiAliasing for this JMapPane to " + aa);
+ RenderingHints java2DHints = super.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);
+ super.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..
+ try {
+
+ // BB umrechnen von Layer-CRS in Map-CRS
+ final CoordinateReferenceSystem targetCRS = getContext()
+ .getCoordinateReferenceSystem();
+ final CoordinateReferenceSystem sourceCRS = layer
+ .getFeatureSource().getSchema()
+ .getCoordinateReferenceSystem();
+
+ Envelope mapAreaNew;
+ if (!CRS.equalsIgnoreMetadata(sourceCRS, targetCRS)) {
+ mapAreaNew = JTSUtil.transformEnvelope(layer.getFeatureSource()
+ .getBounds(), sourceCRS, targetCRS);
+ } else {
+ try {
+ mapAreaNew = layer.getFeatureSource().getBounds();
+ } catch (java.lang.IllegalArgumentException e) {
+ LOGGER.error("Can't calc layers bounds...", e);
+ mapAreaNew = null;
+
+ /**
+ *
+ 23.10.2009 11:20:50
+ * org.geotools.data.shapefile.shp.PolygonHandler read
+ * WARNUNG: only one hole in this polygon record ERROR
+ * JMapPane zoomToLayer Zoom to layer did not terminate
+ * correctly java.lang.IllegalArgumentException: Points of
+ * LinearRing do not form a closed linestring at
+ * com.vividsolutions
+ * .jts.geom.LinearRing.validateConstruction
+ * (LinearRing.java:105) at
+ * com.vividsolutions.jts.geom.LinearRing
+ * .<init>(LinearRing.java:100) at
+ * com.vividsolutions.jts.geom
+ * .GeometryFactory.createLinearRing
+ * (GeometryFactory.java:339) at
+ * org.geotools.data.shapefile.
+ * shp.PolygonHandler.read(PolygonHandler.java:188) at
+ * org.geotools
+ * .data.shapefile.shp.ShapefileReader$Record.shape
+ * (ShapefileReader.java:106) at
+ * org.geotools.data.shapefile.
+ * ShapefileAttributeReader.next(
+ * ShapefileAttributeReader.java:157) at
+ * org.geotools.data.shapefile
+ * .indexed.IndexedShapefileAttributeReader
+ * .next(IndexedShapefileAttributeReader.java:122) at
+ * org.geotools
+ * .data.FIDFeatureReader.next(FIDFeatureReader.java:96) at
+ * org.geotools.data.FIDFeatureReader.next(FIDFeatureReader.
+ * java:55) at org.geotools.data.MaxFeatureReader.next(
+ * MaxFeatureReader.java:61) at
+ * org.geotools.data.MaxFeatureReader
+ * .next(MaxFeatureReader.java:61)
+ **/
+ }
+ }
+
+ // 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)
+
+ if (mapAreaNew != null) {
+ mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1, mapAreaNew
+ .getHeight() * 0.1);
+ setMapArea(mapAreaNew);
+ } else {
+ LOGGER
+ .warn("Couldn't transformEnvelope when zooming to the layer");
+ }
+ } catch (Exception err) {
+ LOGGER.error("Zoom to layer did not terminate correctly", err);
+ }
+ }
+
+ /**
+ * Zooms the {@link SelectableXMapPane} 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üger</a>
+ */
+ public void zoomToLayer(int index) {
+ final MapContext context = getContext();
+ if (context != null)
+ zoomToLayer(context.getLayer(index));
+ }
+
+ /**
+ * Zooms the {@link SelectableXMapPane} 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ü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 (!isWellDefined())
+ 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 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 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;
+ }
+
+ /**
+ * 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 state
+ * Modus fuer Window-Selektion
+ */
+ public void setState(final int state) {
+
+ // 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: "+newSelState);
+
+ // // Den selTracker bei Wechsel zu NONE deaktivieren (SK), damit
+ // // Selektionsfenster beim Draggen nicht mehr gezeichnet wird
+ // if ((state == NONE) && (getState() != NONE)) {
+ // this.removeMouseListener(selTracker);
+ // } else
+ // // Den selTracker bei Wechsel von NONE aktivieren (SK)
+ // if ((state != NONE) && (getState() == NONE)) {
+ // this.addMouseListener(selTracker);
+ // }
+ //
+ selectMapPaneMouseListener.setEnabled((state == SELECT_ALL || state == SELECT_ONE_FROM_TOP || state == SELECT_TOP));
+
+ super.setState(state);
+ }
+
+ /**
+ * 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üger</a>
+ */
+ public boolean findGridCoverageValuesAndFireEvents(Point2D point,
+ int mode) {
+ Hashtable<MapLayer, double[]> result = findGridCoverageValues(point,
+ mode);
+
+ // 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();
+ }
+
+ /**
+ * 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)} return <code>false</code>, falls durch die
+ * neue MapArea ein nicht gueltiger Massstab entstehen wuerde UND die
+ * bisherige maparea != null ist
+ *
+ * @param newMapArea
+ * neuer Kartenausschnitt im CRS des {@link MapContext}
+ * @see #resetTransforms()
+ * @see #getScreenToWorld()
+ *
+ * @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üger</a>
+ */
+ @Override
+ public boolean setMapArea(Envelope newMapArea) {
+ double oldScale = getScale();
+
+ boolean b = super.setMapArea(newMapArea);
+
+ if (b) {
+ if (getScale() > 0) // If the JPane has not been set yet, there is
+ // no scale
+ fireMapPaneEvent(new ScaleChangedEvent(this, oldScale,
+ getScale()));
+ fireMapPaneEvent(new MapAreaChangedEvent(this, oldMapArea,
+ getMapArea()));
+ }
+ return b;
+ }
+
+ /**
+ * Sets the mapArea to smartly present the given features. Note: The method
+ * does not call {@link #repaint()} on the {@link SelectableXMapPane}.
+ */
+ public void zoomTo(SimpleFeature feature) {
+ final MemoryFeatureCollection mfc = new MemoryFeatureCollection(feature
+ .getFeatureType());
+ mfc.add(feature);
+ zoomTo(mfc);
+ }
+
+ /**
+ * 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
+ */
+ public 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);
+ FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+ .getFeatureSource();
+ GeometryFilterImpl filter = new BoundingBoxFilterGenerator(env,
+ getContext().getCoordinateReferenceSystem())
+ .adaptFilter(featureSource);
+ return !layer.getFeatureSource().getFeatures(filter).isEmpty();
+ } catch (Exception err) {
+ return false;
+ }
+ }
+
+ /**
+ * 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 iterator
+ * Filter
+ * @param mode
+ * Suchmodus
+ * @return eine leere {@link Hashtable} falls der Filter {@code null} ist
+ */
+ protected Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> findFeatures(
+ GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+ Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>>();
+ 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;
+
+ // 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;
+ }
+
+ // 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<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+ .getFeatureSource();
+ final GeometryFilterImpl filter = filterGenerator
+ .adaptFilter(featureSource);
+
+ try {
+ // Filter auf Layer des Features anwenden
+ // FeatureCollection fc = layer.getFeatureSource().getFeatures(
+ // FilterUtil.cloneFilter(filter) ); // KLAPPT (NOCH) NICHT
+ FeatureCollection<SimpleFeatureType, SimpleFeature> 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.
+ fc = StylingUtil.filterSLDVisibleOnly(fc, layer.getStyle(),
+ this);
+
+ 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) {
+ LOGGER.error("Looking for features:", err);
+ }
+
+ // for ( FeatureCollection fc1 : result.values() )
+ // LOGGER.debug("A "+fc1+" "+fc1.isEmpty());
+ }
+ // for ( FeatureCollection fc1 : result.values() )
+ // LOGGER.debug("B "+fc1+" "+fc1.isEmpty());
+
+ return result;
+ }
+
+ /**
+ * 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üger</a>
+ */
+ protected Hashtable<MapLayer, double[]> findGridCoverageValues(
+ Point2D point, int mode) {
+ Hashtable<MapLayer, double[]> result = new Hashtable<MapLayer, double[]>();
+
+ if (point == null)
+ return result;
+
+ 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 = FeatureUtil
+ .getWrappedGeoObject((FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+ .getFeatureSource());
+
+ // LOGGER.info("layerObj = "+layerObj.getClass().getSimpleName());
+
+ // 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;
+ // }
+
+ // 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;
+ }
+
+ GridCoverage2D sourceGrid;
+
+ if (layerObj instanceof AbstractGridCoverage2DReader) {
+ // LOGGER.info("layerObj instanceof AbstractGridCoverage2DReader"
+ // );
+ AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) layerObj;
+ Parameter readGG = new Parameter(
+ AbstractGridFormat.READ_GRIDGEOMETRY2D);
+
+ ReferencedEnvelope mapExtend = new org.geotools.geometry.jts.ReferencedEnvelope(
+ mapArea, context.getCoordinateReferenceSystem());
+
+ readGG.setValue(new GridGeometry2D(new GeneralGridEnvelope(
+ getBounds()), mapExtend));
+
+ try {
+ sourceGrid = (GridCoverage2D) reader
+ .read(new GeneralParameterValue[] { readGG });
+ } catch (Exception e) {
+ LOGGER.error(
+ "read(new GeneralParameterValue[] { readGG })", e);
+ continue;
+ }
+ } else {
+ // Ein instanceof ist nicht noetig, da sonst schon break oder
+ // continue aufgerufen worden waere
+ sourceGrid = (GridCoverage2D) layerObj;
+ }
+
+ // vorher: double[] value = new double[2];
+
+ // getNumSampleDimensions gibt die Anzahl der Baender des Rasters
+ // zurueck.
+ double[] values = new double[sourceGrid.getNumSampleDimensions()];
+
+ 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("sourceGrid.evaluate(point, values);", e);
+ continue;
+ }
+
+ // SK: voher wurde nur der erste Wert zurueckgegeben
+ // result.put(layer,value[0]);
+ // jetzt werden alle werte zueuckgegeben
+
+ result.put(layer, values);
+ // Beim Modus "oberstes Layer selektieren" die Schleife beenden
+ if (mode == SELECT_TOP)
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Propagiert ein Ereignis an alle angeschlossenen Listener.
+ *
+ * @param e
+ * Ereignis
+ */
+ public void fireMapPaneEvent(MapPaneEvent e) {
+ for (JMapPaneListener l : mapPaneListeners)
+ l.performMapPaneEvent(e);
+ }
+
+ /**
+ * 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
+ */
+ public void performSelectionEvent(int ox, int oy, int px, int py) {
+
+ if (getContext().getLayerCount() == 0)
+ return;
+
+
+ // Fenster-Koordinaten in Map-Koordinaten umwandeln
+ Envelope env = tranformWindowToGeo(ox, oy, px, py);
+
+ // Generelles Event ausloesen
+ fireMapPaneEvent(new GeneralSelectionEvent(this, env));
+
+ int selectState = getState();
+ 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;
+ }
+ }
+
+ /**
+ * 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!)
+ */
+ public boolean findFeaturesAndFireEvents(
+ GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+ Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = findVisibleFeatures(
+ filterGenerator, mode, env);
+
+ // Events ausloesen fuer jedes Layer
+ for (final Enumeration<MapLayer> e = result.keys(); e.hasMoreElements();) {
+
+ final MapLayer layer = e.nextElement();
+
+ final FeatureCollection<SimpleFeatureType, SimpleFeature> fc = result
+ .get(layer);
+ if (fc != null && !fc.isEmpty())
+ fireMapPaneEvent(new FeatureSelectedEvent(this, layer, env, fc));
+ }
+ return !result.isEmpty();
+ }
+
+ /**
+ * 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 state
+ * Suchmodus
+ * @return eine leere {@link Hashtable} falls die Bounding-Box {@code null}
+ * ist
+ */
+ protected Hashtable<MapLayer, GridCoverage2D> findGridCoverageSubsets(
+ Envelope env, int state) {
+ Hashtable<MapLayer, GridCoverage2D> result = new Hashtable<MapLayer, GridCoverage2D>();
+ if (env == null)
+ return result;
+
+ 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 = FeatureUtil
+ .getWrappedGeoObject((FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+ .getFeatureSource());
+ if (!layer.isVisible())
+ continue;
+
+ // 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 ((state == XMapPane.SELECT_TOP || state == XMapPane.SELECT_ONE_FROM_TOP)
+ && featureLayerIntersectsEnvelope(layer, env))
+ break;
+ continue;
+ }
+
+ 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
+
+ // 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 (state == SELECT_TOP || state == SELECT_ONE_FROM_TOP)
+ break;
+ }
+ 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
+ */
+ public 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();
+ }
+
+ /**
+ * 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
+ */
+ public Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> findVisibleFeatures(
+ GeomFilterGenerator filterGenerator, int mode, Envelope env) {
+ Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>> result = new Hashtable<MapLayer, FeatureCollection<SimpleFeatureType, SimpleFeature>>();
+ if (filterGenerator == null)
+ throw new IllegalArgumentException("filterGenerator may not be 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;
+
+ // This should never happen, because the check should be performed
+ // earlier already
+ if (!isMapLayerSelectable(layer)) {
+ LOGGER.debug("Ignoring layer " + layer.getTitle()
+ + " because it is not declared as selectable!");
+ continue;
+ }
+
+ // LOGGER.debug("mode = " + mode);
+
+ // 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;
+ }
+// ReferencedEnvelope re;
+// re.inter
+
+ // 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<SimpleFeatureType, SimpleFeature> featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) layer
+ .getFeatureSource();
+ final GeometryFilterImpl distancefilter = filterGenerator
+ .adaptFilter(featureSource);
+
+ /**
+ * 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 && !layerFilter.equals(Filter.INCLUDE)) {
+ 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<SimpleFeatureType, SimpleFeature> fc = featureSource
+ .getFeatures(filter);
+
+ if (!fc.isEmpty()) {
+ fc = StylingUtil.filterSLDVisibleOnly(fc, layer.getStyle(),
+ this);
+
+ 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;
+ }
+
+ }
+ } catch (IOException err) {
+ LOGGER.error("applying the distanceWithin filter", err);
+ }
+
+ // for ( FeatureCollection fc1 : result.values() )
+ // LOGGER.debug("A "+fc1+" "+fc1.isEmpty());
+ }
+ // for ( FeatureCollection fc1 : result.values() )
+ // LOGGER.debug("B "+fc1+" "+fc1.isEmpty());
+
+ return result;
+ }
+
+ @Override
+ public void mouseDragged(Point startPos, Point lastPos, MouseEvent event) {
+
+ super.mouseDragged(startPos, lastPos, event);
+
+ }
+
+ /**
+ * 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().getGeometryDescriptor()
+ .getCoordinateReferenceSystem(), getContext()
+ .getCoordinateReferenceSystem());
+
+ // 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;
+ }
+ }
+
+ /**
+ * 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 SimpleFeature 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) {
+ return (MapLayerUtils.isGridLayer(layer).get(MapLayerUtils.IS_GRID_KEY) == Boolean.TRUE);
+ }
+
+}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/io/GeoImportUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/io/GeoImportUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/io/GeoImportUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -91,7 +91,8 @@
* @version 1.0
*/
public class GeoImportUtil {
- private static final Logger LOGGER = Logger.getLogger(GeoImportUtil.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(GeoImportUtil.class
+ .getName());
/**
* These postfixes are associated with Arc/Info ASCII Grid files TODO .0
@@ -127,54 +128,67 @@
wld, jgw, pgw, tfw
};
- ///////////////////////////////////////////////////////////////////////////
- // ASCII IMPORT STYLE
- ///////////////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////////////
+ // ASCII IMPORT STYLE
+ // /////////////////////////////////////////////////////////////////////////
/**
- * This type specifies how this class can proceed the import of ASCII rasters.
- * @see GeoImportUtil#readGridFromArcInfoASCII(Object, CoordinateReferenceSystem)
- * @see GeoImportUtil#readGridRasterFromGeoTiff(File, CoordinateReferenceSystem)
- */
- public static enum ARCASCII_IMPORT_TYPE {
- /** Use the old {@link ArcGridRaster}. This works fine (colorization and
- * no data transparency), but {@link ArcGridRaster} is deprecated
- * and no longer supported since gt2-2.3.0-M0. */
- USE_ARCGRIDRASTER,
- /** Use the {@link ArcGridReader} from "standard" GT.<br>
- * <b>Note:</b>There may be problems with colorization and
- * no data transparency using this import type! */
- USE_ARCGRIDREADER
- }
-
- /**
- * Specifies how this class proceeds the import of ASCII rasters. The default is
- * {@link ARCASCII_IMPORT_TYPE#USE_ARCGRIDREADER} because this works fine!
- * @see GeoImportUtil#readGridFromArcInfoASCII(Object, CoordinateReferenceSystem)
- * @see GeoImportUtil#readGridRasterFromGeoTiff(File, CoordinateReferenceSystem)
- */
- private static ARCASCII_IMPORT_TYPE ARCASCII_IMPORT_MODE = ARCASCII_IMPORT_TYPE.USE_ARCGRIDRASTER;
+ * This type specifies how this class can proceed the import of ASCII
+ * rasters.
+ *
+ * @see GeoImportUtil#readGridFromArcInfoASCII(Object,
+ * CoordinateReferenceSystem)
+ * @see GeoImportUtil#readGridRasterFromGeoTiff(File,
+ * CoordinateReferenceSystem)
+ */
+ public static enum ARCASCII_IMPORT_TYPE {
+ /**
+ * Use the old {@link ArcGridRaster}. This works fine (colorization and
+ * no data transparency), but {@link ArcGridRaster} is deprecated and no
+ * longer supported since gt2-2.3.0-M0.
+ */
+ USE_ARCGRIDRASTER,
+ /**
+ * Use the {@link ArcGridReader} from "standard" GT.<br>
+ * <b>Note:</b>There may be problems with colorization and no data
+ * transparency using this import type!
+ */
+ USE_ARCGRIDREADER
+ }
- /**
- * Sets how this class proceeds the import of ASCII rasters.
- * @param mode the mode how to proceed the import
- */
- public static void setAsciiRasterImportMode(ARCASCII_IMPORT_TYPE mode) {
- ARCASCII_IMPORT_MODE = mode;
- }
+ /**
+ * Specifies how this class proceeds the import of ASCII rasters. The
+ * default is {@link ARCASCII_IMPORT_TYPE#USE_ARCGRIDREADER} because this
+ * works fine!
+ *
+ * @see GeoImportUtil#readGridFromArcInfoASCII(Object,
+ * CoordinateReferenceSystem)
+ * @see GeoImportUtil#readGridRasterFromGeoTiff(File,
+ * CoordinateReferenceSystem)
+ */
+ private static ARCASCII_IMPORT_TYPE ARCASCII_IMPORT_MODE = ARCASCII_IMPORT_TYPE.USE_ARCGRIDRASTER;
- /**
- * Returns the default CRS used if no CRS can be found during import.
- */
- public static ARCASCII_IMPORT_TYPE getAsciiRasterImportMode() {
- return ARCASCII_IMPORT_MODE;
- }
+ /**
+ * Sets how this class proceeds the import of ASCII rasters.
+ *
+ * @param mode
+ * the mode how to proceed the import
+ */
+ public static void setAsciiRasterImportMode(ARCASCII_IMPORT_TYPE mode) {
+ ARCASCII_IMPORT_MODE = mode;
+ }
-
- ///////////////////////////////////////////////////////////////////////////
- // DEFAULT COORDINATE REFERENCE SYSTEM
- ///////////////////////////////////////////////////////////////////////////
+ /**
+ * Returns the default CRS used if no CRS can be found during import.
+ */
+ public static ARCASCII_IMPORT_TYPE getAsciiRasterImportMode() {
+ return ARCASCII_IMPORT_MODE;
+ }
+ // /////////////////////////////////////////////////////////////////////////
+ // DEFAULT COORDINATE REFERENCE SYSTEM
+ // /////////////////////////////////////////////////////////////////////////
+
/**
* Standard-CRS, welches verwendet wird, wenn beim Import kein CRS ermittelt
* werden kann (Default: {@link DefaultGeographicCRS#WGS84}).<br>
@@ -186,22 +200,24 @@
/**
* Sets the default CRS used if no CRS can be found during import.
- * @param crs the new default CRS
+ *
+ * @param crs
+ * the new default CRS
*/
public static void setDefaultCRS(CoordinateReferenceSystem crs) {
- DEFAULT_CRS = crs;
+ DEFAULT_CRS = crs;
}
- /**
- * Returns the default CRS used if no CRS can be found during import.
- */
+ /**
+ * Returns the default CRS used if no CRS can be found during import.
+ */
public static CoordinateReferenceSystem getDefaultCRS() {
- return DEFAULT_CRS;
+ return DEFAULT_CRS;
}
- ///////////////////////////////////////////////////////////////////////////
- // FEATURE IMPORT
- ///////////////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////////////
+ // FEATURE IMPORT
+ // /////////////////////////////////////////////////////////////////////////
/**
* Diese Methode extrahiert saemtliche Features aus einem ShapeFile-Projekt
* (<code><i>name</i>.shp <i>name</i>.prj <i>name</i>.dbf ...</code>) und
@@ -221,8 +237,8 @@
*
* @throws IOException
*/
- public static FeatureCollection<SimpleFeatureType, SimpleFeature> readFeaturesFromShapeURL(URL url, URL prjUrl)
- throws IOException {
+ public static FeatureCollection<SimpleFeatureType, SimpleFeature> readFeaturesFromShapeURL(
+ URL url, URL prjUrl) throws IOException {
ShapefileDataStore store = new ShapefileDataStore(url);
try {
// Testen, ob Projektion ermittelt werden kann, um vorab das
@@ -238,7 +254,8 @@
// store.forceSchemaCRS(DEFAULT_CRS);
}
String[] typeNames = store.getTypeNames();
- FeatureCollection<SimpleFeatureType, SimpleFeature> fc = store.getFeatureSource(typeNames[0]).getFeatures();
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fc = store
+ .getFeatureSource(typeNames[0]).getFeatures();
// Create a new DefaultFeatureCollection to allow modifying
// operations on the collection ("fc" is a DataFeatureCollection, whose
@@ -246,7 +263,8 @@
// FIDFeatureReader is used which returns copies of the features,
// so modifying the attributes does not effect the features
// in the collection!)
- FeatureCollection<SimpleFeatureType, SimpleFeature> fc1 = FeatureCollections.newCollection(fc.getID());
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fc1 = FeatureCollections
+ .newCollection(fc.getID());
fc1.addAll(fc);
fc = fc1;
@@ -271,8 +289,10 @@
* hiet auf readFeaturesFromShapeURL(file.getURL) umgeleitet werden
* (SK)
*/
- public static FeatureCollection<SimpleFeatureType, SimpleFeature> readFeaturesFromShapeFile(File file) throws Exception {
- ShapefileDataStore store = new ShapefileDataStore(DataUtilities.fileToURL(file));
+ public static FeatureCollection<SimpleFeatureType, SimpleFeature> readFeaturesFromShapeFile(
+ File file) throws Exception {
+ ShapefileDataStore store = new ShapefileDataStore(DataUtilities
+ .fileToURL(file));
File prjFile = IOUtil.changeFileExt(file, "prj");
boolean delPrjFile = false;
try {
@@ -291,7 +311,8 @@
delPrjFile = true; // von DataStore erzeugte Datei wieder loeschen
}
String[] typeNames = store.getTypeNames();
- FeatureCollection<SimpleFeatureType, SimpleFeature> fc = store.getFeatureSource(typeNames[0]).getFeatures();
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fc = store
+ .getFeatureSource(typeNames[0]).getFeatures();
if (delPrjFile)
prjFile.delete();
@@ -302,7 +323,8 @@
// is used which returns copies of the features, so modifying the
// attributes
// does not effect the features in the collection!)
- FeatureCollection<SimpleFeatureType, SimpleFeature> fc1 = FeatureCollections.newCollection(fc.getID());
+ FeatureCollection<SimpleFeatureType, SimpleFeature> fc1 = FeatureCollections
+ .newCollection(fc.getID());
fc1.addAll(fc);
fc = fc1;
@@ -311,19 +333,25 @@
/**
* Creates a {@link DataStore} from shape file
- * @param shpURL URL to shape file
- * @param prjURL URL to projection file
- * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons Krüger</a>
- * @throws IOException if an error occur
+ *
+ * @param shpURL
+ * URL to shape file
+ * @param prjURL
+ * URL to projection file
+ * @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
+ * Krüger</a>
+ * @throws IOException
+ * if an error occur
*/
- public static DataStore readDataStoreFromShape(URL shpURL, URL prjURL) throws IOException {
- Map<Object,Object> map = new HashMap<Object,Object>();
+ public static DataStore readDataStoreFromShape(URL shpURL, URL prjURL)
+ throws IOException {
+ Map<Object, Object> map = new HashMap<Object, Object>();
map.put("url", shpURL);
map.put("create spatial index", true);
// DataStore dataStore = DataStoreFinder.getDataStore( map );
- DataStore dataStore = new IndexedShapefileDataStore(
- shpURL, null, false, true, IndexType.QIX);
+ DataStore dataStore = new IndexedShapefileDataStore(shpURL, null,
+ false, true, IndexType.QIX);
// DataStore dataStore = new ShapefileDataStore(shpURL);
LOGGER.debug("DataStore = " + dataStore.getClass().toString());
IndexedShapefileDataStore dataStoreIndex = (IndexedShapefileDataStore) dataStore;
@@ -353,11 +381,11 @@
*/
public static Vector<Geometry> readGeometriesFromShapeFile(File file)
throws Exception {
-// FileChannel in = new FileInputStream(file).getChannel();
-// ShapefileReader r = new ShapefileReader(in, new Lock());
+ // FileChannel in = new FileInputStream(file).getChannel();
+ // ShapefileReader r = new ShapefileReader(in, new Lock());
ShapefileReader r = new ShapefileReader(new ShpFiles(file), true, false);
-
+
Vector<Geometry> geomList = new Vector<Geometry>();
for (int i = 1; r.hasNext(); i++) {
// org.geotools.renderer.geom.Geometry shape =
@@ -372,228 +400,259 @@
return geomList;
}
- ///////////////////////////////////////////////////////////////////////////
- // RASTER IMPORT (GridCoverage2D)
- ///////////////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////////////
+ // RASTER IMPORT (GridCoverage2D)
+ // /////////////////////////////////////////////////////////////////////////
- /**
- * Imports a raster from file or URL in
- * ArcInfoASCII format. The CRS is taken from prj-file (EPSG-Code
- * "EPSG:..." oder WKT-Definition). If not present the {@link #DEFAULT_CRS}
- * is used.
- * @param input file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
- */
- public static GridCoverage2D readGridFromArcInfoASCII(Object input) throws Exception {
- return readGridFromArcInfoASCII(input, null);
- }
+ /**
+ * Imports a raster from file or URL in ArcInfoASCII format. The CRS is
+ * taken from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not
+ * present the {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
+ */
+ public static GridCoverage2D readGridFromArcInfoASCII(Object input)
+ throws Exception {
+ return readGridFromArcInfoASCII(input, null);
+ }
- /**
- * Imports a raster from file or URL in
- * ArcInfoASCII format. The CRS is taken from prj-file (EPSG-Code
- * "EPSG:..." oder WKT-Definition). If not present the {@link #DEFAULT_CRS}
- * is used.
- * @param input file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
- */
- public static GridCoverage2D readGridFromArcInfoASCII(Object input, CoordinateReferenceSystem crs) throws Exception {
- switch( getAsciiRasterImportMode() ) {
- case USE_ARCGRIDREADER: return readGridFromArcInfoASCII_ArcGridReader(input, crs);
- case USE_ARCGRIDRASTER: return readGridFromArcInfoASCII_ArcGridRaster(input, crs);
- }
- throw new UnsupportedOperationException("ASCII raster import mode not supported: "+getAsciiRasterImportMode());
- }
-
- /**
- * Uses the <b>{@link ArcGridReader} class</b> (standard GT) to import a raster
- * from file or URL in ArcInfoASCII format. The CRS is taken from prj-file (EPSG-Code
- * "EPSG:..." oder WKT-Definition). If not present the {@link #DEFAULT_CRS}
- * is used.
- * @param input file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
- */
- private static GridCoverage2D readGridFromArcInfoASCII_ArcGridReader(Object input, CoordinateReferenceSystem crs) throws Exception {
- Hints hints = new Hints();
- if (crs != null) {
- hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, crs);
- }
- ArcGridReader reader = new ArcGridReader(input ,hints);
- GridCoverage2D gc = (GridCoverage2D) reader.read(null);
- return gc;
- }
-
- /**
- * Uses the <b>{@link ArcGridRaster} class</b> (standard GT) to import a raster
- * from file or URL in ArcInfoASCII format. The CRS is taken from prj-file (EPSG-Code
- * "EPSG:..." oder WKT-Definition). If not present the {@link #DEFAULT_CRS}
- * is used.
- * @param input file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
- */
- private static GridCoverage2D readGridFromArcInfoASCII_ArcGridRaster(Object input, CoordinateReferenceSystem crs) throws Exception {
- // Import raster data
- ArcGridRaster reader = null;
- if (input instanceof File)
- reader = new ArcGridRaster( new BufferedReader( new InputStreamReader( new FileInputStream((File)input) ) ), false );
- else if (input instanceof URL)
- reader = new ArcGridRaster( (URL)input );
- else
- throw new UnsupportedOperationException("Import source not supported: "+LangUtil.getSimpleClassName(input));
- WritableRaster raster = reader.readRaster();
-
- // Import CRS
- if (crs == null) {
- if (input instanceof File)
- crs = determineProjection((File)input);
- else if (input instanceof URL)
- crs = determineProjection((URL)input);
- }
-
-// LOGGER.debug("Position "+reader.getXlCorner()+" / "+reader.getYlCorner());
-// LOGGER.debug("Size "+reader.getNCols()+" / "+reader.getNRows());
-// LOGGER.debug("Min/Max "+reader.getMinValue()+" / "+reader.getMaxValue());
-// LOGGER.debug("NoData "+reader.getNoData());
-// LOGGER.debug("CellSize "+reader.getCellSize());
-
- float x = (float) reader.getXlCorner(); // SW corner!
- float y = (float) reader.getYlCorner(); // SW corner!
- // real width = colums * cell size
- float w = (float) (reader.getNCols() * reader.getCellSize());
- // real hight = rows * cell size
- float h = (float) (reader.getNRows() * reader.getCellSize());
- Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Float(x, y, w, h));
-
- // WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten
- // das Coloring des Rasters nicht klappt.
- // --> Name der Categories muss (warum auch immer) mit dem Namen
- // des Rasters uebereinstimmen!!!
- return new GridCoverageFactory().create("", raster, envelope);
- }
+ /**
+ * Imports a raster from file or URL in ArcInfoASCII format. The CRS is
+ * taken from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not
+ * present the {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
+ */
+ public static GridCoverage2D readGridFromArcInfoASCII(Object input,
+ CoordinateReferenceSystem crs) throws Exception {
+ switch (getAsciiRasterImportMode()) {
+ case USE_ARCGRIDREADER:
+ return readGridFromArcInfoASCII_ArcGridReader(input, crs);
+ case USE_ARCGRIDRASTER:
+ return readGridFromArcInfoASCII_ArcGridRaster(input, crs);
+ }
+ throw new UnsupportedOperationException(
+ "ASCII raster import mode not supported: "
+ + getAsciiRasterImportMode());
+ }
- // NOT USED ANYMORE: File and URL are handled by the same method using Object
-// /**
-// * Diese Methode importiert ein Raster aus einer Datei im
-// * ArcInfoASCII-Grid-Format. Das CRS wird aus einem prj-File (EPSG-Code
-// * "EPSG:..." oder WKT-Definition) gelesen. Ist dies nicht erfolgreich, wird
-// * {@link #DEFAULT_CRS} als CRS verwendet.
-// * @param file ASCII-File
-// * @throws java.lang.Exception bei irgendeinem Fehler
-// * @return {@link GridCoverage2D}
-// */
-// public static GridCoverage2D readGridFromArcInfoASCII(File file) throws Exception {
-// return readGridFromArcInfoASCII(file, null);
-// }
-//
-// /**
-// * Diese Methode importiert ein Raster aus einer Datei im
-// * ArcInfoASCII-Grid-Format. Wenn kein CRS angegeben wird, wird versucht das
-// * CRS aus einem prj-File (EPSG-Code "EPSG:..." oder WKT-Definition) zu
-// * lesen. Ist dies nicht erfolgreich, wird {@link #DEFAULT_CRS} als CRS
-// * verwendet.
-// * @param file ASCII-File
-// * @param crs CoordinateReferenceSystem fuer das Raster (kann {@code null} sein)
-// * @throws MalformedURLException if the file can not be converted to URL
-// * @throws Exception bei irgendeinem Fehler
-// */
-// public static GridCoverage2D readGridFromArcInfoASCII(File file, CoordinateReferenceSystem crs) throws MalformedURLException, Exception {
-// return readGridFromArcInfoASCII(file.toURI().toURL(), crs);
-// }
+ /**
+ * Uses the <b>{@link ArcGridReader} class</b> (standard GT) to import a
+ * raster from file or URL in ArcInfoASCII format. The CRS is taken from
+ * prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not present the
+ * {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
+ */
+ private static GridCoverage2D readGridFromArcInfoASCII_ArcGridReader(
+ Object input, CoordinateReferenceSystem crs) throws Exception {
+ Hints hints = new Hints();
+ if (crs != null) {
+ hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, crs);
+ }
+ ArcGridReader reader = new ArcGridReader(input, hints);
+ GridCoverage2D gc = (GridCoverage2D) reader.read(null);
+ return gc;
+ }
- /**
- * Diese Methode importiert ein Raster aus einer Datei im GeoTIFF-Format.
- *
- * @param file
- * GeoTIFF-File
- * @throws java.lang.Exception
- * bei irgendeinem Fehler
- * @see #readGridFromGeoTiff(File, CoordinateReferenceSystem)
- */
- public static GridCoverage2D readGridFromGeoTiff(File file) throws Exception {
- return readGridFromGeoTiff(file, null);
- }
+ /**
+ * Uses the <b>{@link ArcGridRaster} class</b> (standard GT) to import a
+ * raster from file or URL in ArcInfoASCII format. The CRS is taken from
+ * prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not present the
+ * {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
+ */
+ private static GridCoverage2D readGridFromArcInfoASCII_ArcGridRaster(
+ Object input, CoordinateReferenceSystem crs) throws Exception {
+ // Import raster data
+ ArcGridRaster reader = null;
+ if (input instanceof File)
+ reader = new ArcGridRaster(new BufferedReader(
+ new InputStreamReader(new FileInputStream((File) input))),
+ false);
+ else if (input instanceof URL)
+ reader = new ArcGridRaster((URL) input);
+ else
+ throw new UnsupportedOperationException(
+ "Import source not supported: "
+ + LangUtil.getSimpleClassName(input));
+ WritableRaster raster = reader.readRaster();
- /**
- * Diese Methode importiert ein Raster aus einer Datei im GeoTIFF-Format.
- *
- * @param file
- * GeoTIFF-File
- * @param crs
- * erzwungenes CoordinateReferenceSystem fuer das Raster (kann
- * {@code null} sein)
- * @throws java.lang.Exception
- * bei irgendeinem Fehler
- * @see #createGridReaderFromGeoTiff(File, CoordinateReferenceSystem)
- */
- public static GridCoverage2D readGridFromGeoTiff(File file, CoordinateReferenceSystem crs) throws Exception {
- // return (GridCoverage2D)createGridReaderFromGeoTiff(file, crs).read(null);
- GridCoverage2D gc = null;
- // Versuchen Geo-Information aus Tiff zu lesen
- try {
- Hints hints = new Hints();
+ // Import CRS
+ if (crs == null) {
+ if (input instanceof File)
+ crs = determineProjection((File) input);
+ else if (input instanceof URL)
+ crs = determineProjection((URL) input);
+ }
- // Wenn CRS angegeben, dieses durch Hint erzwingen
- if (crs != null)
- hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, crs);
- // Reader (mit Metadaten) erzeugen
- GeoTiffReader reader = new GeoTiffReader(file, hints);
- // Wenn kein Referenzsystem vorhanden, versuchen ein prj-File zu
- // verwenden
- if (reader.getOriginalEnvelope().getCoordinateReferenceSystem() == null) {
- LOGGER.warn("No projection information found in '"
- + file.getName() + "'. Using prj-file...");
- hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM,
- determineProjection(file));
- reader = new GeoTiffReader(file, hints);
- }
- gc = (GridCoverage2D) reader.read(null);
- return gc;
- } catch (UnsupportedOperationException err) {
- // erwartet, wenn keine Geo-Information im Tiff vorhanden ist
- // ExceptionMonitor.show(null, err,
- // "No geoinformation in TIFF, importing it as a normal file. Trying to read it as normal TIFF + Worldfile.");
- } catch (NullPointerException err) {
- // erwartet, wenn keine Geo-Information im Tiff vorhanden ist
- }
+ // LOGGER.debug("Position "+reader.getXlCorner()+" / "+reader.getYlCorner());
+ // LOGGER.debug("Size "+reader.getNCols()+" / "+reader.getNRows());
+ // LOGGER.debug("Min/Max "+reader.getMinValue()+" / "+reader.getMaxValue());
+ // LOGGER.debug("NoData "+reader.getNoData());
+ // LOGGER.debug("CellSize "+reader.getCellSize());
- // keine Geo-Informationen in Tiff
- // --> Raster ueber ImageIO einlesen und WorldFile/ProjectionFile
- // verwenden
- LOGGER.warn("No geo information found in '" + file.getName()
- + "'. Using world- and prj-file...");
- BufferedImage im = ImageIO.read(file);
- if (im == null)
- throw new IIOException("No image reader found for this image type!");
- // World-File einlesen
- File tfw = IOUtil.changeFileExt(file, "tfw");
- double[] tfwInfo = readWorldFile(tfw);
- float w = (float) (im.getWidth() * tfwInfo[0]); // reale Breite =
- // RasterSpalten * hor.
- // Aufloesung
- float h = (float) (im.getHeight() * (-tfwInfo[3])); // reale Hoehe =
- // RasterZeilen *
- // vert. Aufloesung
- float x = (float) tfwInfo[4]; // Suedwestliche Ecke!
- float y = (float) tfwInfo[5] - h; // Suedwestliche Ecke (im tfw-File
- // steht die Nordwestliche!)
- // ggf. Projektion einlesen
- if (crs == null)
- crs = determineProjection(file);
- Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Float(x, y,
- w, h));
- // WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten das
- // Coloring des Rasters nicht klappt.
- // --> Name der Categories muss (warum auch immer) mit dem Namen
- // des Rasters uebereinstimmen!!!
- gc = new GridCoverageFactory().create("", im.copyData(null), envelope);
- return gc;
- }
+ float x = (float) reader.getXlCorner(); // SW corner!
+ float y = (float) reader.getYlCorner(); // SW corner!
+ // real width = colums * cell size
+ float w = (float) (reader.getNCols() * reader.getCellSize());
+ // real hight = rows * cell size
+ float h = (float) (reader.getNRows() * reader.getCellSize());
+ Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Float(x, y,
+ w, h));
-
- ///////////////////////////////////////////////////////////////////////////
- // RASTER IMPORT (AbstractGridCoverage2DReader)
- ///////////////////////////////////////////////////////////////////////////
-
+ // WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten
+ // das Coloring des Rasters nicht klappt.
+ // --> Name der Categories muss (warum auch immer) mit dem Namen
+ // des Rasters uebereinstimmen!!!
+ return new GridCoverageFactory().create("", raster, envelope);
+ }
+
+ // NOT USED ANYMORE: File and URL are handled by the same method using
+ // Object
+ // /**
+ // * Diese Methode importiert ein Raster aus einer Datei im
+ // * ArcInfoASCII-Grid-Format. Das CRS wird aus einem prj-File (EPSG-Code
+ // * "EPSG:..." oder WKT-Definition) gelesen. Ist dies nicht erfolgreich,
+ // wird
+ // * {@link #DEFAULT_CRS} als CRS verwendet.
+ // * @param file ASCII-File
+ // * @throws java.lang.Exception bei irgendeinem Fehler
+ // * @return {@link GridCoverage2D}
+ // */
+ // public static GridCoverage2D readGridFromArcInfoASCII(File file) throws
+ // Exception {
+ // return readGridFromArcInfoASCII(file, null);
+ // }
+ //
+ // /**
+ // * Diese Methode importiert ein Raster aus einer Datei im
+ // * ArcInfoASCII-Grid-Format. Wenn kein CRS angegeben wird, wird versucht
+ // das
+ // * CRS aus einem prj-File (EPSG-Code "EPSG:..." oder WKT-Definition) zu
+ // * lesen. Ist dies nicht erfolgreich, wird {@link #DEFAULT_CRS} als CRS
+ // * verwendet.
+ // * @param file ASCII-File
+ // * @param crs CoordinateReferenceSystem fuer das Raster (kann {@code null}
+ // sein)
+ // * @throws MalformedURLException if the file can not be converted to URL
+ // * @throws Exception bei irgendeinem Fehler
+ // */
+ // public static GridCoverage2D readGridFromArcInfoASCII(File file,
+ // CoordinateReferenceSystem crs) throws MalformedURLException, Exception {
+ // return readGridFromArcInfoASCII(file.toURI().toURL(), crs);
+ // }
+
/**
+ * Diese Methode importiert ein Raster aus einer Datei im GeoTIFF-Format.
+ *
+ * @param file
+ * GeoTIFF-File
+ * @throws java.lang.Exception
+ * bei irgendeinem Fehler
+ * @see #readGridFromGeoTiff(File, CoordinateReferenceSystem)
+ */
+ public static GridCoverage2D readGridFromGeoTiff(File file)
+ throws Exception {
+ return readGridFromGeoTiff(file, null);
+ }
+
+ /**
+ * Diese Methode importiert ein Raster aus einer Datei im GeoTIFF-Format.
+ *
+ * @param file
+ * GeoTIFF-File
+ * @param crs
+ * erzwungenes CoordinateReferenceSystem fuer das Raster (kann
+ * {@code null} sein)
+ * @throws java.lang.Exception
+ * bei irgendeinem Fehler
+ * @see #createGridReaderFromGeoTiff(File, CoordinateReferenceSystem)
+ */
+ public static GridCoverage2D readGridFromGeoTiff(File file,
+ CoordinateReferenceSystem crs) throws Exception {
+ // return (GridCoverage2D)createGridReaderFromGeoTiff(file,
+ // crs).read(null);
+ GridCoverage2D gc = null;
+ // Versuchen Geo-Information aus Tiff zu lesen
+ try {
+ Hints hints = new Hints();
+
+ // Wenn CRS angegeben, dieses durch Hint erzwingen
+ if (crs != null)
+ hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, crs);
+ // Reader (mit Metadaten) erzeugen
+ GeoTiffReader reader = new GeoTiffReader(file, hints);
+ // Wenn kein Referenzsystem vorhanden, versuchen ein prj-File zu
+ // verwenden
+ if (reader.getOriginalEnvelope().getCoordinateReferenceSystem() == null) {
+ LOGGER.warn("No projection information found in '"
+ + file.getName() + "'. Using prj-file...");
+ hints.put(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM,
+ determineProjection(file));
+ reader = new GeoTiffReader(file, hints);
+ }
+ gc = (GridCoverage2D) reader.read(null);
+ return gc;
+ } catch (UnsupportedOperationException err) {
+ // erwartet, wenn keine Geo-Information im Tiff vorhanden ist
+ // ExceptionMonitor.show(null, err,
+ // "No geoinformation in TIFF, importing it as a normal file. Trying to read it as normal TIFF + Worldfile.");
+ } catch (NullPointerException err) {
+ // erwartet, wenn keine Geo-Information im Tiff vorhanden ist
+ }
+
+ // keine Geo-Informationen in Tiff
+ // --> Raster ueber ImageIO einlesen und WorldFile/ProjectionFile
+ // verwenden
+ LOGGER.warn("No geo information found in '" + file.getName()
+ + "'. Using world- and prj-file...");
+ BufferedImage im = ImageIO.read(file);
+ if (im == null)
+ throw new IIOException("No image reader found for this image type!");
+ // World-File einlesen
+ File tfw = IOUtil.changeFileExt(file, "tfw");
+ double[] tfwInfo = readWorldFile(tfw);
+ float w = (float) (im.getWidth() * tfwInfo[0]); // reale Breite =
+ // RasterSpalten * hor.
+ // Aufloesung
+ float h = (float) (im.getHeight() * (-tfwInfo[3])); // reale Hoehe =
+ // RasterZeilen *
+ // vert. Aufloesung
+ float x = (float) tfwInfo[4]; // Suedwestliche Ecke!
+ float y = (float) tfwInfo[5] - h; // Suedwestliche Ecke (im tfw-File
+ // steht die Nordwestliche!)
+ // ggf. Projektion einlesen
+ if (crs == null)
+ crs = determineProjection(file);
+ Envelope2D envelope = new Envelope2D(crs, new Rectangle2D.Float(x, y,
+ w, h));
+ // WICHTIG: Name des Rasters sollte Leer-String sein, da ansonsten das
+ // Coloring des Rasters nicht klappt.
+ // --> Name der Categories muss (warum auch immer) mit dem Namen
+ // des Rasters uebereinstimmen!!!
+ gc = new GridCoverageFactory().create("", im.copyData(null), envelope);
+ return gc;
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ // RASTER IMPORT (AbstractGridCoverage2DReader)
+ // /////////////////////////////////////////////////////////////////////////
+
+ /**
* Diese Methode erzeugt einen {@link AbstractGridCoverage2DReader} aus
* einer Datei im GeoTIFF-Format. Zunaechst wird versucht, die
* Geo-Informationen (Referenz+CRS) aus den TIFF-Metadaten zu ermitteln. Ist
@@ -669,94 +728,117 @@
return createGridReaderFromGeoTiff(file, null);
}
- ///////////////////////////////////////////////////////////////////////////
- // RASTER IMPORT (WritableGridRaster)
- ///////////////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////////////
+ // RASTER IMPORT (WritableGridRaster)
+ // /////////////////////////////////////////////////////////////////////////
- /**
- * Import a raster from file or URL in ArcInfoASCII format.
- * The CRS is taken from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition).
- * If not present the {@link #DEFAULT_CRS} is used.
- * @param input ASCII file or URL to the input file
- */
- public static WritableGridRaster readGridRasterFromArcInfoASCII(Object input) throws Exception {
- return readGridRasterFromArcInfoASCII(input, null);
+ /**
+ * Import a raster from file or URL in ArcInfoASCII format. The CRS is taken
+ * from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not present
+ * the {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * ASCII file or URL to the input file
+ */
+ public static WritableGridRaster readGridRasterFromArcInfoASCII(Object input)
+ throws Exception {
+ return readGridRasterFromArcInfoASCII(input, null);
}
- /**
- * Import a raster from file or URL in ArcInfoASCII format.
- * The CRS is taken from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition).
- * If not present the {@link #DEFAULT_CRS} is used.
- * @param input ASCII file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
+ /**
+ * Import a raster from file or URL in ArcInfoASCII format. The CRS is taken
+ * from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not present
+ * the {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * ASCII file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
*/
- public static WritableGridRaster readGridRasterFromArcInfoASCII(Object input, CoordinateReferenceSystem crs) throws Exception {
- switch( getAsciiRasterImportMode() ) {
- case USE_ARCGRIDREADER: return readGridRasterFromArcInfoASCII_ArcGridReader(input, crs);
- case USE_ARCGRIDRASTER: return readGridRasterFromArcInfoASCII_ArcGridRaster(input, crs);
- }
- throw new UnsupportedOperationException("ASCII raster import mode not supported: "+getAsciiRasterImportMode());
+ public static WritableGridRaster readGridRasterFromArcInfoASCII(
+ Object input, CoordinateReferenceSystem crs) throws Exception {
+ switch (getAsciiRasterImportMode()) {
+ case USE_ARCGRIDREADER:
+ return readGridRasterFromArcInfoASCII_ArcGridReader(input, crs);
+ case USE_ARCGRIDRASTER:
+ return readGridRasterFromArcInfoASCII_ArcGridRaster(input, crs);
+ }
+ throw new UnsupportedOperationException(
+ "ASCII raster import mode not supported: "
+ + getAsciiRasterImportMode());
}
- /**
- * Uses the <b>{@link ArcGridReader} class</b> (standard GT) to
- * import a raster from file or URL in ArcInfoASCII format.
- * The CRS is taken from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition).
- * If not present the {@link #DEFAULT_CRS} is used.
- * @param input file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
- */
- private static WritableGridRaster readGridRasterFromArcInfoASCII_ArcGridReader(Object input, CoordinateReferenceSystem crs) throws Exception {
- GridCoverage2D grid = readGridFromArcInfoASCII(input, crs);
- WritableRaster raster = grid.getRenderedImage().copyData(null);
- return new WritableGridRaster(raster,grid.getEnvelope2D()) ;
- }
-
- /**
- * Uses the <b>{@link ArcGridRaster} class</b> (standard GT) to
- * import a raster from file or URL in ArcInfoASCII format.
- * The CRS is taken from prj-file (EPSG-Code "EPSG:..." oder WKT-Definition).
- * If not present the {@link #DEFAULT_CRS} is used.
- * @param input file or URL to the input file
- * @param crs CRS forced to use (can be <code>null</code>)
- */
- private static WritableGridRaster readGridRasterFromArcInfoASCII_ArcGridRaster(Object input, CoordinateReferenceSystem crs) throws Exception {
- // Import raster data
- ArcGridRaster reader = null;
- if (input instanceof File)
- reader = new ArcGridRaster( new BufferedReader( new InputStreamReader( new FileInputStream((File)input) ) ), false );
- else if (input instanceof URL)
- reader = new ArcGridRaster( (URL)input );
- else
- throw new UnsupportedOperationException("Import source not supported: "+LangUtil.getSimpleClassName(input));
- WritableRaster raster = reader.readRaster();
-
- // Import CRS
- if (crs == null) {
- if (input instanceof File)
- crs = determineProjection((File)input);
- else if (input instanceof URL)
- crs = determineProjection((URL)input);
- }
-
-// LOGGER.debug("Position "+reader.getXlCorner()+" / "+reader.getYlCorner());
-// LOGGER.debug("Size "+reader.getNCols()+" / "+reader.getNRows());
-// LOGGER.debug("Min/Max "+reader.getMinValue()+" / "+reader.getMaxValue());
-// LOGGER.debug("NoData "+reader.getNoData());
-// LOGGER.debug("CellSize "+reader.getCellSize());
-
- float x = (float) reader.getXlCorner(); // SW corner!
- float y = (float) reader.getYlCorner(); // SW corner!
- // real width = colums * cell size
- float w = (float) (reader.getNCols() * reader.getCellSize());
- // real hight = rows * cell size
- float h = (float) (reader.getNRows() * reader.getCellSize());
- Rectangle2D envelope = new Rectangle2D.Float(x, y, w, h);
+ /**
+ * Uses the <b>{@link ArcGridReader} class</b> (standard GT) to import a
+ * raster from file or URL in ArcInfoASCII format. The CRS is taken from
+ * prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not present the
+ * {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
+ */
+ private static WritableGridRaster readGridRasterFromArcInfoASCII_ArcGridReader(
+ Object input, CoordinateReferenceSystem crs) throws Exception {
+ GridCoverage2D grid = readGridFromArcInfoASCII(input, crs);
+ WritableRaster raster = grid.getRenderedImage().copyData(null);
+ return new WritableGridRaster(raster, grid.getEnvelope2D());
+ }
- return new WritableGridRaster(raster, envelope, crs);
- }
-
/**
+ * Uses the <b>{@link ArcGridRaster} class</b> (standard GT) to import a
+ * raster from file or URL in ArcInfoASCII format. The CRS is taken from
+ * prj-file (EPSG-Code "EPSG:..." oder WKT-Definition). If not present the
+ * {@link #DEFAULT_CRS} is used.
+ *
+ * @param input
+ * file or URL to the input file
+ * @param crs
+ * CRS forced to use (can be <code>null</code>)
+ */
+ private static WritableGridRaster readGridRasterFromArcInfoASCII_ArcGridRaster(
+ Object input, CoordinateReferenceSystem crs) throws Exception {
+ // Import raster data
+ ArcGridRaster reader = null;
+ if (input instanceof File)
+ reader = new ArcGridRaster(new BufferedReader(
+ new InputStreamReader(new FileInputStream((File) input))),
+ false);
+ else if (input instanceof URL)
+ reader = new ArcGridRaster((URL) input);
+ else
+ throw new UnsupportedOperationException(
+ "Import source not supported: "
+ + LangUtil.getSimpleClassName(input));
+ WritableRaster raster = reader.readRaster();
+
+ // Import CRS
+ if (crs == null) {
+ if (input instanceof File)
+ crs = determineProjection((File) input);
+ else if (input instanceof URL)
+ crs = determineProjection((URL) input);
+ }
+
+ // LOGGER.debug("Position "+reader.getXlCorner()+" / "+reader.getYlCorner());
+ // LOGGER.debug("Size "+reader.getNCols()+" / "+reader.getNRows());
+ // LOGGER.debug("Min/Max "+reader.getMinValue()+" / "+reader.getMaxValue());
+ // LOGGER.debug("NoData "+reader.getNoData());
+ // LOGGER.debug("CellSize "+reader.getCellSize());
+
+ float x = (float) reader.getXlCorner(); // SW corner!
+ float y = (float) reader.getYlCorner(); // SW corner!
+ // real width = colums * cell size
+ float w = (float) (reader.getNCols() * reader.getCellSize());
+ // real hight = rows * cell size
+ float h = (float) (reader.getNRows() * reader.getCellSize());
+ Rectangle2D envelope = new Rectangle2D.Float(x, y, w, h);
+
+ return new WritableGridRaster(raster, envelope, crs);
+ }
+
+ /**
* Diese Methode importiert ein Raster aus einer Datei im GeoTIFF-Format.
* Zunaechst wird versucht, die Geo-Informationen (Referenz+CRS) aus den
* TIFF-Metadaten zu ermitteln. Ist dies nicht erfolgreich, werden ein
@@ -770,7 +852,8 @@
* @throws java.lang.Exception
* bei irgendeinem Fehler
*/
- public static WritableGridRaster readGridRasterFromGeoTiff(File file) throws Exception {
+ public static WritableGridRaster readGridRasterFromGeoTiff(File file)
+ throws Exception {
return readGridRasterFromGeoTiff(file, null);
}
@@ -783,12 +866,16 @@
* WKT-Definition erlaubt. Kann kein CRS ermitteln werden, wird
* {@link #DEFAULT_CRS} als CRS verwendet.
*
- * @param file GeoTIFF-File
- * @param crs erzwungenes CoordinateReferenceSystem fuer das Raster (kann
+ * @param file
+ * GeoTIFF-File
+ * @param crs
+ * erzwungenes CoordinateReferenceSystem fuer das Raster (kann
* {@code null} sein)
- * @throws java.lang.Exception bei irgendeinem Fehler
+ * @throws java.lang.Exception
+ * bei irgendeinem Fehler
*/
- public static WritableGridRaster readGridRasterFromGeoTiff(File file, CoordinateReferenceSystem crs) throws Exception {
+ public static WritableGridRaster readGridRasterFromGeoTiff(File file,
+ CoordinateReferenceSystem crs) throws Exception {
// // GeoTiff-File einlesen
// BufferedImage im = ImageIO.read( file );
// if ( im == null )
@@ -820,24 +907,20 @@
// );
//
- GridCoverage2D gc = readGridFromGeoTiff(file, crs);
- Rectangle2D env = gc.getEnvelope2D();
- RenderedImage im = gc.getRenderedImage();
- WritableGridRaster raster = new WritableGridRaster(
- im.getData().getDataBuffer().getDataType(),
- 0, 0,
- im.getWidth(), im.getHeight(),
- env,
- crs
- );
+ GridCoverage2D gc = readGridFromGeoTiff(file, crs);
+ Rectangle2D env = gc.getEnvelope2D();
+ RenderedImage im = gc.getRenderedImage();
+ WritableGridRaster raster = new WritableGridRaster(im.getData()
+ .getDataBuffer().getDataType(), 0, 0, im.getWidth(), im
+ .getHeight(), env, crs);
im.copyData(raster);
return raster;
}
- ///////////////////////////////////////////////////////////////////////////
- // META DATA IMPORT (WORLD FILE)
- ///////////////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////////////
+ // META DATA IMPORT (WORLD FILE)
+ // /////////////////////////////////////////////////////////////////////////
/**
* Liest ein World-File (.tfw) ein und liefert die darin zeilenweise
* gespeicherten Werte zurueck. Leer- und Kommentarzeilen werden dabei
@@ -939,9 +1022,9 @@
return ret;
}
- ///////////////////////////////////////////////////////////////////////////
- // META DATA IMPORT (PROJECTION)
- ///////////////////////////////////////////////////////////////////////////
+ // /////////////////////////////////////////////////////////////////////////
+ // META DATA IMPORT (PROJECTION)
+ // /////////////////////////////////////////////////////////////////////////
/**
* Liest das CRS aus einer Datei. Zunaechst wird versucht das CRS aus der
@@ -952,8 +1035,9 @@
* Datei
* @return {@code null}, wenn kein CRS gelesen werden konnte
*/
- public static CoordinateReferenceSystem determineProjection(File file) throws IOException {
- return determineProjection(DataUtilities.fileToURL(file));
+ public static CoordinateReferenceSystem determineProjection(File file)
+ throws IOException {
+ return determineProjection(DataUtilities.fileToURL(file));
}
/**
@@ -967,24 +1051,26 @@
public static CoordinateReferenceSystem determineProjection(URL prjUrl) {
CoordinateReferenceSystem crs = null;
// Versuchen CRS aus angegebener Datei zu lesen
- LOGGER.debug("determineProjection: Try to read a projection from URL " + prjUrl);
+ LOGGER.debug("determineProjection: Try to read a projection from URL "
+ + prjUrl);
try {
crs = GeoImportUtil.readProjectionFile(prjUrl);
} catch (IOException e) {
}
if (crs == null) {
- try {
- crs = GeoImportUtil.readProjectionFile(IOUtil.changeUrlExt(prjUrl, "prj"));
- } catch (IllegalArgumentException e) {
- } catch (IOException e) {
- }
+ try {
+ crs = GeoImportUtil.readProjectionFile(IOUtil.changeUrlExt(
+ prjUrl, "prj"));
+ } catch (IllegalArgumentException e) {
+ } catch (IOException e) {
+ }
}
// Wenn nicht erfolgreich, Default verwenden
if (crs == null) {
- LOGGER.warn("No projection found in URL. Default CRS used.");
- crs = getDefaultCRS();
+ LOGGER.warn("No projection found in URL. Default CRS used.");
+ crs = getDefaultCRS();
}
return crs;
}
@@ -1005,10 +1091,11 @@
* @throws IOException
* falls die URL nicht wie erwartet gelesen werden konnte.
*/
- public static CoordinateReferenceSystem readProjectionFile(URL prjURL) throws IOException {
- String crsDefinition = readProjectionString(prjURL);
- CoordinateReferenceSystem crs = GTUtil.createCRS(crsDefinition);
- return crs;
+ public static CoordinateReferenceSystem readProjectionFile(URL prjURL)
+ throws IOException {
+ String crsDefinition = readProjectionString(prjURL);
+ CoordinateReferenceSystem crs = GTUtil.createCRS(crsDefinition);
+ return crs;
}
/**
@@ -1023,7 +1110,8 @@
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a>
* (University of Bonn/Germany)
*/
- public static CoordinateReferenceSystem readProjectionFile(File prjFile) throws IOException {
+ public static CoordinateReferenceSystem readProjectionFile(File prjFile)
+ throws IOException {
String crsDefinition = readProjectionString(prjFile);
CoordinateReferenceSystem crs = GTUtil.createCRS(crsDefinition);
// if ( crs == null )
@@ -1084,29 +1172,37 @@
*/
public static String readProjectionString(URL url) throws IOException {
if (url == null) {
- LOGGER.debug("readProjectionString returned empty String for url==null");
+ LOGGER
+ .debug("readProjectionString returned empty String for url==null");
return "";
}
- BufferedReader input = new BufferedReader(new InputStreamReader(url.openStream()));
+ final InputStream openStream = url.openStream();
try {
- // Alle Zeilen der Datei aneinander haengen
- StringBuffer buffer = new StringBuffer();
- String line = null;
- while (input.ready() && (line = input.readLine()) != null) {
- if (!IOUtil.isCommentLine(line))
- buffer.append(" ").append(line);
- if (buffer.length() > 3000) {
- // LOGGER.warn("The URL " + url +
- // " doesn't seem point to a .prj file, because size is > 3000 characters. Returning \"\"");
- return "";
+
+ BufferedReader input = new BufferedReader(new InputStreamReader(
+ openStream));
+ try {
+ // Alle Zeilen der Datei aneinander haengen
+ StringBuffer buffer = new StringBuffer();
+ String line = null;
+ while (input.ready() && (line = input.readLine()) != null) {
+ if (!IOUtil.isCommentLine(line))
+ buffer.append(" ").append(line);
+ if (buffer.length() > 3000) {
+ // LOGGER.warn("The URL " + url +
+ // " doesn't seem point to a .prj file, because size is > 3000 characters. Returning \"\"");
+ return "";
+ }
}
+ final String prjString = buffer.toString().trim();
+ // LOGGER.debug("This is the PRJ String from URL = \n"+prjString);
+ return prjString;
+ } finally {
+ input.close();
}
- final String prjString = buffer.toString().trim();
- // LOGGER.debug("This is the PRJ String from URL = \n"+prjString);
- return prjString;
} finally {
- input.close();
+ openStream.close();
}
}
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/FeatureSelectedEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/FeatureSelectedEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/FeatureSelectedEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,15 +29,17 @@
******************************************************************************/
package schmitzm.geotools.map.event;
+import gtmig.org.geotools.swing.XMapPane;
+
import org.geotools.feature.FeatureCollection;
import org.geotools.map.MapLayer;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import com.vividsolutions.jts.geom.Envelope;
/**
- * Diese Klasse stellt ein Ereignis dar, das ein {@link JMapPane} ausloest,
+ * Diese Klasse stellt ein Ereignis dar, das ein {@link XMapPane} ausloest,
* wenn der Anwender Features in der Karte ausgewaehlt hat.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
@@ -52,7 +54,7 @@
* @param sourceObject Objekt, das die Selektion initiiert hat (wenn {@code null},
* wird das MapPane als Ausloeser gesetzt)
*/
- public FeatureSelectedEvent(JMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, FeatureCollection result, Object sourceObject) {
+ public FeatureSelectedEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, FeatureCollection result, Object sourceObject) {
super(sourceMap, sourceLayer, envelope, result, sourceObject);
}
@@ -63,7 +65,7 @@
* @param envelope Bereich der selektiert wurde
* @param result selektierte Features
*/
- public FeatureSelectedEvent(JMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, FeatureCollection result) {
+ public FeatureSelectedEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, FeatureCollection result) {
this(sourceMap, sourceLayer, envelope, result,null);
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GeneralSelectionEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GeneralSelectionEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GeneralSelectionEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,18 +29,19 @@
******************************************************************************/
package schmitzm.geotools.map.event;
-import schmitzm.geotools.gui.JMapPane;
+import gtmig.org.geotools.swing.XMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import com.vividsolutions.jts.geom.Envelope;
/**
- * Diese Klasse stellt ein Ereignis dar, das ein {@link JMapPane} ausloest,
+ * Diese Klasse stellt ein Ereignis dar, das ein {@link SelectableXMapPane} ausloest,
* wenn der Anwender (irgendeinen) einen Bereich in der Karte ausgewaehlt hat,
* auch wenn dort keine Objekte selektiert wurden.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
-public class GeneralSelectionEvent extends JMapPaneEvent {
+public class GeneralSelectionEvent extends MapPaneEvent {
/** Bereich der selektiert wurde. */
protected Envelope envelope = null;
@@ -51,7 +52,7 @@
* @param sourceObject Objekt, das die Selektion initiiert hat (wenn {@code null},
* wird das MapPane als Ausloeser gesetzt)
*/
- public GeneralSelectionEvent(JMapPane source, Envelope envelope, Object sourceObject) {
+ public GeneralSelectionEvent(SelectableXMapPane source, Envelope envelope, Object sourceObject) {
super(source, sourceObject);
this.envelope = envelope;
}
@@ -61,7 +62,7 @@
* @param sourceMap Karte in der die Selektion vorgenommen wurde
* @param envelope Bereich der selektiert wurde
*/
- public GeneralSelectionEvent(JMapPane sourceMap, Envelope envelope) {
+ public GeneralSelectionEvent(SelectableXMapPane sourceMap, Envelope envelope) {
this(sourceMap,envelope,null);
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageSelectedEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageSelectedEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageSelectedEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,15 +29,17 @@
******************************************************************************/
package schmitzm.geotools.map.event;
+import gtmig.org.geotools.swing.XMapPane;
+
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.map.MapLayer;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import com.vividsolutions.jts.geom.Envelope;
/**
- * Diese Klasse stellt ein Ereignis dar, das ein {@link JMapPane} ausloest,
+ * Diese Klasse stellt ein Ereignis dar, das ein {@link XMapPane} ausloest,
* wenn der Anwender ein Raster in der Karte ausgewaehlt hat.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
@@ -53,7 +55,7 @@
* @param sourceObject Objekt, das die Selektion initiiert hat (wenn {@code null},
* wird das MapPane als Ausloeser gesetzt)
*/
- public GridCoverageSelectedEvent(JMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, GridCoverage2D result, Object sourceObject) {
+ public GridCoverageSelectedEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, GridCoverage2D result, Object sourceObject) {
super(sourceMap,sourceLayer,envelope,result,sourceObject);
}
@@ -64,7 +66,7 @@
* @param envelope Bereich der selektiert wurde
* @param result selektierters Teil-Raster
*/
- public GridCoverageSelectedEvent(JMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, GridCoverage2D result) {
+ public GridCoverageSelectedEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, GridCoverage2D result) {
this(sourceMap,sourceLayer,envelope,result,null);
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageValueSelectedEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageValueSelectedEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/GridCoverageValueSelectedEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -33,12 +33,12 @@
import org.geotools.map.MapLayer;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import com.vividsolutions.jts.geom.Envelope;
/**
- * Diese Klasse stellt ein Ereignis dar, das ein {@link JMapPane} ausloest,
+ * Diese Klasse stellt ein Ereignis dar, das ein {@link SelectableXMapPane} ausloest,
* wenn der Anwender den Wert eines Rasters in der Karte ausgewaehlt hat.
*
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
@@ -68,7 +68,7 @@
* @param sourceObject Objekt, das die Selektion initiiert hat (wenn {@code null},
* wird das MapPane als Ausloeser gesetzt)
*/
- public GridCoverageValueSelectedEvent(JMapPane sourceMap, MapLayer sourceLayer, Point2D point, double[] result, Object sourceObject) {
+ public GridCoverageValueSelectedEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Point2D point, double[] result, Object sourceObject) {
super(sourceMap,sourceLayer,new Envelope(point.getX(),point.getX(),point.getY(),point.getY()),result, sourceObject);
this.point = point;
}
@@ -80,7 +80,7 @@
* @param point Punkt der selektiert wurde
* @param result selektierters Teil-Raster
*/
- public GridCoverageValueSelectedEvent(JMapPane sourceMap, MapLayer sourceLayer, Point2D point, double[] result) {
+ public GridCoverageValueSelectedEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Point2D point, double[] result) {
this(sourceMap,sourceLayer,point,result,null);
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JEditorPaneEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JEditorPaneEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JEditorPaneEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -40,7 +40,7 @@
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
-public abstract class JEditorPaneEvent extends JMapPaneEvent {
+public abstract class JEditorPaneEvent extends MapPaneEvent {
/** Das bearbeitete Layer. */
protected MapLayer layer = null;
/** Bearbeitungs-Modus (zum Zeitpunkt des Events) */
Deleted: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -1,78 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Martin O. J. Schmitz.
- *
- * This file is part of the SCHMITZM library - a collection of utility
- * classes based on Java 1.6, focusing (not only) on Java Swing
- * and the Geotools library.
- *
- * The SCHMITZM project is hosted at:
- * http://wald.intevation.org/projects/schmitzm/
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License (license.txt)
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * or try this link: http://www.gnu.org/licenses/lgpl.html
- *
- * Contributors:
- * Martin O. J. Schmitz - initial API and implementation
- * Stefan A. Krüger - additional utility classes
- ******************************************************************************/
-package schmitzm.geotools.map.event;
-
-import schmitzm.geotools.gui.JMapPane;
-
-/**
- * Diese Klasse stellt ein Ereignis dar, das von einem {@link JMapPane}
- * ausgeloest wurde (z.B. Aenderung der Aufloesung).
- * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
- * @version 1.0
- */
-public abstract class JMapPaneEvent {
- /** Beinhaltet das {@link JMapPane}, das das Ereignis ausgeloest hat */
- protected JMapPane source = null;
- /** Beinhaltet ein Objekt, das das Ereignis initiiert hat */
- protected Object sourceObject = null;
-
- /**
- * Erzeugt ein neues Ereignis.
- * @param source {@link JMapPane}, das das Ereignis ausgeloest hat
- * @param sourceObject Objeckt, das das Ereignis initiiert hat (wenn {@code null},
- * wird das MapPane als Ausloeser gesetzt)
- */
- public JMapPaneEvent(JMapPane source, Object sourceObject) {
- this.source = source;
- this.sourceObject = (sourceObject != null) ? sourceObject : source;
- }
-
- /**
- * Erzeugt ein neues Ereignis.
- * @param source {@link JMapPane}, das das Ereignis ausgeloest hat
- */
- public JMapPaneEvent(JMapPane source) {
- this(source,null);
- }
-
- /**
- * Liefert das {@link JMapPane}, das das Ereignis ausgeloest hat.
- */
- public JMapPane getSource() {
- return source;
- }
-
- /**
- * Liefert das Object, das das Ereignis initiiert hat.
- */
- public Object getSourceObject() {
- return sourceObject;
- }
-}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneListener.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneListener.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneListener.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -30,12 +30,12 @@
package schmitzm.geotools.map.event;
// fuer Doku
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
/**
- * Diese Klasse stellt einen Listener fuer Ereignisse des {@link JMapPane}
+ * Diese Klasse stellt einen Listener fuer Ereignisse des {@link SelectableXMapPane}
* dar (z.B. Aenderung der Aufloesung).
- * @see JMapPaneEvent
+ * @see MapPaneEvent
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
@@ -44,5 +44,5 @@
* Verarbeitet ein JMapPane-Ereignis.
* @param e Ereignis
*/
- public void performMapPaneEvent(JMapPaneEvent e);
+ public void performMapPaneEvent(MapPaneEvent e);
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapAreaChangedEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapAreaChangedEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapAreaChangedEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,17 +29,17 @@
******************************************************************************/
package schmitzm.geotools.map.event;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import com.vividsolutions.jts.geom.Envelope;
/**
- * Diese Klasse stellt ein Ereignis dar, das ein {@link JMapPane} ausloest,
+ * Diese Klasse stellt ein Ereignis dar, das ein {@link SelectableXMapPane} ausloest,
* wenn sich die Ausdehnung der dargestellte Karten-Ausschnitt aendert.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
-public class MapAreaChangedEvent extends JMapPaneEvent {
+public class MapAreaChangedEvent extends MapPaneEvent {
private Envelope oldEnvelope = null;
private Envelope newEnvelope = null;
@@ -48,7 +48,7 @@
* @param oldEnvelope vormalige Ausdehnung
* @param newEnvelope neue Ausdehnung
*/
- public MapAreaChangedEvent(JMapPane source, Envelope oldEnvelope, Envelope newEnvelope) {
+ public MapAreaChangedEvent(SelectableXMapPane source, Envelope oldEnvelope, Envelope newEnvelope) {
super(source);
this.oldEnvelope = oldEnvelope;
this.newEnvelope = newEnvelope;
Copied: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapPaneEvent.java (from rev 505, branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneEvent.java)
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/JMapPaneEvent.java 2009-10-31 10:53:43 UTC (rev 505)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/MapPaneEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Martin O. J. Schmitz.
+ *
+ * This file is part of the SCHMITZM library - a collection of utility
+ * classes based on Java 1.6, focusing (not only) on Java Swing
+ * and the Geotools library.
+ *
+ * The SCHMITZM project is hosted at:
+ * http://wald.intevation.org/projects/schmitzm/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License (license.txt)
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * or try this link: http://www.gnu.org/licenses/lgpl.html
+ *
+ * Contributors:
+ * Martin O. J. Schmitz - initial API and implementation
+ * Stefan A. Krüger - additional utility classes
+ ******************************************************************************/
+package schmitzm.geotools.map.event;
+
+import gtmig.org.geotools.swing.XMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
+
+/**
+ * Diese Klasse stellt ein Ereignis dar, das von einem {@link SelectableXMapPane}
+ * ausgeloest wurde (z.B. Aenderung der Aufloesung).
+ * @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
+ * @version 1.0
+ */
+public abstract class MapPaneEvent {
+ /** Beinhaltet das {@link XMapPane}, das das Ereignis ausgeloest hat */
+ protected SelectableXMapPane source = null;
+ /** Beinhaltet ein Objekt, das das Ereignis initiiert hat */
+ protected Object sourceObject = null;
+
+ /**
+ * Erzeugt ein neues Ereignis.
+ * @param source {@link XMapPane}, das das Ereignis ausgeloest hat
+ * @param sourceObject Objeckt, das das Ereignis initiiert hat (wenn {@code null},
+ * wird das MapPane als Ausloeser gesetzt)
+ */
+ public MapPaneEvent(SelectableXMapPane source, Object sourceObject) {
+ this.source = source;
+ this.sourceObject = (sourceObject != null) ? sourceObject : source;
+ }
+
+ /**
+ * Erzeugt ein neues Ereignis.
+ * @param source {@link XMapPane}, das das Ereignis ausgeloest hat
+ */
+ public MapPaneEvent(SelectableXMapPane source) {
+ this(source,null);
+ }
+
+ /**
+ * Liefert das {@link SelectableXMapPane}, das das Ereignis ausgeloest hat.
+ */
+ public SelectableXMapPane getSource() {
+ return source;
+ }
+
+ /**
+ * Liefert das Object, das das Ereignis initiiert hat.
+ */
+ public Object getSourceObject() {
+ return sourceObject;
+ }
+}
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ObjectSelectionEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ObjectSelectionEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ObjectSelectionEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,15 +29,17 @@
******************************************************************************/
package schmitzm.geotools.map.event;
+import gtmig.org.geotools.swing.XMapPane;
+
import org.geotools.map.MapLayer;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import com.vividsolutions.jts.geom.Envelope;
/**
* Diese Klasse stellt eine Oberklasse fuer die Ereignisse dar, die ein
- * {@link JMapPane} ausloest, wenn der Anwender einen Bereich in der Karte ausgewaehlt hat
+ * {@link XMapPane} ausloest, wenn der Anwender einen Bereich in der Karte ausgewaehlt hat
* und dabei Objekte selektiert wurde.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
@@ -55,7 +57,7 @@
* @param sourceObject Objekt, das die Selektion initiiert hat (wenn {@code null},
* wird das MapPane als Ausloeser gesetzt)
*/
- public ObjectSelectionEvent(JMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, E result, Object sourceObject) {
+ public ObjectSelectionEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, E result, Object sourceObject) {
super(sourceMap,envelope,sourceObject);
this.sourceLayer = sourceLayer;
this.result = result;
@@ -68,7 +70,7 @@
* @param envelope Bereich der selektiert wurde
* @param result selektierte Objekte
*/
- public ObjectSelectionEvent(JMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, E result) {
+ public ObjectSelectionEvent(SelectableXMapPane sourceMap, MapLayer sourceLayer, Envelope envelope, E result) {
this(sourceMap,sourceLayer,envelope, result, null);
}
/**
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ScaleChangedEvent.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ScaleChangedEvent.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/map/event/ScaleChangedEvent.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,15 +29,15 @@
******************************************************************************/
package schmitzm.geotools.map.event;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
/**
- * Diese Klasse stellt ein Ereignis dar, das ein {@link JMapPane} ausloest,
+ * Diese Klasse stellt ein Ereignis dar, das ein {@link SelectableXMapPane} ausloest,
* wenn sich die Skalierung/Aufloesung der Karte aendert.
* @author <a href="mailto:martin.schmitz at koeln.de">Martin Schmitz</a> (University of Bonn/Germany)
* @version 1.0
*/
-public class ScaleChangedEvent extends JMapPaneEvent {
+public class ScaleChangedEvent extends MapPaneEvent {
private double oldScale = 0;
private double newScale = 0;
@@ -46,7 +46,7 @@
* @param oldScale vormalige Aufloesung
* @param newScale neue Aufloesung
*/
- public ScaleChangedEvent(JMapPane source, double oldScale, double newScale) {
+ public ScaleChangedEvent(SelectableXMapPane source, double oldScale, double newScale) {
super(source);
this.oldScale = oldScale;
this.newScale = newScale;
Modified: branches/1.0-gt2-2.6/src/schmitzm/geotools/styling/StylingUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/geotools/styling/StylingUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/geotools/styling/StylingUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,6 +29,8 @@
******************************************************************************/
package schmitzm.geotools.styling;
+import gtmig.org.geotools.swing.XMapPane;
+
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -61,11 +63,13 @@
import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
import org.geotools.data.FeatureSource;
import org.geotools.data.memory.MemoryFeatureCollection;
+import org.geotools.data.store.EmptyFeatureCollection;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.GeometryAttributeType;
import org.geotools.filter.ConstantExpression;
+import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.renderer.lite.RendererUtilities;
import org.geotools.resources.i18n.Vocabulary;
import org.geotools.resources.i18n.VocabularyKeys;
@@ -149,12 +153,12 @@
/** Standard-Instanz eines {@link SLDTransformer}. */
public final static SLDTransformer SLDTRANSFORMER = new SLDTransformer();
-// /**
-// * Standard-Instanz eines {@link StyleBuilder}.
-// *
-// * @deprecated wurde ersetzt durch {@link #STYLE_BUILDER}
-// */
-// public static final StyleBuilder builder = STYLE_BUILDER;
+ // /**
+ // * Standard-Instanz eines {@link StyleBuilder}.
+ // *
+ // * @deprecated wurde ersetzt durch {@link #STYLE_BUILDER}
+ // */
+ // public static final StyleBuilder builder = STYLE_BUILDER;
/** Standard-Instanz einer {@link StyleFactory} */
public static final StyleFactory STYLE_FACTORY = CommonFactoryFinder
@@ -1158,6 +1162,10 @@
*
* TODO Was ist mit raster?!
*
+ * TODO Das sollte man besser machen: Zuerst die FIlter der
+ * sichtbaren regeln raussuchen, und dann direkt am anfang damitmit
+ * mitfiltern...
+ *
* @author <a href="mailto:skpublic at wikisquare.de">Stefan Alfons
* Krüger</a>
*/
@@ -1579,8 +1587,7 @@
* @param colors
* colors for the palette
*/
- public static BrewerPalette createBrewerPalette(String name, Color[] colors)
- {
+ public static BrewerPalette createBrewerPalette(String name, Color[] colors) {
BrewerPalette palette = new BrewerPalette();
palette.setColors(colors);
palette.setName(name);
@@ -1589,14 +1596,17 @@
// set suitability to UNKNOWN for all viewers
PaletteSuitability suitability = new PaletteSuitability();
try {
- suitability.setSuitability(colors.length, new String[] { "?", "?", "?",
- "?", "?", "?" });
+ suitability.setSuitability(colors.length, new String[] { "?", "?",
+ "?", "?", "?", "?" });
palette.setPaletteSuitability(suitability);
} catch (IOException e) {
- LOGGER.error("Unabel to PaletteSuitability.setSuitablility for colors.length="+colors,e);
+ LOGGER.error(
+ "Unabel to PaletteSuitability.setSuitablility for colors.length="
+ + colors, e);
}
- // Create the trivial scheme for the palette (requested colors equals number of colors)
+ // Create the trivial scheme for the palette (requested colors equals
+ // number of colors)
int[] schema = new int[colors.length];
for (int j = 0; j < colors.length; j++)
schema[j] = j;
@@ -1605,12 +1615,10 @@
// set the trivial scheme for all schemas
for (int j = 2; j < schema.length; j++) {
sampleScheme.setSampleScheme(j, schema);
-// sampleScheme.setSampleScheme(schema.length, schema);
+ // sampleScheme.setSampleScheme(schema.length, schema);
}
-
-
+
palette.setColorScheme(sampleScheme);
-
return palette;
}
@@ -1656,7 +1664,7 @@
Symbolizer[] symbolizers = new Symbolizer[0];
switch (geometryForm) {
-
+
case POINT:
PointSymbolizer ps = STYLE_FACTORY.createPointSymbolizer();
ps.setGraphic(SELECTION_GRAPHIC1);
@@ -2270,4 +2278,39 @@
return maxScale;
}
+ /**
+ * 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üger</a>
+ */
+ public static FeatureCollection<SimpleFeatureType, SimpleFeature> filterSLDVisibleOnly(
+ final FeatureCollection<SimpleFeatureType, SimpleFeature> fc,
+ final Style style, XMapPane xMapPane) {
+
+ if (xMapPane == null || style == null)
+ return new EmptyFeatureCollection(fc.getSchema());
+
+ // Der "scaleDenominator" der aktuellen JMapPane
+ Double scaleDenominator = RendererUtilities.calculateOGCScale(
+ new ReferencedEnvelope(xMapPane.getMapArea(), xMapPane
+ .getContext().getCoordinateReferenceSystem()), xMapPane
+ .getBounds().width, null);
+
+ return filterSLDVisibleOnly(fc, style, scaleDenominator);
+ }
+
}
Modified: branches/1.0-gt2-2.6/src/schmitzm/jfree/JFreeChartUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/jfree/JFreeChartUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/jfree/JFreeChartUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -31,7 +31,6 @@
import java.awt.Color;
import java.text.DecimalFormat;
-import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
Modified: branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/SelectableChartPanel.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/SelectableChartPanel.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/SelectableChartPanel.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,8 +29,6 @@
******************************************************************************/
package schmitzm.jfree.chart;
-import java.awt.BasicStroke;
-import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.HashSet;
Modified: branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionCategoryRenderer.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -32,7 +32,6 @@
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
-import java.awt.Stroke;
import java.awt.geom.Rectangle2D;
import org.apache.log4j.Logger;
Modified: branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/PointSelectionXYRenderer.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,18 +29,10 @@
******************************************************************************/
package schmitzm.jfree.chart.renderer;
-import java.awt.BasicStroke;
import java.awt.Color;
-import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
-import java.awt.Stroke;
-import java.awt.Rectangle;
-import java.awt.TexturePaint;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
import org.apache.log4j.Logger;
import org.jfree.chart.axis.ValueAxis;
@@ -52,7 +44,6 @@
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.general.Dataset;
import org.jfree.data.xy.XYDataset;
-import org.jfree.util.BooleanList;
import schmitzm.jfree.JFreeChartUtil;
import schmitzm.jfree.chart.selection.SeriesDatasetSelectionModel;
Modified: branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionRenderer.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -30,7 +30,6 @@
package schmitzm.jfree.chart.renderer;
import java.awt.Paint;
-import java.awt.Stroke;
import schmitzm.jfree.chart.selection.DatasetSelectionModel;
import schmitzm.jfree.chart.selection.DatasetSelectionModelProvider;
Modified: branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/jfree/chart/renderer/SelectionXYLineAndShapeRenderer.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -32,7 +32,6 @@
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
-import java.awt.Stroke;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Map;
Modified: branches/1.0-gt2-2.6/src/schmitzm/swing/SwingUtil.java
===================================================================
--- branches/1.0-gt2-2.6/src/schmitzm/swing/SwingUtil.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/schmitzm/swing/SwingUtil.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -29,18 +29,24 @@
******************************************************************************/
package schmitzm.swing;
+import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
+import java.awt.Composite;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
+import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.Image;
import java.awt.Point;
+import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
import java.text.NumberFormat;
import java.util.Enumeration;
import java.util.Locale;
@@ -1032,26 +1038,97 @@
* Allows to define a renderer and min- and max width of a column with just
* one line of code ;-)
*
- * @param table
- * @param modelIdx column index in model
- * @param cellRenderer <code>null</code> allowed
- * @param minwidth <code>null</code> allowed
- * @param prefwidth <code>null</code> allowed
- * @param maxwidth <code>null</code> allowed
+ * @param table
+ * @param modelIdx
+ * column index in model
+ * @param cellRenderer
+ * <code>null</code> allowed
+ * @param minwidth
+ * <code>null</code> allowed
+ * @param prefwidth
+ * <code>null</code> allowed
+ * @param maxwidth
+ * <code>null</code> allowed
*/
public static void setColumnLook(JTable table, Integer modelIdx,
- TableCellRenderer cellRenderer, Integer minWidth, Integer preferredWidth, Integer maxWidth) {
+ TableCellRenderer cellRenderer, Integer minWidth,
+ Integer preferredWidth, Integer maxWidth) {
int idx = table.convertColumnIndexToView(modelIdx);
if (cellRenderer != null)
table.getColumnModel().getColumn(idx).setCellRenderer(cellRenderer);
if (minWidth != null)
table.getColumnModel().getColumn(idx).setMinWidth(minWidth);
- if (preferredWidth!= null)
- table.getColumnModel().getColumn(idx).setPreferredWidth(preferredWidth);
+ if (preferredWidth != null)
+ table.getColumnModel().getColumn(idx).setPreferredWidth(
+ preferredWidth);
if (maxWidth != null)
table.getColumnModel().getColumn(idx).setMaxWidth(maxWidth);
}
+ /**
+ * Erase an image. This is much faster than recreating a new BufferedImage
+ */
+ public static void clearImage(BufferedImage image) {
+ Graphics2D baseImageGraphics = (Graphics2D) image.getGraphics();
+ Composite composite = baseImageGraphics.getComposite();
+ baseImageGraphics.setComposite(AlphaComposite.Clear);
+ Rectangle2D.Double rect = new Rectangle2D.Double(0, 0,
+ image.getWidth(), image.getHeight());
+ baseImageGraphics.fill(rect);
+ baseImageGraphics.setComposite(composite);
+ }
+
+ /**
+ * Clears the four rectengular areas around a given inner {@link Rectangle}.
+ * Clearing is faster than painting.
+ *
+ * @param paintArea
+ * The {@link Rectangle} that shall not be cleared.
+ * @param clearArea
+ * The {@link Rectangle} that shall be cleared, except for where
+ * it intersects with the paintArea.
+ */
+ public static void clearAround(Graphics2D graphics, Rectangle paintArea,
+ Rectangle clearArea) {
+
+ // Clear left of the painted area if needed
+ if (clearArea.getMinX() < paintArea.getMinX()) {
+ graphics.clearRect(
+ (int) clearArea.getMinX(),
+ (int) clearArea.getMinY(),
+ (int) paintArea.getMinX(),
+ (int) clearArea.getMaxY());
+ }
+
+ // Clear right of the painted area if needed
+ if (clearArea.getMaxX() > paintArea.getMaxX()) {
+ graphics.clearRect(
+ (int) paintArea.getMaxX(),
+ (int) clearArea.getMinY(),
+ (int) clearArea.getMaxX(),
+ (int) clearArea.getMaxY());
+ }
+
+ // Clear above of the painted area if needed
+ if (clearArea.getMinY() < paintArea.getMinY()) {
+ graphics.clearRect(
+ (int) clearArea.getMinX(),
+ (int) clearArea.getMinY(),
+ (int) clearArea.getMaxX(),
+ (int) paintArea.getMinY());
+ }
+
+ // Clear below of the painted area if needed
+ if (clearArea.getMaxY() > paintArea.getMaxY()) {
+ graphics.clearRect(
+ (int) clearArea.getMinX(),
+ (int) paintArea.getMaxY(),
+ (int) clearArea.getMaxX(),
+ (int) clearArea.getMaxY());
+ }
+
+ }
+
}
Modified: branches/1.0-gt2-2.6/src/skrueger/geotools/MapPaneToolBar.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/geotools/MapPaneToolBar.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/geotools/MapPaneToolBar.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -52,8 +52,8 @@
import org.apache.log4j.Logger;
-import schmitzm.geotools.gui.JMapPane;
-import schmitzm.geotools.map.event.JMapPaneEvent;
+import schmitzm.geotools.gui.SelectableXMapPane;
+import schmitzm.geotools.map.event.MapPaneEvent;
import schmitzm.geotools.map.event.JMapPaneListener;
import schmitzm.geotools.map.event.MapAreaChangedEvent;
import schmitzm.lang.LangUtil;
@@ -66,7 +66,7 @@
import com.vividsolutions.jts.geom.Envelope;
/**
- * A toolbar to control an {@link JMapPane} (Atlas visualization). This contains
+ * A toolbar to control an {@link SelectableXMapPane} (Atlas visualization). This contains
* two types of buttons. A group of <i>tools</i> for the mouse actions on the
* map represented by {@link JToggleButton JToggleButtons}, where only one tool
* can be activated every time. And some (general) <i>actions</i>, represented
@@ -140,8 +140,8 @@
// /** Holds the action buttons of the bar. */
// protected SortedMap<Integer, JButton> actionButtons = null;
- /** Holds the {@link JMapPane} this tool bar controls. */
- protected JMapPane mapPane = null;
+ /** Holds the {@link SelectableXMapPane} this tool bar controls. */
+ protected SelectableXMapPane mapPane = null;
/**
* A List to remember the last Envelopes that have been watched. Used for
@@ -176,7 +176,7 @@
/**
* Creates a new toolbar. Notice: This toolbar does nothing until
- * {@link #setMapPane(JMapPane)} is called!
+ * {@link #setMapPane(SelectableXMapPane)} is called!
*/
public MapPaneToolBar() {
this(null);
@@ -195,9 +195,9 @@
* Creates a new tool bar.
*
* @param mapPane
- * {@link JMapPane} the tool bar controls
+ * {@link SelectableXMapPane} the tool bar controls
*/
- public MapPaneToolBar(JMapPane mapPane) {
+ public MapPaneToolBar(SelectableXMapPane mapPane) {
super("Control the map", JToolBar.HORIZONTAL);
// I want to see nothing on the background
@@ -208,7 +208,7 @@
// Create a Listener to listen to the zooms on the JMapPane
this.mapPaneListener = new JMapPaneListener() {
- public void performMapPaneEvent(JMapPaneEvent e) {
+ public void performMapPaneEvent(MapPaneEvent e) {
if (!(e instanceof MapAreaChangedEvent))
return;
@@ -269,13 +269,13 @@
}
/**
- * Sets the {@link JMapPane} controlled by this tool bar.
+ * Sets the {@link SelectableXMapPane} controlled by this tool bar.
*
* @param mapPane
- * {@link JMapPane} to control (if {@code null} this tool bar
+ * {@link SelectableXMapPane} to control (if {@code null} this tool bar
* controls NOTHING!)
*/
- public void setMapPane(JMapPane mapPane) {
+ public void setMapPane(SelectableXMapPane mapPane) {
// Remove listener from old MapPane
if (this.mapPane != null)
this.mapPane.removeMapPaneListener(mapPaneListener);
@@ -426,39 +426,31 @@
switch (tool) {
case TOOL_PAN:
// Set the mouse tool to "Panning"
- mapPane.setWindowSelectionState(JMapPane.NONE);
- mapPane.setState(JMapPane.PAN);
- mapPane.setNormalCursor(SwingUtil.PAN_CURSOR);
+ mapPane.setState(SelectableXMapPane.PAN);
+// mapPane.setNormalCursor(SwingUtil.PAN_CURSOR);
break;
case TOOL_INFO:
// Set the mouse tool to "Info"
- mapPane.setWindowSelectionState(JMapPane.NONE);
- mapPane.setState(JMapPane.SELECT_TOP); // Why not:
- // JMapPane.SELECT_TOP_ONEONLY
- // properly removed it to save
- // performance
- mapPane.setNormalCursor(SwingUtil.CROSSHAIR_CURSOR);
+ mapPane.setState(SelectableXMapPane.SELECT_ONE_FROM_TOP);
+// mapPane.setNormalCursor(SwingUtil.CROSSHAIR_CURSOR);
break;
case TOOL_ZOOMIN:
// Set the mouse tool to "Zoom in"
- mapPane.setWindowSelectionState(JMapPane.ZOOM_IN);
- mapPane.setState(JMapPane.ZOOM_IN);
- mapPane.setNormalCursor(SwingUtil.ZOOMIN_CURSOR);
+ mapPane.setState(SelectableXMapPane.ZOOM_IN);
+// mapPane.setNormalCursor(SwingUtil.ZOOMIN_CURSOR);
break;
case TOOL_ZOOMOUT:
// Set the mouse tool to "Zoom out"
- mapPane.setWindowSelectionState(JMapPane.NONE);
- mapPane.setState(JMapPane.ZOOM_OUT);
- mapPane.setNormalCursor(SwingUtil.ZOOMOUT_CURSOR);
+ mapPane.setState(SelectableXMapPane.ZOOM_OUT);
+// mapPane.setNormalCursor(SwingUtil.ZOOMOUT_CURSOR);
break;
default:
// Set map actions to default
- mapPane.setWindowSelectionState(JMapPane.NONE);
- mapPane.setState(JMapPane.NONE);
- mapPane.setNormalCursor(null);
+ mapPane.setState(SelectableXMapPane.NONE);
+// mapPane.setNormalCursor(null);
break;
}
- mapPane.updateCursor();
+// mapPane.updateCursorAndRepaintTimer();
}
/**
Modified: branches/1.0-gt2-2.6/src/skrueger/geotools/MapView.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/geotools/MapView.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/geotools/MapView.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -42,9 +42,9 @@
import org.apache.log4j.Logger;
import schmitzm.geotools.gui.GeoMapPane;
-import schmitzm.geotools.gui.JMapPane;
import schmitzm.geotools.gui.MapContextControlPane;
import schmitzm.geotools.gui.MapPaneStatusBar;
+import schmitzm.geotools.gui.SelectableXMapPane;
import schmitzm.geotools.styling.ColorMapManager;
/**
@@ -71,21 +71,20 @@
/**
* Creates a new {@link MapView}. A {@link MapView} is a combination of a
* {@link GeoMapPane}, a {@link MapContextManagerInterface} on the left, and
- * some buttons floating over the {@link JMapPane}
+ * some buttons floating over the {@link SelectableXMapPane}
*/
public MapView(Component parentGui, MapPaneToolBar toolBar) {
super(new BorderLayout());
// Call initialize() by yourself afterwards.
// Needed because variables for the overwritten methods
// are not yet set.
- getGeoMapPane().getMapPane().setWaitCursorComponent(parentGui);
jToolBar = toolBar;
}
/**
* Creates a new {@link MapView}. A {@link MapView} is a combination of a
* {@link GeoMapPane}, a {@link MapContextManagerInterface} on the left, and
- * some buttons floating over the {@link JMapPane}
+ * some buttons floating over the {@link SelectableXMapPane}
*/
public MapView(Component parentGui) {
this(parentGui, null);
@@ -226,7 +225,7 @@
/**
* Liefert den Karten-Bereich der Komponente.
*/
- public final JMapPane getMapPane() {
+ public final SelectableXMapPane getMapPane() {
return getGeoMapPane().getMapPane();
}
Modified: branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/LabelSearch.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/LabelSearch.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/LabelSearch.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -73,9 +73,9 @@
return RESOURCE.getString(key, values);
}
- protected final schmitzm.geotools.gui.JMapPane mapPane;
+ protected final schmitzm.geotools.gui.SelectableXMapPane mapPane;
- public LabelSearch(final schmitzm.geotools.gui.JMapPane mapPane) {
+ public LabelSearch(final schmitzm.geotools.gui.SelectableXMapPane mapPane) {
this.mapPane = mapPane;
}
Modified: branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchMapDialog.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchMapDialog.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchMapDialog.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -59,7 +59,7 @@
import org.apache.log4j.Logger;
import org.geotools.swing.ExceptionMonitor;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import schmitzm.swing.SortableJTable;
import schmitzm.swing.SwingUtil;
@@ -83,10 +83,10 @@
searchTextField.setText(text);
}
- private final JMapPane mapPane;
+ private final SelectableXMapPane mapPane;
/**
- * The dialog will be relative to the {@link JMapPane}s parent
+ * The dialog will be relative to the {@link SelectableXMapPane}s parent
* {@link Window}.
*
* @param parent
@@ -95,7 +95,7 @@
* @param windowTitle
* A title to be used for the dialog.
*/
- public SearchMapDialog(LabelSearch labelSearch, JMapPane mapPane,
+ public SearchMapDialog(LabelSearch labelSearch, SelectableXMapPane mapPane,
final String windowTitle) {
super(SwingUtil.getParentWindow(mapPane), windowTitle);
this.labelSearch = labelSearch;
@@ -157,7 +157,7 @@
}
/**
- * Performes a search on the {@link JMapPane}'s labels and outputs the
+ * Performes a search on the {@link SelectableXMapPane}'s labels and outputs the
* possible numerouse results.
*
* @param text
Modified: branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchResultFeature.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchResultFeature.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/geotools/labelsearch/SearchResultFeature.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -41,13 +41,13 @@
private final SimpleFeature feature;
private final String title;
- private final schmitzm.geotools.gui.JMapPane mapPane;
+ private final schmitzm.geotools.gui.SelectableXMapPane mapPane;
private final String inTitle;
private final MapLayer mapLayer;
public SearchResultFeature(SimpleFeature feature, String title, String inTitle,
- schmitzm.geotools.gui.JMapPane mapPane, MapLayer mapLayer) {
+ schmitzm.geotools.gui.SelectableXMapPane mapPane, MapLayer mapLayer) {
this.feature = feature;
this.title = title;
this.inTitle = inTitle;
Modified: branches/1.0-gt2-2.6/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/geotools/selection/FeatureMapLayerSelectionSynchronizer.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -42,11 +42,9 @@
**/
package skrueger.geotools.selection;
-import java.awt.RenderingHints;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@@ -60,9 +58,6 @@
import org.geotools.feature.FeatureIterator;
import org.geotools.filter.FidFilterImpl;
import org.geotools.map.MapLayer;
-import org.geotools.renderer.GTRenderer;
-import org.geotools.renderer.label.LabelCacheImpl;
-import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Style;
import org.geotools.styling.visitor.DuplicatingStyleVisitor;
@@ -73,10 +68,9 @@
import org.opengis.filter.identity.FeatureId;
import schmitzm.geotools.FilterUtil;
-import schmitzm.geotools.GTUtil;
-import schmitzm.geotools.gui.JMapPane;
+import schmitzm.geotools.gui.SelectableXMapPane;
import schmitzm.geotools.map.event.FeatureSelectedEvent;
-import schmitzm.geotools.map.event.JMapPaneEvent;
+import schmitzm.geotools.map.event.MapPaneEvent;
import schmitzm.geotools.map.event.JMapPaneListener;
import schmitzm.geotools.styling.StylingUtil;
import skrueger.geotools.MapPaneToolBar;
@@ -110,9 +104,8 @@
*/
protected final MapLayer mapLayer;
protected final StyledFeaturesInterface<?> styledLayer;
- protected final JMapPane mapPane;
+ protected final SelectableXMapPane mapPane;
private final MapPaneToolBar toolBar;
- private final HashMap<Object, Object> defaultGTRenderingHints;
/**
* Creates a new synchronizer
@@ -127,8 +120,7 @@
public FeatureMapLayerSelectionSynchronizer(
StyledFeatureLayerSelectionModel layerSelModel,
StyledFeaturesInterface<?> styledLayer, MapLayer mapLayer,
- JMapPane mapPane, MapPaneToolBar toolBar,
- HashMap<Object, Object> defaultGTRenderingHints) {
+ SelectableXMapPane mapPane, MapPaneToolBar toolBar) {
super(layerSelModel);
this.styledLayer = styledLayer;
@@ -136,10 +128,6 @@
this.mapLayer = mapLayer;
this.mapPane = mapPane;
this.toolBar = toolBar;
- if (defaultGTRenderingHints != null)
- this.defaultGTRenderingHints = defaultGTRenderingHints;
- else
- this.defaultGTRenderingHints = new HashMap<Object, Object>();
}
/**
@@ -405,40 +393,43 @@
return false;
}
+ /**
+ * Replaces the local renderer
+ */
private void replaceRenderer() {
- //
- // // Has to be done before we apply the new Renderer
- // mapLayer.setStyle(style);
+// //
+// // // Has to be done before we apply the new Renderer
+// // mapLayer.setStyle(style);
+//
+// GTRenderer oldRenderer = mapPane.getLocalRenderer();
+//
+// /**
+// * Explicitly putting a new instance of LabelCacheDefault into the
+// * renderer instance, so JMapPane doesn't reuse the old one. This is
+// * very useful when changing the TextSymbolizer with AtlasStyler<br/>
+// * SK 9.7.09: It's not enought to user LabelCache.clear(). We can not
+// * reuse the old Renderer - better to create a new one!
+// */
+// final GTRenderer newRenderer = GTUtil.createGTRenderer();
+//
+// final HashMap<Object, Object> rendererHints = defaultGTRenderingHints;
+// rendererHints.put(StreamingRenderer.LABEL_CACHE_KEY,
+// new LabelCacheImpl());
+//
+// newRenderer.setRendererHints(rendererHints);
+// mapPane.setLocalRenderer(newRenderer);
+//
+// if (oldRenderer != null) {
+//
+// RenderingHints java2DHints = oldRenderer.getJava2DHints();
+// if (java2DHints != null) {
+// newRenderer.setJava2DHints(java2DHints);
+// }
+//
+// oldRenderer.setContext(null);
+// oldRenderer = null;
+// }
- GTRenderer oldRenderer = mapPane.getRenderer();
-
- /**
- * Explicitly putting a new instance of LabelCacheDefault into the
- * renderer instance, so JMapPane doesn't reuse the old one. This is
- * very useful when changing the TextSymbolizer with AtlasStyler<br/>
- * SK 9.7.09: It's not enought to user LabelCache.clear(). We can not
- * reuse the old Renderer - better to create a new one!
- */
- final GTRenderer newRenderer = GTUtil.createGTRenderer();
-
- final HashMap<Object, Object> rendererHints = defaultGTRenderingHints;
- rendererHints.put(StreamingRenderer.LABEL_CACHE_KEY,
- new LabelCacheImpl());
-
- newRenderer.setRendererHints(rendererHints);
- mapPane.setRenderer(newRenderer);
-
- if (oldRenderer != null) {
-
- RenderingHints java2DHints = oldRenderer.getJava2DHints();
- if (java2DHints != null) {
- newRenderer.setJava2DHints(java2DHints);
- }
-
- oldRenderer.setContext(null);
- oldRenderer = null;
- }
-
mapPane.refresh();
}
@@ -448,7 +439,7 @@
* {@link StyledFeatureLayerSelectionModel}
*/
@Override
- public void performMapPaneEvent(JMapPaneEvent e) {
+ public void performMapPaneEvent(MapPaneEvent e) {
// Ignore event if it is caused by us or the synchronizer is disabled.
if (!isEnabled() || selectionChangeCausedByMe)
Modified: branches/1.0-gt2-2.6/src/skrueger/swing/CancellableDialogManager.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/swing/CancellableDialogManager.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/swing/CancellableDialogManager.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -27,7 +27,7 @@
}
/**
- * Tells the suer that the dialog shall be closed. The user may save, cancel or abort the closing.
+ * Tells the user that the dialog shall be closed. The user may save, cancel or abort the closing.
*
* @return <code>true</code> if there is no open instance or the instance has been disposed
*/
Modified: branches/1.0-gt2-2.6/src/skrueger/swing/CancellableTabbedDialogAdapter.java
===================================================================
--- branches/1.0-gt2-2.6/src/skrueger/swing/CancellableTabbedDialogAdapter.java 2009-11-03 14:38:26 UTC (rev 508)
+++ branches/1.0-gt2-2.6/src/skrueger/swing/CancellableTabbedDialogAdapter.java 2009-11-05 08:51:33 UTC (rev 509)
@@ -10,7 +10,6 @@
import net.miginfocom.swing.MigLayout;
import schmitzm.swing.JPanel;
-import schmitzm.swing.SwingUtil;
public abstract class CancellableTabbedDialogAdapter extends
CancellableDialogAdapter {
More information about the Schmitzm-commits
mailing list