13 |
import java.awt.event.ActionListener; |
import java.awt.event.ActionListener; |
14 |
import java.awt.event.ComponentAdapter; |
import java.awt.event.ComponentAdapter; |
15 |
import java.awt.event.ComponentEvent; |
import java.awt.event.ComponentEvent; |
|
import java.awt.event.InputEvent; |
|
16 |
import java.awt.event.MouseEvent; |
import java.awt.event.MouseEvent; |
17 |
import java.awt.event.MouseListener; |
import java.awt.event.MouseListener; |
18 |
import java.awt.geom.AffineTransform; |
import java.awt.geom.AffineTransform; |
36 |
import org.geotools.geometry.jts.JTS; |
import org.geotools.geometry.jts.JTS; |
37 |
import org.geotools.geometry.jts.ReferencedEnvelope; |
import org.geotools.geometry.jts.ReferencedEnvelope; |
38 |
import org.geotools.map.DefaultMapContext; |
import org.geotools.map.DefaultMapContext; |
39 |
|
import org.geotools.map.DefaultMapLayer; |
40 |
import org.geotools.map.MapContext; |
import org.geotools.map.MapContext; |
41 |
import org.geotools.map.MapLayer; |
import org.geotools.map.MapLayer; |
42 |
import org.geotools.map.event.MapLayerEvent; |
import org.geotools.map.event.MapLayerEvent; |
49 |
import org.geotools.renderer.lite.LabelCache; |
import org.geotools.renderer.lite.LabelCache; |
50 |
import org.geotools.renderer.lite.RendererUtilities; |
import org.geotools.renderer.lite.RendererUtilities; |
51 |
import org.geotools.renderer.lite.StreamingRenderer; |
import org.geotools.renderer.lite.StreamingRenderer; |
52 |
|
import org.geotools.resources.image.ImageUtilities; |
53 |
|
import org.geotools.styling.Style; |
54 |
import org.geotools.swing.JMapPane; |
import org.geotools.swing.JMapPane; |
55 |
import org.geotools.swing.event.MapMouseEvent; |
import org.geotools.swing.event.MapMouseEvent; |
56 |
import org.geotools.swing.event.MapPaneEvent; |
import org.geotools.swing.event.MapPaneEvent; |
68 |
import schmitzm.geotools.io.GeoImportUtil; |
import schmitzm.geotools.io.GeoImportUtil; |
69 |
import schmitzm.geotools.map.event.JMapPaneListener; |
import schmitzm.geotools.map.event.JMapPaneListener; |
70 |
import schmitzm.geotools.map.event.MapLayerAdapter; |
import schmitzm.geotools.map.event.MapLayerAdapter; |
71 |
|
import schmitzm.geotools.styling.StylingUtil; |
72 |
import schmitzm.lang.LangUtil; |
import schmitzm.lang.LangUtil; |
73 |
import schmitzm.swing.JPanel; |
import schmitzm.swing.JPanel; |
74 |
import schmitzm.swing.SwingUtil; |
import schmitzm.swing.SwingUtil; |
103 |
*/ |
*/ |
104 |
public class XMapPane extends JPanel { |
public class XMapPane extends JPanel { |
105 |
|
|
106 |
|
/** |
107 |
|
* If {@link #maxExtend} is <code>null</code> the following rules are used |
108 |
|
* to create a default maximum. |
109 |
|
* <ul> |
110 |
|
* <li>Values < 0 : don't grow to fit the monitors aspect ratio, no |
111 |
|
* margin</li> |
112 |
|
* <li>Values 0 : grow to fit the monitors aspect ratio, no margin</li> |
113 |
|
* <li>Values > 0 : grow to fit the monitors aspect ratio, and add a |
114 |
|
* relative margin</li> |
115 |
|
* </ul> |
116 |
|
* **/ |
117 |
|
private double defaultMaxMapExtendMode = .05; |
118 |
|
|
119 |
// private static final int IMAGETYPE = BufferedImage.TYPE_INT_RGB; |
// private static final int IMAGETYPE = BufferedImage.TYPE_INT_RGB; |
120 |
// private static final int IMAGETYPE_withAlpha = |
// private static final int IMAGETYPE_withAlpha = |
121 |
// BufferedImage.TYPE_INT_ARGB; |
// BufferedImage.TYPE_INT_ARGB; |
122 |
private static final int IMAGETYPE = BufferedImage.TYPE_3BYTE_BGR; |
private static final int IMAGETYPE = BufferedImage.TYPE_3BYTE_BGR; |
123 |
|
|
124 |
|
public XMapPaneTool getTool() { |
125 |
|
return tool; |
126 |
|
} |
127 |
|
|
128 |
|
/** |
129 |
|
* If the {@link JPanel} is disabled, it shows nothing and the images are disposed. |
130 |
|
*/ |
131 |
|
@Override |
132 |
|
public void setEnabled(boolean enabled) { |
133 |
|
super.setEnabled(enabled); |
134 |
|
if (enabled == false) |
135 |
|
disposeImages(); |
136 |
|
else |
137 |
|
requestStartRendering(); |
138 |
|
} |
139 |
|
|
140 |
private static final int IMAGETYPE_withAlpha = BufferedImage.TYPE_4BYTE_ABGR; |
private static final int IMAGETYPE_withAlpha = BufferedImage.TYPE_4BYTE_ABGR; |
141 |
|
|
142 |
private final static Logger LOGGER = Logger.getLogger(XMapPane.class); |
private final static Logger LOGGER = Logger.getLogger(XMapPane.class); |
207 |
* Flag for no-tool. |
* Flag for no-tool. |
208 |
*/ |
*/ |
209 |
public static final int NONE = -123; |
public static final int NONE = -123; |
210 |
|
// |
211 |
/** |
// /** |
212 |
* Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl |
// * Flag fuer Modus "Kartenausschnitt bewegen". Nicht fuer Window-Auswahl |
213 |
* moeglich! |
// * moeglich! |
214 |
* |
// * |
215 |
* @see #setState(int) |
// * @see #setState(int) |
216 |
*/ |
// */ |
217 |
public static final int PAN = 1; |
// public static final int PAN = 1; |
218 |
|
// |
219 |
/** |
// /** |
220 |
* Flag fuer Modus "Heran zoomen". |
// * Flag fuer Modus "Heran zoomen". |
221 |
* |
// * |
222 |
* @see #setState(int) |
// * @see #setState(int) |
223 |
* @see #setState(int) |
// * @see #setState(int) |
224 |
*/ |
// */ |
225 |
public static final int ZOOM_IN = 2; |
// public static final int ZOOM_IN = 2; |
226 |
|
// |
227 |
/** |
// /** |
228 |
* Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich! |
// * Flag fuer Modus "Heraus zoomen". Nicht fuer Window-Auswahl moeglich! |
229 |
* |
// * |
230 |
* @see #setState(int) |
// * @see #setState(int) |
231 |
*/ |
// */ |
232 |
public static final int ZOOM_OUT = 3; |
// public static final int ZOOM_OUT = 3; |
|
|
|
|
/** |
|
|
* 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; |
|
|
/** |
|
|
* Flag fuer Modus |
|
|
* "SimpleFeature-Auswahl auf dem obersten (sichtbaren) Layer". |
|
|
* |
|
|
* @see #setState(int) |
|
|
* @see #setState(int) |
|
|
*/ |
|
|
public static final int SELECT_TOP = 4; |
|
233 |
|
|
234 |
/** |
/** |
235 |
* {@link Font} used to paint the wait messages into the map |
* {@link Font} used to paint the wait messages into the map |
570 |
* thread. |
* thread. |
571 |
*/ |
*/ |
572 |
final private Timer startRenderThreadsTimer; |
final private Timer startRenderThreadsTimer; |
573 |
|
// |
574 |
/** |
// /** |
575 |
* The default state is ZOOM_IN, hence by default the |
// * The default state is ZOOM_IN, hence by default the |
576 |
* {@link #xMapPaneMouseListener} is also enabled. |
// * {@link #xMapPaneMouseListener} is also enabled. |
577 |
**/ |
// **/ |
578 |
private int state = ZOOM_IN; |
// private int state = ZOOM_IN; |
579 |
|
// |
580 |
/** |
// /** |
581 |
* Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen |
// * Manuell gesetzter statischer Cursor, unabhaengig von der aktuellen |
582 |
* MapPane-Funktion |
// * MapPane-Funktion |
583 |
*/ |
// */ |
584 |
protected Cursor staticCursor = null; |
// protected Cursor staticCursor = null; |
585 |
|
|
586 |
private AffineTransform worldToScreen; |
private AffineTransform worldToScreen; |
587 |
|
|
625 |
*/ |
*/ |
626 |
public XMapPane(final MapContext localContext_, |
public XMapPane(final MapContext localContext_, |
627 |
final Map<Object, Object> rendererHints) { |
final Map<Object, Object> rendererHints) { |
628 |
|
|
629 |
super(true); |
super(true); |
630 |
|
|
631 |
|
blinkTimer = initBlinkTimer(); |
632 |
|
|
633 |
|
// A default setting |
634 |
|
RenderingHints hintsJava2d = ImageUtilities.NN_INTERPOLATION_HINT; |
635 |
|
setJava2dHints(hintsJava2d); |
636 |
|
|
637 |
setRendererHints(rendererHints); |
setRendererHints(rendererHints); |
638 |
|
|
639 |
setOpaque(true); |
setOpaque(true); |
647 |
this.addMouseListener(xMapPaneMouseListener); |
this.addMouseListener(xMapPaneMouseListener); |
648 |
this.addMouseMotionListener(xMapPaneMouseListener); |
this.addMouseMotionListener(xMapPaneMouseListener); |
649 |
this.addMouseWheelListener(xMapPaneMouseListener); |
this.addMouseWheelListener(xMapPaneMouseListener); |
|
xMapPaneMouseListener.actions.put(MouseInputType.LClick, |
|
|
XMapPaneAction.ZOOM_IN); |
|
|
xMapPaneMouseListener.actions.put(MouseInputType.LDrag, |
|
|
XMapPaneAction.ZOOM_IN); |
|
|
xMapPaneMouseListener.actions.put(MouseInputType.Wheel, |
|
|
XMapPaneAction.ZOOM_IN); |
|
|
|
|
|
xMapPaneMouseListener.actions.put(MouseInputType.RClick, |
|
|
XMapPaneAction.SELECT_ALL); |
|
650 |
|
|
651 |
xMapPaneMouseListener.actions.put(MouseInputType.RDrag, |
// By default the XMapPAne uses the ZOOM_IN tool. |
652 |
XMapPaneAction.PAN); |
setTool(XMapPaneTool.ZOOM_IN); |
653 |
|
|
654 |
/* |
/* |
655 |
* We use a Timer object to avoid rendering delays and flickering when |
* We use a Timer object to avoid rendering delays and flickering when |
741 |
@Override |
@Override |
742 |
public void actionPerformed(final ActionEvent e) { |
public void actionPerformed(final ActionEvent e) { |
743 |
synchronized (requestStartRendering) { |
synchronized (requestStartRendering) { |
744 |
if (requestStartRendering && isWellDefined()) { |
if (requestStartRendering && isWellDefined() && isEnabled()) { |
745 |
|
|
746 |
if (localExecuter.isRunning()) { |
if (localExecuter.isRunning()) { |
747 |
localExecuter.cancelTask(); |
localExecuter.cancelTask(); |
835 |
|
|
836 |
final Envelope maxAllowedExtend = getMaxExtend(); |
final Envelope maxAllowedExtend = getMaxExtend(); |
837 |
|
|
838 |
|
// This variable is used to break the loop if it runs forever... |
839 |
|
Envelope lastCalculatedArea = null; |
840 |
|
/* |
841 |
|
* If a maxAllowedExtend is set, we have to honour that... |
842 |
|
*/ |
843 |
while (maxAllowedExtend != null && !maxAllowedExtend.contains(newArea) |
while (maxAllowedExtend != null && !maxAllowedExtend.contains(newArea) |
844 |
&& newArea != null && !newArea.isNull() |
&& newArea != null && !newArea.isNull() |
845 |
&& !Double.isNaN(newArea.getMinX()) |
&& !Double.isNaN(newArea.getMinX()) |
846 |
&& !Double.isNaN(newArea.getMaxX()) |
&& !Double.isNaN(newArea.getMaxX()) |
847 |
&& !Double.isNaN(newArea.getMinY()) |
&& !Double.isNaN(newArea.getMinY()) |
848 |
&& !Double.isNaN(newArea.getMaxY())) { |
&& !Double.isNaN(newArea.getMaxY())) // Due to Double precision |
849 |
/* |
// problems, this may |
850 |
* If a maxExtend is set, we have to honour that... |
// iterate for ever |
851 |
*/ |
{ |
852 |
|
|
853 |
|
if (newArea.equals(lastCalculatedArea)) |
854 |
|
break; |
855 |
|
// Check that we are not iterating for ever due to double precision |
856 |
|
// rounding errors |
857 |
|
lastCalculatedArea = newArea; |
858 |
|
|
859 |
// Exceeds top? Move down and maybe cut |
// Exceeds top? Move down and maybe cut |
860 |
if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) { |
if (newArea.getMaxY() > maxAllowedExtend.getMaxY()) { |
959 |
.getCoordinateReferenceSystem()), false); |
.getCoordinateReferenceSystem()), false); |
960 |
} |
} |
961 |
} |
} |
962 |
|
|
963 |
} |
} |
964 |
|
|
965 |
return new ReferencedEnvelope(newArea, env |
return new ReferencedEnvelope(newArea, env |
1058 |
return; |
return; |
1059 |
|
|
1060 |
graphics.setXORMode(color); |
graphics.setXORMode(color); |
1061 |
|
|
1062 |
if (fill) { |
if (fill) { |
1063 |
graphics.fillRect(left, bottom, width, height); |
graphics.fillRect(left, bottom, width, height); |
1064 |
graphics.setXORMode(Color.WHITE); |
graphics.setXORMode(Color.WHITE); |
1065 |
} |
} |
1066 |
|
|
|
|
|
1067 |
graphics.drawRect(left, bottom, width, height); |
graphics.drawRect(left, bottom, width, height); |
1068 |
} |
} |
1069 |
|
|
1275 |
return null; |
return null; |
1276 |
} |
} |
1277 |
|
|
1278 |
// Vergrößerung um 10% nochmal rausgenommen |
return JTSUtil.fixAspectRatio(getVisibleRect(), |
1279 |
// // // Kartenbereich um 10% vergroessern |
addDefaultMargin(layerBounds), true); |
|
// return JTSUtil.fixAspectRatio(getVisibleRect(), JTSUtil |
|
|
// .expandEnvelope(layerBounds, 0.1), true); |
|
1280 |
|
|
|
return JTSUtil.fixAspectRatio(getVisibleRect(), layerBounds, true); |
|
1281 |
} |
} |
1282 |
return maxExtend; |
return maxExtend; |
1283 |
} |
} |
1332 |
return new AffineTransform(screenToWorld); |
return new AffineTransform(screenToWorld); |
1333 |
} |
} |
1334 |
|
|
1335 |
public int getState() { |
// public int getState() { |
1336 |
return state; |
// return state; |
1337 |
} |
// } |
1338 |
|
// |
1339 |
/** |
// /** |
1340 |
* Liefert den statisch eingestellten Cursor, der unabhaengig von der |
// * Liefert den statisch eingestellten Cursor, der unabhaengig von der |
1341 |
* eingestellten MapPane-Aktion (Zoom, Auswahl, ...) verwendet wird. |
// * eingestellten MapPane-Aktion (Zoom, Auswahl, ...) verwendet wird. |
1342 |
* |
// * |
1343 |
* @return {@code null}, wenn kein statischer Cursor verwendet, sondern der |
// * @return {@code null}, wenn kein statischer Cursor verwendet, sondern |
1344 |
* Cursor automatisch je nach MapPane-Aktion eingestellt wird. |
// der |
1345 |
*/ |
// * Cursor automatisch je nach MapPane-Aktion eingestellt wird. |
1346 |
public Cursor getStaticCursor() { |
// */ |
1347 |
return this.staticCursor; |
// public Cursor getStaticCursor() { |
1348 |
} |
// return this.staticCursor; |
1349 |
|
// } |
1350 |
|
|
1351 |
public AffineTransform getWorldToScreenTransform() { |
public AffineTransform getWorldToScreenTransform() { |
1352 |
if (worldToScreen == null) { |
if (worldToScreen == null) { |
1634 |
} |
} |
1635 |
|
|
1636 |
} |
} |
1637 |
// |
|
1638 |
// /** |
// |
1639 |
// * Performs a {@value #PAN} action. During panning, the displacement is |
// /** |
1640 |
// * stored in {@link #imageOrigin} object. Calling {@link #performPan()} will |
// * Performs a {@value #PAN} action. During panning, the displacement is |
1641 |
// * reset the offset and call {@link #setMapArea(Envelope)}. |
// * stored in {@link #imageOrigin} object. Calling {@link #performPan()} |
1642 |
// */ |
// will |
1643 |
// public void performPan() { |
// * reset the offset and call {@link #setMapArea(Envelope)}. |
1644 |
// |
// */ |
1645 |
// final Rectangle winBounds = getVisibleRect(); |
// public void performPan() { |
1646 |
// |
// |
1647 |
// winBounds.translate(-imageOrigin.x, -imageOrigin.y); |
// final Rectangle winBounds = getVisibleRect(); |
1648 |
// final Envelope newMapArea = tranformWindowToGeo(winBounds.x, |
// |
1649 |
// winBounds.y, winBounds.x + winBounds.width, winBounds.y |
// winBounds.translate(-imageOrigin.x, -imageOrigin.y); |
1650 |
// + winBounds.height); |
// final Envelope newMapArea = tranformWindowToGeo(winBounds.x, |
1651 |
// |
// winBounds.y, winBounds.x + winBounds.width, winBounds.y |
1652 |
// imageOrigin.x = 0; |
// + winBounds.height); |
1653 |
// imageOrigin.y = 0; |
// |
1654 |
// |
// imageOrigin.x = 0; |
1655 |
// if (!setMapArea(newMapArea)) { |
// imageOrigin.y = 0; |
1656 |
// /** |
// |
1657 |
// * If setMapArea returns true, the finalImage is updated anyways. |
// if (!setMapArea(newMapArea)) { |
1658 |
// * This if-case exists to ensure that we repaint a correct image |
// /** |
1659 |
// * even if the new panning area has been denied. |
// * If setMapArea returns true, the finalImage is updated anyways. |
1660 |
// */ |
// * This if-case exists to ensure that we repaint a correct image |
1661 |
// updateFinalImage(); |
// * even if the new panning area has been denied. |
1662 |
// repaint(); |
// */ |
1663 |
// } |
// updateFinalImage(); |
1664 |
// |
// repaint(); |
1665 |
// if (getCursor() == SwingUtil.PANNING_CURSOR) |
// } |
1666 |
// setCursor(SwingUtil.PAN_CURSOR); |
// |
1667 |
// } |
// if (getCursor() == SwingUtil.PANNING_CURSOR) |
1668 |
|
// setCursor(SwingUtil.PAN_CURSOR); |
1669 |
|
// } |
1670 |
|
|
1671 |
/** |
/** |
1672 |
* Entfernt einen Listener von der Map. |
* Entfernt einen Listener von der Map. |
1975 |
|
|
1976 |
// /** Stored the time used for the last real rendering in ms. **/ |
// /** Stored the time used for the last real rendering in ms. **/ |
1977 |
private long lastRenderingDuration = 1000; |
private long lastRenderingDuration = 1000; |
1978 |
private XMapPaneTool tool = XMapPaneTool.INFO; |
private XMapPaneTool tool = null; |
1979 |
|
|
1980 |
|
private Timer blinkTimer; |
1981 |
|
|
1982 |
/** |
/** |
1983 |
* Set the minimum (nearest) allowed zoom scale. This is the bigger number |
* Set the minimum (nearest) allowed zoom scale. This is the bigger number |
2009 |
this.rendererHints = rendererHints; |
this.rendererHints = rendererHints; |
2010 |
} |
} |
2011 |
|
|
2012 |
/** |
// @Deprecated |
2013 |
* Enables/Disables the ZOOM Mouse Listener. Upates the Cursor and stops the |
// public void setState(final int state) { |
2014 |
* repaint Timer if |
// this.state = state; |
2015 |
* |
// |
2016 |
* @param state |
// // throw new RuntimeException("Old concept.. migrate to new concept!"); |
2017 |
*/ |
// |
2018 |
@Deprecated |
// // xMapPaneMouseListener.setEnabled((state == ZOOM_IN |
2019 |
public void setState(final int state) { |
// // || state == ZOOM_OUT || state == PAN)); |
2020 |
this.state = state; |
// |
2021 |
|
// // Je nach Aktion den Cursor umsetzen |
2022 |
// throw new RuntimeException("Old concept.. migrate to new concept!"); |
// updateCursor(); |
2023 |
|
// } |
|
// xMapPaneMouseListener.setEnabled((state == ZOOM_IN |
|
|
// || state == ZOOM_OUT || state == PAN)); |
|
|
|
|
|
// Je nach Aktion den Cursor umsetzen |
|
|
updateCursor(); |
|
|
} |
|
2024 |
|
|
2025 |
public void configureMouse(MouseInputType type, XMapPaneAction action) { |
public void configureMouse(MouseInputType type, XMapPaneAction action) { |
2026 |
xMapPaneMouseListener.actions.put(type, action); |
xMapPaneMouseListener.actions.put(type, action); |
2027 |
} |
} |
2028 |
|
|
2029 |
/** |
/** |
2030 |
* Configure the tool that active on the map |
* Configure the {@link XMapPaneTool} that active on the map. Passing |
2031 |
|
* <code>null</code> will set the NO_ACTION tool. |
2032 |
*/ |
*/ |
2033 |
public void setTool(XMapPaneTool tool) { |
public void setTool(XMapPaneTool tool) { |
2034 |
|
if (tool == null) |
2035 |
|
tool = XMapPaneTool.NO_ACTION; |
2036 |
this.tool = tool; |
this.tool = tool; |
2037 |
xMapPaneMouseListener.configure(tool); |
xMapPaneMouseListener.configure(tool); |
2038 |
setCursor(tool.cursor); |
setCursor(tool.getCursor()); |
2039 |
} |
} |
2040 |
|
|
2041 |
/** |
// /** |
2042 |
* Standardmaessig wird der Cursor automatisch je nach MapPane-Aktion (Zoom, |
// * Standardmaessig wird der Cursor automatisch je nach MapPane-Aktion |
2043 |
* Auswahl, ...) gesetzt. Mit dieser Methode kann ein statischer Cursor |
// (Zoom, |
2044 |
* gesetzt werden, der unabhaengig von der aktuellen MapPanes-Aktion |
// * Auswahl, ...) gesetzt. Mit dieser Methode kann ein statischer Cursor |
2045 |
* beibehalten wird. Um diesen statischen Cursor wieder zu entfernen, kann |
// * gesetzt werden, der unabhaengig von der aktuellen MapPanes-Aktion |
2046 |
* {@code null} als Parameter uebergeben werden |
// * beibehalten wird. Um diesen statischen Cursor wieder zu entfernen, kann |
2047 |
* |
// * {@code null} als Parameter uebergeben werden |
2048 |
* @param cursor |
// * |
2049 |
* Cursor |
// * @param cursor |
2050 |
*/ |
// * Cursor |
2051 |
public void setStaticCursor(final Cursor cursor) { |
// */ |
2052 |
this.staticCursor = cursor; |
// public void setStaticCursor(final Cursor cursor) { |
2053 |
if (cursor != null) |
// this.staticCursor = cursor; |
2054 |
super.setCursor(cursor); |
// if (cursor != null) |
2055 |
} |
// super.setCursor(cursor); |
2056 |
|
// } |
2057 |
|
|
2058 |
/** |
/** |
2059 |
* Starts rendering on one or two threads |
* Starts rendering on one or two threads |
2131 |
* X-Koordinate der BIS-Position |
* X-Koordinate der BIS-Position |
2132 |
* @param py |
* @param py |
2133 |
* Y-Koordinate der BIS-Position |
* Y-Koordinate der BIS-Position |
|
* @param winToGeotransform |
|
|
* Eine Window to Geo transform. If <code>null</code>, |
|
|
* {@link #getScreenToWorld()} is used. |
|
2134 |
*/ |
*/ |
2135 |
public Envelope tranformGeoToWindow(final double ox, final double oy, |
public Envelope tranformGeoToWindow(final double ox, final double oy, |
2136 |
final double px, final double py) { |
final double px, final double py) { |
2147 |
} |
} |
2148 |
|
|
2149 |
/** |
/** |
2150 |
|
* Transformiert einen Geo-Koordinate in eine Fenster-Koordinaten. |
2151 |
|
* |
2152 |
|
* @param x |
2153 |
|
* X-Koordinate der VON-Position |
2154 |
|
* @param y |
2155 |
|
* Y-Koordinate der VON-Position |
2156 |
|
*/ |
2157 |
|
public Point2D tranformGeoToWindow(final double x, final double y) { |
2158 |
|
return getWorldToScreenTransform().transform(new Point2D.Double(x, y), |
2159 |
|
null); |
2160 |
|
} |
2161 |
|
|
2162 |
|
/** |
2163 |
* Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten. |
* Transformiert einen Fenster-Koordinaten-Bereich in Geo-Koordinaten. |
2164 |
* |
* |
2165 |
* @param ox |
* @param ox |
2205 |
repaint(); |
repaint(); |
2206 |
} |
} |
2207 |
} |
} |
2208 |
|
// |
2209 |
// |
// // |
2210 |
// wenn manueller Cursor gesetzt ist, dann diesen verwenden (unabhaengig |
// // wenn manueller Cursor gesetzt ist, dann diesen verwenden |
2211 |
// von der aktuellen Aktion |
// (unabhaengig |
2212 |
if (this.staticCursor != null) { |
// // von der aktuellen Aktion |
2213 |
setCursor(staticCursor); |
// if (this.staticCursor != null) { |
2214 |
return; |
// setCursor(staticCursor); |
2215 |
} |
// return; |
2216 |
|
// } |
2217 |
|
// |
2218 |
if (getCursor() == SwingUtil.PANNING_CURSOR) { |
if (getCursor() == SwingUtil.PANNING_CURSOR) { |
2219 |
// This cursor will reset itself |
// This cursor will reset itself |
2220 |
return; |
return; |
2221 |
} |
} |
2222 |
|
|
2223 |
setCursor(tool.cursor); |
setCursor(tool.getCursor()); |
2224 |
// |
|
2225 |
// // Set the cursor depending on what tool is in use... |
// |
2226 |
// switch (state) { |
// // Set the cursor depending on what tool is in use... |
2227 |
// case SELECT_TOP: |
// switch (state) { |
2228 |
// case SELECT_ONE_FROM_TOP: |
// case SELECT_TOP: |
2229 |
// case SELECT_ALL: |
// case SELECT_ONE_FROM_TOP: |
2230 |
// setCursor(SwingUtil.CROSSHAIR_CURSOR); |
// case SELECT_ALL: |
2231 |
// break; |
// setCursor(SwingUtil.CROSSHAIR_CURSOR); |
2232 |
// case ZOOM_IN: |
// break; |
2233 |
// setCursor(SwingUtil.ZOOMIN_CURSOR); |
// case ZOOM_IN: |
2234 |
// break; |
// setCursor(SwingUtil.ZOOMIN_CURSOR); |
2235 |
// case ZOOM_OUT: |
// break; |
2236 |
// setCursor(SwingUtil.ZOOMOUT_CURSOR); |
// case ZOOM_OUT: |
2237 |
// break; |
// setCursor(SwingUtil.ZOOMOUT_CURSOR); |
2238 |
// case PAN: |
// break; |
2239 |
// setCursor(SwingUtil.PAN_CURSOR); |
// case PAN: |
2240 |
// break; |
// setCursor(SwingUtil.PAN_CURSOR); |
2241 |
// default: |
// break; |
2242 |
// setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
// default: |
2243 |
// break; |
// setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
2244 |
// } |
// break; |
2245 |
|
// } |
2246 |
} |
} |
2247 |
|
|
2248 |
/** |
/** |
2272 |
|
|
2273 |
final Graphics2D finalG = getFinalImage().createGraphics(); |
final Graphics2D finalG = getFinalImage().createGraphics(); |
2274 |
finalG.setBackground(getMapBackgroundColor()); |
finalG.setBackground(getMapBackgroundColor()); |
2275 |
finalG.drawImage(getPreFinalImage(), getImageOrigin().x, getImageOrigin().y, |
finalG.drawImage(getPreFinalImage(), getImageOrigin().x, |
2276 |
getMapBackgroundColor(), null); |
getImageOrigin().y, getMapBackgroundColor(), null); |
2277 |
|
|
2278 |
// When panning, we have to clear the area around the image |
// When panning, we have to clear the area around the image |
2279 |
final Rectangle painedArea = new Rectangle(getImageOrigin().x, |
final Rectangle painedArea = new Rectangle(getImageOrigin().x, |
2282 |
SwingUtil.clearAround(finalG, painedArea, getVisibleRect(), |
SwingUtil.clearAround(finalG, painedArea, getVisibleRect(), |
2283 |
getMapBackgroundColor()); |
getMapBackgroundColor()); |
2284 |
|
|
2285 |
// addGadgets(finalG, false); |
addGadgets(finalG, false); |
2286 |
|
|
2287 |
finalG.dispose(); |
finalG.dispose(); |
2288 |
|
|
2443 |
// BB umrechnen von Layer-CRS in Map-CRS |
// BB umrechnen von Layer-CRS in Map-CRS |
2444 |
|
|
2445 |
// Expand a bit |
// Expand a bit |
2446 |
bounds.expandBy(bounds.getWidth() / 6., bounds.getHeight() / 6.); |
addDefaultMargin(bounds); |
2447 |
|
|
2448 |
setMapArea(bounds); |
setMapArea(bounds); |
2449 |
} |
} |
2450 |
} |
} |
2451 |
|
|
2452 |
|
private ReferencedEnvelope addDefaultMargin(ReferencedEnvelope bounds) { |
2453 |
|
return JTSUtil.expandEnvelope(bounds, Math.max(0, |
2454 |
|
defaultMaxMapExtendMode)); |
2455 |
|
} |
2456 |
|
|
2457 |
|
private Envelope addDefaultMargin(Envelope bounds) { |
2458 |
|
return JTSUtil.expandEnvelope(bounds, Math.max(0, |
2459 |
|
defaultMaxMapExtendMode)); |
2460 |
|
} |
2461 |
|
|
2462 |
/** |
/** |
2463 |
* Zooms towards a point. |
* Zooms towards a point. |
2464 |
* |
* |
2606 |
// genau auf dem Rand der angezeigten Flaeche) |
// genau auf dem Rand der angezeigten Flaeche) |
2607 |
|
|
2608 |
if (mapAreaNew != null) { |
if (mapAreaNew != null) { |
2609 |
mapAreaNew.expandBy(mapAreaNew.getWidth() * 0.1, mapAreaNew |
|
2610 |
.getHeight() * 0.1); |
mapAreaNew = addDefaultMargin(mapAreaNew); |
2611 |
setMapArea(mapAreaNew); |
setMapArea(mapAreaNew); |
2612 |
} else { |
} else { |
2613 |
LOGGER |
LOGGER |
2689 |
return imageOrigin; |
return imageOrigin; |
2690 |
} |
} |
2691 |
|
|
2692 |
|
/** |
2693 |
|
* If {@link #maxExtend} is <code>null</code> the following rules are used |
2694 |
|
* to create a default maximum. |
2695 |
|
* <ul> |
2696 |
|
* <li>Values < 0 : don't grow to fit the monitors aspect ratio, no |
2697 |
|
* margin</li> |
2698 |
|
* <li>Values 0 : grow to fit the monitors aspect ratio, no margin</li> |
2699 |
|
* <li>Values > 0 : grow to fit the monitors aspect ratio, and add a |
2700 |
|
* relative margin</li> |
2701 |
|
* </ul> |
2702 |
|
* **/ |
2703 |
|
public void setDefaultMaxMapExtendMode(double defaultMaxMapExtendMode) { |
2704 |
|
this.defaultMaxMapExtendMode = defaultMaxMapExtendMode; |
2705 |
|
} |
2706 |
|
|
2707 |
|
/** |
2708 |
|
* If {@link #maxExtend} is <code>null</code> the following rules are used |
2709 |
|
* to create a default maximum. |
2710 |
|
* <ul> |
2711 |
|
* <li>Values < 0 : don't grow to fit the monitors aspect ratio, no |
2712 |
|
* margin</li> |
2713 |
|
* <li>Values 0 : grow to fit the monitors aspect ratio, no margin</li> |
2714 |
|
* <li>Values > 0 : grow to fit the monitors aspect ratio, and add a |
2715 |
|
* relative margin</li> |
2716 |
|
* </ul> |
2717 |
|
* **/ |
2718 |
|
public double getDefaultMaxMapExtendMode() { |
2719 |
|
return defaultMaxMapExtendMode; |
2720 |
|
} |
2721 |
|
|
2722 |
|
final static int BLINK_TIMER_DEPLAY = 800; |
2723 |
|
|
2724 |
|
private Timer initBlinkTimer() { |
2725 |
|
Timer timer = new Timer(BLINK_TIMER_DEPLAY, new ActionListener() { |
2726 |
|
|
2727 |
|
@Override |
2728 |
|
public void actionPerformed(ActionEvent e) { |
2729 |
|
XMapPane.this.repaint(300); |
2730 |
|
} |
2731 |
|
}); |
2732 |
|
timer.setDelay(BLINK_TIMER_DEPLAY); |
2733 |
|
timer.setRepeats(false); |
2734 |
|
return timer; |
2735 |
|
} |
2736 |
|
|
2737 |
|
/** |
2738 |
|
* Makes the given {@link FeatureCollection} bink in the map for a moment |
2739 |
|
*/ |
2740 |
|
public void blink( |
2741 |
|
FeatureCollection<SimpleFeatureType, SimpleFeature> features) { |
2742 |
|
{ |
2743 |
|
blinkTimer.stop(); |
2744 |
|
repaint(); |
2745 |
|
blinkTimer = initBlinkTimer(); |
2746 |
|
|
2747 |
|
DefaultMapContext mc = new DefaultMapContext(getMapContext() |
2748 |
|
.getCoordinateReferenceSystem()); |
2749 |
|
|
2750 |
|
Style style = StylingUtil.STYLE_FACTORY.createStyle(); |
2751 |
|
style.featureTypeStyles().add( |
2752 |
|
StylingUtil.createBlinkFeatureTypeStyle(features)); |
2753 |
|
|
2754 |
|
// style = StylingUtil.createStyleSimple(features, Color.pink, |
2755 |
|
// Color.WHITE); |
2756 |
|
|
2757 |
|
DefaultMapLayer dml = new DefaultMapLayer(features, style); |
2758 |
|
mc.addLayer(dml); |
2759 |
|
|
2760 |
|
GTRenderer renderer = new StreamingRenderer(); |
2761 |
|
|
2762 |
|
renderer.setJava2DHints(getJava2dHints()); |
2763 |
|
|
2764 |
|
renderer.setContext(mc); |
2765 |
|
|
2766 |
|
Graphics2D g2d = (Graphics2D) getGraphics(); |
2767 |
|
renderer.paint(g2d, getVisibleRect(), getMapArea()); |
2768 |
|
|
2769 |
|
blinkTimer.start(); |
2770 |
|
|
2771 |
|
} |
2772 |
|
|
2773 |
|
} |
2774 |
|
|
2775 |
} |
} |