Statistics
| Revision:

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 @ 457

History | View | Annotate | Download (11.5 KB)

1
/**
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
import java.awt.Dimension;
35
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
import org.slf4j.Logger;
44
import org.slf4j.LoggerFactory;
45

    
46
import org.gvsig.fmap.crs.CRSFactory;
47
import org.gvsig.fmap.dal.exception.ReadException;
48
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
49
import org.gvsig.fmap.geom.GeometryLocator;
50
import org.gvsig.fmap.geom.GeometryManager;
51
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
52
import org.gvsig.fmap.geom.primitive.Envelope;
53
import org.gvsig.fmap.mapcontext.MapContext;
54
import org.gvsig.fmap.mapcontext.ViewPort;
55
import org.gvsig.fmap.mapcontext.layers.FLayer;
56
import org.gvsig.tools.task.Cancellable;
57

    
58
/**
59
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
60
 *
61
 */
62
@SuppressWarnings("deprecation")
63
public class GvSIGLayerDataRaster extends WWObjectImpl implements DataRaster {
64

    
65
    private static final Logger LOG = LoggerFactory
66
        .getLogger(GvSIGLayerDataRaster.class);
67

    
68
    private MapContext mapContext;
69
    private FLayer layer;
70

    
71
    /**
72
     * 
73
     */
74
    public GvSIGLayerDataRaster(MapContext mapContext, FLayer theLayer,
75
        AVList params) {
76

    
77
        if (params == null || mapContext == null || theLayer == null) {
78
            throw new IllegalArgumentException();
79
        }
80

    
81
        this.layer = theLayer;
82
        this.mapContext = mapContext;
83
        this.setValues(params.copy());
84
    }
85

    
86
    public void dispose() {
87
        //TODO
88
    }
89

    
90
    public int getWidth() {
91
        return (Integer) this.getValue(AVKey.WIDTH);
92
    }
93

    
94
    public int getHeight() {
95
        return (Integer) this.getValue(AVKey.HEIGHT);
96
    }
97

    
98
    public Sector getSector() {
99

    
100
        return (Sector) this.getValue(AVKey.SECTOR);
101

    
102
    }
103

    
104
    public void drawOnTo(DataRaster canvas) {
105

    
106
        if (canvas == null) {
107
            throw new IllegalArgumentException();
108
        }
109

    
110
        if (!canvas.getSector().intersects(getSector())) {
111
            return;
112
        }
113

    
114
        Sector overlap = this.getSector().intersection(canvas.getSector());
115

    
116
        ViewPort viewPort = new ViewPort(mapContext.getProjection());
117

    
118
        // Set adjustable to false to avoid problems with adjusted envelope
119
        viewPort.setAdjustable(false);
120

    
121
        GeometryManager geoManager = GeometryLocator.getGeometryManager();
122

    
123
        Envelope envelope = null;
124
        double[] degrees = overlap.asDegreesArray();
125

    
126
        try {
127

    
128
            IProjection projection = layer.getProjection();
129

    
130
            if (projection == null) {
131
                projection = mapContext.getProjection();
132
            }
133

    
134
            ICoordTrans ct = CRSFactory.getCRS("EPSG:4326").getCT(projection);
135
            Point2D p1 = convert(ct, new Point2D.Double(degrees[2], degrees[0]));
136
            Point2D p2 = convert(ct, new Point2D.Double(degrees[3], degrees[1]));
137

    
138
            envelope =
139
                geoManager.createEnvelope(Math.min(p1.getX(), p2.getX()),
140
                    Math.min(p1.getY(), p2.getY()),
141
                    Math.max(p1.getX(), p2.getX()),
142
                    Math.max(p1.getY(), p2.getY()), SUBTYPES.GEOM2D);
143
            
144
            /**
145
             *  Check if request tile intersect with layer envelope to avoid
146
             *  the creation of useless tiles. 
147
             */
148
            if (!envelope.intersects(layer.getFullEnvelope())) {
149
                return;
150
            }
151

    
152
            viewPort.setEnvelope(envelope);
153

    
154
        } catch (CreateEnvelopeException e) {
155
            LOG.error(
156
                "Can't create envelope from sector tile:  minLat {} maxLat {} minLon {} maxLon {}",
157
                new Object[] { degrees[0], degrees[1], degrees[2], degrees[3] });
158
            return;
159
        } catch (ReadException e) {
160
            LOG.warn("Can't get full envelope of {}", layer.getInfoString());
161
        }
162

    
163
        int canvasWidth = canvas.getWidth();
164
        int canvasHeight = canvas.getHeight();
165

    
166
        java.awt.Rectangle clipRect = this.computeClipRect(overlap, this);
167
        if (null == clipRect || clipRect.width == 0 || clipRect.height == 0) {
168
            return;
169
        }
170

    
171
        // Apply the transform that correctly maps the image onto the canvas.
172
        java.awt.geom.AffineTransform affineTransform =
173
            this.computeSourceToDestTransform(clipRect.width, clipRect.height,
174
                overlap, canvasWidth, canvasHeight, canvas.getSector());
175

    
176
        // Trick to apply transform to size value
177
        Point2D srcSizePoint =
178
            new Point2D.Double(clipRect.width, clipRect.height);
179
        Point2D dstSizePoint = new Point2D.Double();
180

    
181
        affineTransform.transform(srcSizePoint, dstSizePoint);
182

    
183
        int clipWidth =
184
            (int) Math.ceil((dstSizePoint.getX() >= canvasWidth) ? canvasWidth
185
                : dstSizePoint.getX());
186
        int clipHeight =
187
            (int) Math.ceil((dstSizePoint.getY() >= canvasHeight)
188
                ? canvasHeight : dstSizePoint.getY());
189

    
190
        if (clipWidth <= 0 || clipHeight <= 0) {
191
            return;
192
        }
193

    
194
        BufferedImage image =
195
            new BufferedImage(clipWidth, clipHeight,
196
                BufferedImage.TYPE_INT_ARGB);
197

    
198
        viewPort.setImageSize(new Dimension(clipWidth, clipHeight));
199
        viewPort.refreshExtent();
200

    
201
        try {
202
            layer.draw(image, (Graphics2D) image.getGraphics(), viewPort,
203
                new Cancellable() {
204

    
205
                    private boolean canceled = false;
206

    
207
                    public void setCanceled(boolean flag) {
208
                        canceled = flag;
209
                    }
210

    
211
                    public boolean isCanceled() {
212
                        return canceled;
213
                    }
214
                }, getScale(viewPort));
215

    
216
        } catch (ReadException e) {
217
            LOG.warn(
218
                "Can't draw required zone of layer {}, can't read legend",
219
                layer.getInfoString());
220
            return;
221
        }
222

    
223
        BufferedImageRaster bufferedImageRaster =
224
            new BufferedImageRaster(overlap, image);
225
        bufferedImageRaster.drawOnTo(canvas);
226

    
227
    }
228
    
229
    private Point2D convert(ICoordTrans ct, Point2D srcPoint){
230
        if(ct == null){
231
            return srcPoint;
232
        }
233
        return ct.convert(srcPoint, null);
234
    }
235

    
236
    private java.awt.geom.AffineTransform computeSourceToDestTransform(
237
        int sourceWidth, int sourceHeight, Sector sourceSector, int destWidth,
238
        int destHeight, Sector destSector) {
239
        // Compute the the transform from source to destination coordinates. In
240
        // this computation a pixel is assumed
241
        // to cover a finite area.
242

    
243
        double ty =
244
            destHeight
245
                * -(sourceSector.getMaxLatitude().degrees - destSector
246
                    .getMaxLatitude().degrees)
247
                / destSector.getDeltaLatDegrees();
248
        double tx =
249
            destWidth
250
                * (sourceSector.getMinLongitude().degrees - destSector
251
                    .getMinLongitude().degrees)
252
                / destSector.getDeltaLonDegrees();
253

    
254
        double sy =
255
            ((double) destHeight / (double) sourceHeight)
256
                * (sourceSector.getDeltaLatDegrees() / destSector
257
                    .getDeltaLatDegrees());
258
        double sx =
259
            ((double) destWidth / (double) sourceWidth)
260
                * (sourceSector.getDeltaLonDegrees() / destSector
261
                    .getDeltaLonDegrees());
262

    
263
        java.awt.geom.AffineTransform transform =
264
            new java.awt.geom.AffineTransform();
265
        transform.translate(tx, ty);
266
        transform.scale(sx, sy);
267
        return transform;
268
    }
269

    
270
    private double getScale(ViewPort viewPort) {
271

    
272
        MapContext mapContextCloned = mapContext.cloneFMap();
273
        mapContextCloned.setViewPort(viewPort);
274
        double scale = mapContextCloned.getScaleView();
275
        mapContextCloned.dispose();
276

    
277
        return scale;
278
    }
279

    
280
    private Rectangle computeClipRect(Sector clipSector,
281
        DataRaster clippedRaster) {
282

    
283
        AffineTransform geographicToRaster =
284
            this.computeGeographicToRasterTransform(clippedRaster.getWidth(),
285
                clippedRaster.getHeight(), clippedRaster.getSector());
286

    
287
        java.awt.geom.Point2D geoPoint = new java.awt.geom.Point2D.Double();
288
        java.awt.geom.Point2D ul = new java.awt.geom.Point2D.Double();
289
        java.awt.geom.Point2D lr = new java.awt.geom.Point2D.Double();
290

    
291
        geoPoint.setLocation(clipSector.getMinLongitude().degrees,
292
            clipSector.getMaxLatitude().degrees);
293
        geographicToRaster.transform(geoPoint, ul);
294

    
295
        geoPoint.setLocation(clipSector.getMaxLongitude().degrees,
296
            clipSector.getMinLatitude().degrees);
297
        geographicToRaster.transform(geoPoint, lr);
298

    
299
        int x = (int) Math.floor(ul.getX());
300
        int y = (int) Math.floor(ul.getY());
301
        int width = (int) Math.ceil(lr.getX() - ul.getX());
302
        int height = (int) Math.ceil(lr.getY() - ul.getY());
303

    
304
        return new Rectangle(x, y, width, height);
305
    }
306

    
307
    private java.awt.geom.AffineTransform computeGeographicToRasterTransform(
308
        int width, int height, Sector sector) {
309
        // Compute the the transform from geographic to raster coordinates. In
310
        // this computation a pixel is assumed
311
        // to cover a finite area.
312

    
313
        double ty = -sector.getMaxLatitude().degrees;
314
        double tx = -sector.getMinLongitude().degrees;
315

    
316
        double sy = -(height / sector.getDeltaLatDegrees());
317
        double sx = (width / sector.getDeltaLonDegrees());
318

    
319
        java.awt.geom.AffineTransform transform =
320
            new java.awt.geom.AffineTransform();
321
        transform.scale(sx, sy);
322
        transform.translate(tx, ty);
323
        return transform;
324
    }
325

    
326
    public DataRaster getSubRaster(AVList params) {
327
        int width = (Integer) params.getValue(AVKey.WIDTH);
328
        int height = (Integer) params.getValue(AVKey.HEIGHT);
329
        Sector sector = (Sector) params.getValue(AVKey.SECTOR);
330

    
331
        return this.getSubRaster(width, height, sector, params);
332
    }
333

    
334
    public DataRaster getSubRaster(int width, int height, Sector sector,
335
        AVList params) {
336

    
337
        params.setValue(AVKey.WIDTH, width);
338
        params.setValue(AVKey.HEIGHT, height);
339
        params.setValue(AVKey.SECTOR, sector);
340

    
341
        GvSIGLayerDataRaster subRaster =
342
            new GvSIGLayerDataRaster(mapContext, layer, params);
343
        return subRaster;
344
    }
345
}