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

History | View | Annotate | Download (11.4 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 = mapContext.getProjection();
129

    
130
            ICoordTrans ct = CRSFactory.getCRS("EPSG:4326").getCT(projection);
131
            Point2D p1 = convert(ct, new Point2D.Double(degrees[2], degrees[0]));
132
            Point2D p2 = convert(ct, new Point2D.Double(degrees[3], degrees[1]));
133

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

    
148
            viewPort.setEnvelope(envelope);
149

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

    
159
        int canvasWidth = canvas.getWidth();
160
        int canvasHeight = canvas.getHeight();
161

    
162
        java.awt.Rectangle clipRect = this.computeClipRect(overlap, this);
163
        if (null == clipRect || clipRect.width == 0 || clipRect.height == 0) {
164
            return;
165
        }
166

    
167
        // Apply the transform that correctly maps the image onto the canvas.
168
        java.awt.geom.AffineTransform affineTransform =
169
            this.computeSourceToDestTransform(clipRect.width, clipRect.height,
170
                overlap, canvasWidth, canvasHeight, canvas.getSector());
171

    
172
        // Trick to apply transform to size value
173
        Point2D srcSizePoint =
174
            new Point2D.Double(clipRect.width, clipRect.height);
175
        Point2D dstSizePoint = new Point2D.Double();
176

    
177
        affineTransform.transform(srcSizePoint, dstSizePoint);
178

    
179
        int clipWidth =
180
            (int) Math.ceil((dstSizePoint.getX() >= canvasWidth) ? canvasWidth
181
                : dstSizePoint.getX());
182
        int clipHeight =
183
            (int) Math.ceil((dstSizePoint.getY() >= canvasHeight)
184
                ? canvasHeight : dstSizePoint.getY());
185

    
186
        if (clipWidth <= 0 || clipHeight <= 0) {
187
            return;
188
        }
189

    
190
        BufferedImage image =
191
            new BufferedImage(clipWidth, clipHeight,
192
                BufferedImage.TYPE_INT_ARGB);
193

    
194
        viewPort.setImageSize(new Dimension(clipWidth, clipHeight));
195
        viewPort.refreshExtent();
196

    
197
        try {
198
            layer.draw(image, (Graphics2D) image.getGraphics(), viewPort,
199
                new Cancellable() {
200

    
201
                    private boolean canceled = false;
202

    
203
                    public void setCanceled(boolean flag) {
204
                        canceled = flag;
205
                    }
206

    
207
                    public boolean isCanceled() {
208
                        return canceled;
209
                    }
210
                }, getScale(viewPort));
211

    
212
        } catch (ReadException e) {
213
            LOG.warn(
214
                "Can't draw required zone of layer {}, can't read legend",
215
                layer.getInfoString());
216
            return;
217
        }
218

    
219
        BufferedImageRaster bufferedImageRaster =
220
            new BufferedImageRaster(overlap, image);
221
        bufferedImageRaster.drawOnTo(canvas);
222

    
223
    }
224
    
225
    private Point2D convert(ICoordTrans ct, Point2D srcPoint){
226
        if(ct == null){
227
            return srcPoint;
228
        }
229
        return ct.convert(srcPoint, null);
230
    }
231

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

    
239
        double ty =
240
            destHeight
241
                * -(sourceSector.getMaxLatitude().degrees - destSector
242
                    .getMaxLatitude().degrees)
243
                / destSector.getDeltaLatDegrees();
244
        double tx =
245
            destWidth
246
                * (sourceSector.getMinLongitude().degrees - destSector
247
                    .getMinLongitude().degrees)
248
                / destSector.getDeltaLonDegrees();
249

    
250
        double sy =
251
            ((double) destHeight / (double) sourceHeight)
252
                * (sourceSector.getDeltaLatDegrees() / destSector
253
                    .getDeltaLatDegrees());
254
        double sx =
255
            ((double) destWidth / (double) sourceWidth)
256
                * (sourceSector.getDeltaLonDegrees() / destSector
257
                    .getDeltaLonDegrees());
258

    
259
        java.awt.geom.AffineTransform transform =
260
            new java.awt.geom.AffineTransform();
261
        transform.translate(tx, ty);
262
        transform.scale(sx, sy);
263
        return transform;
264
    }
265

    
266
    private double getScale(ViewPort viewPort) {
267

    
268
        MapContext mapContextCloned = mapContext.cloneFMap();
269
        mapContextCloned.setViewPort(viewPort);
270
        double scale = mapContextCloned.getScaleView();
271
        mapContextCloned.dispose();
272

    
273
        return scale;
274
    }
275

    
276
    private Rectangle computeClipRect(Sector clipSector,
277
        DataRaster clippedRaster) {
278

    
279
        AffineTransform geographicToRaster =
280
            this.computeGeographicToRasterTransform(clippedRaster.getWidth(),
281
                clippedRaster.getHeight(), clippedRaster.getSector());
282

    
283
        java.awt.geom.Point2D geoPoint = new java.awt.geom.Point2D.Double();
284
        java.awt.geom.Point2D ul = new java.awt.geom.Point2D.Double();
285
        java.awt.geom.Point2D lr = new java.awt.geom.Point2D.Double();
286

    
287
        geoPoint.setLocation(clipSector.getMinLongitude().degrees,
288
            clipSector.getMaxLatitude().degrees);
289
        geographicToRaster.transform(geoPoint, ul);
290

    
291
        geoPoint.setLocation(clipSector.getMaxLongitude().degrees,
292
            clipSector.getMinLatitude().degrees);
293
        geographicToRaster.transform(geoPoint, lr);
294

    
295
        int x = (int) Math.floor(ul.getX());
296
        int y = (int) Math.floor(ul.getY());
297
        int width = (int) Math.ceil(lr.getX() - ul.getX());
298
        int height = (int) Math.ceil(lr.getY() - ul.getY());
299

    
300
        return new Rectangle(x, y, width, height);
301
    }
302

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

    
309
        double ty = -sector.getMaxLatitude().degrees;
310
        double tx = -sector.getMinLongitude().degrees;
311

    
312
        double sy = -(height / sector.getDeltaLatDegrees());
313
        double sx = (width / sector.getDeltaLonDegrees());
314

    
315
        java.awt.geom.AffineTransform transform =
316
            new java.awt.geom.AffineTransform();
317
        transform.scale(sx, sy);
318
        transform.translate(tx, ty);
319
        return transform;
320
    }
321

    
322
    public DataRaster getSubRaster(AVList params) {
323
        int width = (Integer) params.getValue(AVKey.WIDTH);
324
        int height = (Integer) params.getValue(AVKey.HEIGHT);
325
        Sector sector = (Sector) params.getValue(AVKey.SECTOR);
326

    
327
        return this.getSubRaster(width, height, sector, params);
328
    }
329

    
330
    public DataRaster getSubRaster(int width, int height, Sector sector,
331
        AVList params) {
332

    
333
        params.setValue(AVKey.WIDTH, width);
334
        params.setValue(AVKey.HEIGHT, height);
335
        params.setValue(AVKey.SECTOR, sector);
336

    
337
        GvSIGLayerDataRaster subRaster =
338
            new GvSIGLayerDataRaster(mapContext, layer, params);
339
        return subRaster;
340
    }
341
}