gvsig-3d / 2.1 / trunk / org.gvsig.view3d / org.gvsig.view3d.swing / org.gvsig.view3d.swing.impl / src / main / java / org / gvsig / view3d / swing / impl / data / GvSIGLayerDataRaster.java @ 466
History | View | Annotate | Download (12.3 KB)
1 | 446 | llmarques | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | *
|
||
4 | * Copyright ? 2007-2015 gvSIG Association
|
||
5 | *
|
||
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | * as published by the Free Software Foundation; either version 2
|
||
9 | * of the License, or (at your option) any later version.
|
||
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
19 | * MA 02110-1301, USA.
|
||
20 | *
|
||
21 | * For any additional information, do not hesitate to contact us
|
||
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | */
|
||
24 | |||
25 | package org.gvsig.view3d.swing.impl.data; |
||
26 | |||
27 | import gov.nasa.worldwind.WWObjectImpl; |
||
28 | import gov.nasa.worldwind.avlist.AVKey; |
||
29 | import gov.nasa.worldwind.avlist.AVList; |
||
30 | import gov.nasa.worldwind.data.BufferedImageRaster; |
||
31 | import gov.nasa.worldwind.data.DataRaster; |
||
32 | import gov.nasa.worldwind.geom.Sector; |
||
33 | |||
34 | 457 | llmarques | import java.awt.Dimension; |
35 | 446 | llmarques | import java.awt.Graphics2D; |
36 | import java.awt.Rectangle; |
||
37 | import java.awt.geom.AffineTransform; |
||
38 | import java.awt.geom.Point2D; |
||
39 | import java.awt.image.BufferedImage; |
||
40 | |||
41 | import org.cresques.cts.ICoordTrans; |
||
42 | import org.cresques.cts.IProjection; |
||
43 | 457 | llmarques | import org.slf4j.Logger; |
44 | import org.slf4j.LoggerFactory; |
||
45 | 446 | llmarques | import org.gvsig.fmap.crs.CRSFactory; |
46 | import org.gvsig.fmap.dal.exception.ReadException; |
||
47 | import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
||
48 | import org.gvsig.fmap.geom.GeometryLocator; |
||
49 | import org.gvsig.fmap.geom.GeometryManager; |
||
50 | import org.gvsig.fmap.geom.exception.CreateEnvelopeException; |
||
51 | import org.gvsig.fmap.geom.primitive.Envelope; |
||
52 | import org.gvsig.fmap.mapcontext.MapContext; |
||
53 | import org.gvsig.fmap.mapcontext.ViewPort; |
||
54 | import org.gvsig.fmap.mapcontext.layers.FLayer; |
||
55 | 466 | llmarques | import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect; |
56 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelable; |
||
57 | 446 | llmarques | import org.gvsig.tools.task.Cancellable; |
58 | |||
59 | /**
|
||
60 | * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
|
||
61 | *
|
||
62 | */
|
||
63 | @SuppressWarnings("deprecation") |
||
64 | public class GvSIGLayerDataRaster extends WWObjectImpl implements DataRaster { |
||
65 | |||
66 | 457 | llmarques | private static final Logger LOG = LoggerFactory |
67 | .getLogger(GvSIGLayerDataRaster.class); |
||
68 | |||
69 | 446 | llmarques | private MapContext mapContext;
|
70 | private FLayer layer;
|
||
71 | |||
72 | /**
|
||
73 | *
|
||
74 | */
|
||
75 | public GvSIGLayerDataRaster(MapContext mapContext, FLayer theLayer,
|
||
76 | AVList params) { |
||
77 | |||
78 | if (params == null || mapContext == null || theLayer == null) { |
||
79 | throw new IllegalArgumentException(); |
||
80 | } |
||
81 | |||
82 | this.layer = theLayer;
|
||
83 | this.mapContext = mapContext;
|
||
84 | this.setValues(params.copy());
|
||
85 | } |
||
86 | |||
87 | public void dispose() { |
||
88 | 457 | llmarques | //TODO
|
89 | 446 | llmarques | } |
90 | |||
91 | public int getWidth() { |
||
92 | return (Integer) this.getValue(AVKey.WIDTH); |
||
93 | } |
||
94 | |||
95 | public int getHeight() { |
||
96 | return (Integer) this.getValue(AVKey.HEIGHT); |
||
97 | } |
||
98 | |||
99 | public Sector getSector() {
|
||
100 | |||
101 | return (Sector) this.getValue(AVKey.SECTOR); |
||
102 | |||
103 | } |
||
104 | |||
105 | public void drawOnTo(DataRaster canvas) { |
||
106 | |||
107 | if (canvas == null) { |
||
108 | throw new IllegalArgumentException(); |
||
109 | } |
||
110 | |||
111 | 457 | llmarques | if (!canvas.getSector().intersects(getSector())) {
|
112 | 446 | llmarques | return;
|
113 | } |
||
114 | |||
115 | 457 | llmarques | Sector overlap = this.getSector().intersection(canvas.getSector());
|
116 | |||
117 | 446 | llmarques | ViewPort viewPort = new ViewPort(mapContext.getProjection());
|
118 | 457 | llmarques | |
119 | // Set adjustable to false to avoid problems with adjusted envelope
|
||
120 | viewPort.setAdjustable(false);
|
||
121 | |||
122 | 446 | llmarques | GeometryManager geoManager = GeometryLocator.getGeometryManager(); |
123 | |||
124 | Envelope envelope = null;
|
||
125 | 457 | llmarques | double[] degrees = overlap.asDegreesArray(); |
126 | |||
127 | 446 | llmarques | try {
|
128 | |||
129 | 458 | llmarques | IProjection projection = mapContext.getProjection(); |
130 | 446 | llmarques | |
131 | ICoordTrans ct = CRSFactory.getCRS("EPSG:4326").getCT(projection);
|
||
132 | 457 | llmarques | Point2D p1 = convert(ct, new Point2D.Double(degrees[2], degrees[0])); |
133 | Point2D p2 = convert(ct, new Point2D.Double(degrees[3], degrees[1])); |
||
134 | 446 | llmarques | |
135 | envelope = |
||
136 | geoManager.createEnvelope(Math.min(p1.getX(), p2.getX()),
|
||
137 | Math.min(p1.getY(), p2.getY()),
|
||
138 | Math.max(p1.getX(), p2.getX()),
|
||
139 | Math.max(p1.getY(), p2.getY()), SUBTYPES.GEOM2D);
|
||
140 | 457 | llmarques | |
141 | /**
|
||
142 | * Check if request tile intersect with layer envelope to avoid
|
||
143 | * the creation of useless tiles.
|
||
144 | */
|
||
145 | if (!envelope.intersects(layer.getFullEnvelope())) {
|
||
146 | return;
|
||
147 | } |
||
148 | 446 | llmarques | |
149 | 457 | llmarques | viewPort.setEnvelope(envelope); |
150 | |||
151 | 446 | llmarques | } catch (CreateEnvelopeException e) {
|
152 | 457 | llmarques | LOG.error( |
153 | "Can't create envelope from sector tile: minLat {} maxLat {} minLon {} maxLon {}",
|
||
154 | new Object[] { degrees[0], degrees[1], degrees[2], degrees[3] }); |
||
155 | return;
|
||
156 | } catch (ReadException e) {
|
||
157 | LOG.warn("Can't get full envelope of {}", layer.getInfoString());
|
||
158 | 446 | llmarques | } |
159 | |||
160 | 457 | llmarques | int canvasWidth = canvas.getWidth();
|
161 | int canvasHeight = canvas.getHeight();
|
||
162 | 446 | llmarques | |
163 | 457 | llmarques | java.awt.Rectangle clipRect = this.computeClipRect(overlap, this); |
164 | if (null == clipRect || clipRect.width == 0 || clipRect.height == 0) { |
||
165 | return;
|
||
166 | } |
||
167 | |||
168 | // Apply the transform that correctly maps the image onto the canvas.
|
||
169 | java.awt.geom.AffineTransform affineTransform = |
||
170 | this.computeSourceToDestTransform(clipRect.width, clipRect.height,
|
||
171 | overlap, canvasWidth, canvasHeight, canvas.getSector()); |
||
172 | |||
173 | // Trick to apply transform to size value
|
||
174 | Point2D srcSizePoint =
|
||
175 | new Point2D.Double(clipRect.width, clipRect.height); |
||
176 | Point2D dstSizePoint = new Point2D.Double(); |
||
177 | |||
178 | affineTransform.transform(srcSizePoint, dstSizePoint); |
||
179 | |||
180 | int clipWidth =
|
||
181 | (int) Math.ceil((dstSizePoint.getX() >= canvasWidth) ? canvasWidth |
||
182 | : dstSizePoint.getX()); |
||
183 | int clipHeight =
|
||
184 | (int) Math.ceil((dstSizePoint.getY() >= canvasHeight) |
||
185 | ? canvasHeight : dstSizePoint.getY()); |
||
186 | |||
187 | if (clipWidth <= 0 || clipHeight <= 0) { |
||
188 | return;
|
||
189 | } |
||
190 | |||
191 | 446 | llmarques | BufferedImage image =
|
192 | 457 | llmarques | new BufferedImage(clipWidth, clipHeight, |
193 | BufferedImage.TYPE_INT_ARGB);
|
||
194 | 446 | llmarques | |
195 | 457 | llmarques | viewPort.setImageSize(new Dimension(clipWidth, clipHeight)); |
196 | viewPort.refreshExtent(); |
||
197 | |||
198 | 446 | llmarques | try {
|
199 | 466 | llmarques | |
200 | 446 | llmarques | layer.draw(image, (Graphics2D) image.getGraphics(), viewPort,
|
201 | 466 | llmarques | getCancel(), getScale(viewPort)); |
202 | |||
203 | if (layer instanceof FLyrVect && layer instanceof ILabelable) { |
||
204 | |||
205 | ILabelable labelable = (ILabelable) layer; |
||
206 | |||
207 | if (labelable.isLabeled()
|
||
208 | && labelable.getLabelingStrategy() != null
|
||
209 | && labelable.getLabelingStrategy().shouldDrawLabels( |
||
210 | getScale(viewPort))) { |
||
211 | |||
212 | labelable.drawLabels(image, (Graphics2D) image
|
||
213 | .getGraphics(), viewPort, getCancel(), |
||
214 | getScale(viewPort), mapContext.getViewPort().getDPI()); |
||
215 | } |
||
216 | } |
||
217 | 446 | llmarques | |
218 | } catch (ReadException e) {
|
||
219 | 457 | llmarques | LOG.warn( |
220 | "Can't draw required zone of layer {}, can't read legend",
|
||
221 | layer.getInfoString()); |
||
222 | return;
|
||
223 | 446 | llmarques | } |
224 | BufferedImageRaster bufferedImageRaster = |
||
225 | new BufferedImageRaster(overlap, image);
|
||
226 | bufferedImageRaster.drawOnTo(canvas); |
||
227 | 457 | llmarques | |
228 | 446 | llmarques | } |
229 | 457 | llmarques | |
230 | private Point2D convert(ICoordTrans ct, Point2D srcPoint){ |
||
231 | if(ct == null){ |
||
232 | return srcPoint;
|
||
233 | } |
||
234 | return ct.convert(srcPoint, null); |
||
235 | } |
||
236 | 446 | llmarques | |
237 | 457 | llmarques | private java.awt.geom.AffineTransform computeSourceToDestTransform(
|
238 | int sourceWidth, int sourceHeight, Sector sourceSector, int destWidth, |
||
239 | int destHeight, Sector destSector) {
|
||
240 | // Compute the the transform from source to destination coordinates. In
|
||
241 | // this computation a pixel is assumed
|
||
242 | // to cover a finite area.
|
||
243 | |||
244 | double ty =
|
||
245 | destHeight |
||
246 | * -(sourceSector.getMaxLatitude().degrees - destSector |
||
247 | .getMaxLatitude().degrees) |
||
248 | / destSector.getDeltaLatDegrees(); |
||
249 | double tx =
|
||
250 | destWidth |
||
251 | * (sourceSector.getMinLongitude().degrees - destSector |
||
252 | .getMinLongitude().degrees) |
||
253 | / destSector.getDeltaLonDegrees(); |
||
254 | |||
255 | double sy =
|
||
256 | ((double) destHeight / (double) sourceHeight) |
||
257 | * (sourceSector.getDeltaLatDegrees() / destSector |
||
258 | .getDeltaLatDegrees()); |
||
259 | double sx =
|
||
260 | ((double) destWidth / (double) sourceWidth) |
||
261 | * (sourceSector.getDeltaLonDegrees() / destSector |
||
262 | .getDeltaLonDegrees()); |
||
263 | |||
264 | java.awt.geom.AffineTransform transform = |
||
265 | new java.awt.geom.AffineTransform();
|
||
266 | transform.translate(tx, ty); |
||
267 | transform.scale(sx, sy); |
||
268 | return transform;
|
||
269 | } |
||
270 | |||
271 | 446 | llmarques | private double getScale(ViewPort viewPort) { |
272 | |||
273 | MapContext mapContextCloned = mapContext.cloneFMap(); |
||
274 | mapContextCloned.setViewPort(viewPort); |
||
275 | double scale = mapContextCloned.getScaleView();
|
||
276 | mapContextCloned.dispose(); |
||
277 | |||
278 | return scale;
|
||
279 | } |
||
280 | |||
281 | private Rectangle computeClipRect(Sector clipSector, |
||
282 | DataRaster clippedRaster) { |
||
283 | |||
284 | AffineTransform geographicToRaster =
|
||
285 | this.computeGeographicToRasterTransform(clippedRaster.getWidth(),
|
||
286 | clippedRaster.getHeight(), clippedRaster.getSector()); |
||
287 | |||
288 | java.awt.geom.Point2D geoPoint = new java.awt.geom.Point2D.Double();
|
||
289 | java.awt.geom.Point2D ul = new java.awt.geom.Point2D.Double();
|
||
290 | java.awt.geom.Point2D lr = new java.awt.geom.Point2D.Double();
|
||
291 | |||
292 | geoPoint.setLocation(clipSector.getMinLongitude().degrees, |
||
293 | clipSector.getMaxLatitude().degrees); |
||
294 | geographicToRaster.transform(geoPoint, ul); |
||
295 | |||
296 | geoPoint.setLocation(clipSector.getMaxLongitude().degrees, |
||
297 | clipSector.getMinLatitude().degrees); |
||
298 | geographicToRaster.transform(geoPoint, lr); |
||
299 | |||
300 | int x = (int) Math.floor(ul.getX()); |
||
301 | int y = (int) Math.floor(ul.getY()); |
||
302 | int width = (int) Math.ceil(lr.getX() - ul.getX()); |
||
303 | int height = (int) Math.ceil(lr.getY() - ul.getY()); |
||
304 | |||
305 | return new Rectangle(x, y, width, height); |
||
306 | } |
||
307 | |||
308 | private java.awt.geom.AffineTransform computeGeographicToRasterTransform(
|
||
309 | int width, int height, Sector sector) { |
||
310 | // Compute the the transform from geographic to raster coordinates. In
|
||
311 | // this computation a pixel is assumed
|
||
312 | // to cover a finite area.
|
||
313 | |||
314 | double ty = -sector.getMaxLatitude().degrees;
|
||
315 | double tx = -sector.getMinLongitude().degrees;
|
||
316 | |||
317 | double sy = -(height / sector.getDeltaLatDegrees());
|
||
318 | double sx = (width / sector.getDeltaLonDegrees());
|
||
319 | |||
320 | java.awt.geom.AffineTransform transform = |
||
321 | new java.awt.geom.AffineTransform();
|
||
322 | transform.scale(sx, sy); |
||
323 | transform.translate(tx, ty); |
||
324 | return transform;
|
||
325 | } |
||
326 | |||
327 | public DataRaster getSubRaster(AVList params) {
|
||
328 | int width = (Integer) params.getValue(AVKey.WIDTH); |
||
329 | int height = (Integer) params.getValue(AVKey.HEIGHT); |
||
330 | Sector sector = (Sector) params.getValue(AVKey.SECTOR); |
||
331 | |||
332 | return this.getSubRaster(width, height, sector, params); |
||
333 | } |
||
334 | |||
335 | public DataRaster getSubRaster(int width, int height, Sector sector, |
||
336 | AVList params) { |
||
337 | |||
338 | params.setValue(AVKey.WIDTH, width); |
||
339 | params.setValue(AVKey.HEIGHT, height); |
||
340 | params.setValue(AVKey.SECTOR, sector); |
||
341 | |||
342 | GvSIGLayerDataRaster subRaster = |
||
343 | new GvSIGLayerDataRaster(mapContext, layer, params);
|
||
344 | return subRaster;
|
||
345 | } |
||
346 | 466 | llmarques | |
347 | private Cancellable getCancel(){
|
||
348 | Cancellable cancel = new Cancellable() {
|
||
349 | |||
350 | private boolean canceled = false; |
||
351 | |||
352 | public void setCanceled(boolean flag) { |
||
353 | canceled = flag; |
||
354 | } |
||
355 | |||
356 | public boolean isCanceled() { |
||
357 | return canceled;
|
||
358 | } |
||
359 | }; |
||
360 | |||
361 | return cancel;
|
||
362 | } |
||
363 | 446 | llmarques | } |