Statistics
| Revision:

gvsig-3d / 2.1 / branches / org.gvsig.view3d_vector_and_extrusion_2.3 / org.gvsig.view3d / org.gvsig.view3d / org.gvsig.view3d.swing / org.gvsig.view3d.swing.impl / src / main / java / org / gvsig / view3d / swing / impl / layers / DefaultLayerConverter.java @ 736

History | View | Annotate | Download (21.2 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.layers;
26

    
27
import java.awt.geom.Point2D;
28
import java.security.MessageDigest;
29
import java.security.NoSuchAlgorithmException;
30

    
31
import org.cresques.cts.IProjection;
32
import org.slf4j.Logger;
33
import org.slf4j.LoggerFactory;
34

    
35
import org.gvsig.fmap.crs.CRSFactory;
36
import org.gvsig.fmap.dal.DataStoreParameters;
37
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
38
import org.gvsig.fmap.dal.coverage.grid.render.VisualPropertyListener;
39
import org.gvsig.fmap.dal.coverage.store.props.Statistics;
40
import org.gvsig.fmap.dal.exception.DataException;
41
import org.gvsig.fmap.geom.primitive.Envelope;
42
import org.gvsig.fmap.mapcontext.MapContextLocator;
43
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
44
import org.gvsig.fmap.mapcontext.layers.FLayer;
45
import org.gvsig.fmap.mapcontext.layers.operations.SingleLayer;
46
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
47
import org.gvsig.fmap.mapcontext.rendering.legend.IVectorLegend;
48
import org.gvsig.raster.fmap.layers.FLyrRaster;
49
import org.gvsig.raster.fmap.layers.ILayerState;
50
import org.gvsig.raster.fmap.layers.NotAvailableStateException;
51
import org.gvsig.view3d.lib.api.View3DLocator;
52
import org.gvsig.view3d.lib.api.View3DManager;
53
import org.gvsig.view3d.lib.api.loadingmodes.NwwLoaderFactory;
54
import org.gvsig.view3d.lib.api.properties.ElevationLayerProperties3D;
55
import org.gvsig.view3d.lib.api.properties.LayerProperties3D;
56
import org.gvsig.view3d.lib.api.properties.RasterLayerProperties3D;
57
import org.gvsig.view3d.lib.impl.layers.properties.DefaultElevationLayerProperties3D;
58
import org.gvsig.view3d.swing.api.MapControl3D;
59
import org.gvsig.view3d.swing.api.exceptions.ConversionLayerException;
60
import org.gvsig.view3d.swing.api.properties.NwwRasterLoaderFactory;
61
import org.gvsig.view3d.swing.impl.DefaultMapControl3D;
62
import org.gvsig.view3d.swing.impl.layers.loaders.ElevationLayerLoaderFactory;
63

    
64
import gov.nasa.worldwind.avlist.AVKey;
65
import gov.nasa.worldwind.avlist.AVList;
66
import gov.nasa.worldwind.avlist.AVListImpl;
67
import gov.nasa.worldwind.geom.Angle;
68
import gov.nasa.worldwind.geom.LatLon;
69
import gov.nasa.worldwind.geom.Sector;
70
import gov.nasa.worldwind.globes.ElevationModel;
71
import gov.nasa.worldwind.layers.Layer;
72
import gov.nasa.worldwind.terrain.BasicElevationModel;
73
import gov.nasa.worldwind.util.WWMath;
74

    
75
/**
76
 * Default implementation of {@link LayerConverter}.
77
 *
78
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
79
 */
80
public class DefaultLayerConverter implements LayerConverter {
81

    
82
    private static final Logger LOG = LoggerFactory.getLogger(DefaultLayerConverter.class);
83

    
84
    private final int DEFAULT_RASTERIZED_LEVEL_ZERO = 20;
85
    private final int DEFAULT_TILE_WIDTH = 512;
86
    private final int DEFAULT_TILE_HEIGHT = 512;
87

    
88
    private View3DManager manager = View3DLocator.getManager();
89

    
90
    public Layer convertToLayer(MapControl3D mapControl, FLayer layer) throws ConversionLayerException {
91

    
92
        IProjection projectionLayer = layer.getProjection();
93
        if(projectionLayer == null){
94
            projectionLayer = mapControl.getMapContext().getProjection();
95
        }
96

    
97
        if (layer.getCoordTrans() != null) {
98

    
99
            // Create new layer and configure it to be drawn projected on the fly
100
            try {
101
                layer = createNewProjectedOnTheFlyLayer(layer, projectionLayer);
102
            } catch (LoadLayerException e) {
103
                throw new ConversionLayerException("Can not create layer and set"
104
                    + " project on the fly configuration", e);
105
            }
106
        }
107

    
108
        //De aqu? hasta el final de m?todo lo que ten?a Andrea
109

    
110
        LayerProperties3D layerProperties = manager.getLayerProperties(layer, null);
111

    
112
        NwwLoaderFactory loadingFactory = manager.getLayerLoadingFactory(layer);
113
        if (loadingFactory instanceof NwwRasterLoaderFactory) {
114
            NwwRasterLoaderFactory rasterLoaderFactory = (NwwRasterLoaderFactory) loadingFactory;
115
            rasterLoaderFactory.setMapControl(mapControl);
116
        }
117
        Layer nwwLayer = loadingFactory.loadLayer(layerProperties);
118
        return nwwLayer;
119
    }
120

    
121
    public ElevationModel convertToElevationModel(MapControl3D mapControl, FLayer layer) {
122
        //FIXME:
123
        // Este m?todo lo ha tenido que refactorizar Andrea
124
        // ver qu? ha hecho y si se puede dejar as?
125
        LayerProperties3D layerProperties = manager.getLayerProperties(layer, null);
126

    
127
        NwwLoaderFactory loadingFactory = manager.getLayerLoadingFactory(layer);
128
        if (loadingFactory instanceof NwwRasterLoaderFactory) {
129
            NwwRasterLoaderFactory rasterLoaderFactory = (NwwRasterLoaderFactory) loadingFactory;
130
            rasterLoaderFactory.setMapControl(mapControl);
131
        }
132
        if (loadingFactory instanceof ElevationLayerLoaderFactory) {
133
            BasicElevationModel elevModel =
134
                ((ElevationLayerLoaderFactory) loadingFactory).loadElevationModel(layerProperties);
135
            return elevModel;
136
        }
137

    
138
        return null;
139
    }
140

    
141

    
142

    
143
    private FLayer createNewProjectedOnTheFlyLayer(FLayer layer, IProjection projectionLayer)
144
        throws LoadLayerException {
145

    
146
        LayerProperties3D oldLayerProperties =
147
            View3DLocator.getManager().getLayerProperties(layer, null);
148

    
149
        FLayer newLayer = null;
150
        DataStoreParameters parameters = null;
151
        if (layer instanceof FLyrVect) {
152
            FLyrVect layerVect = (FLyrVect) layer;
153
            parameters = layerVect.getFeatureStore().getParameters();
154
        } else if (layer instanceof FLyrRaster) {
155
            FLyrRaster layerRaster = (FLyrRaster) layer;
156
            parameters = layerRaster.getDataStore().getParameters();
157
        }
158

    
159
        newLayer =
160
            MapContextLocator.getMapContextManager().createLayer(layer.getName(), parameters);
161
        newLayer.setCoordTrans(projectionLayer.getCT(CRSFactory.getCRS("EPSG:4326")));
162

    
163
        // Set the same legend/render to new layer
164
        if(newLayer instanceof FLyrVect){
165
            ((FLyrVect) newLayer).setLegend((IVectorLegend) ((FLyrVect)layer).getLegend());
166
        } else if (newLayer instanceof FLyrRaster){
167

    
168
            // Set layer initialized and opened to avoid render configurations changes
169
            FLyrRaster rasterLayer = (FLyrRaster) newLayer;
170
            rasterLayer.setLayerInitialized(true);
171
            if(rasterLayer instanceof ILayerState){
172
                try {
173
                    ((ILayerState) rasterLayer).enableOpen();
174
                } catch (NotAvailableStateException e) {
175
                    throw new LoadLayerException(rasterLayer.getName(), e);
176
                }
177
            }
178

    
179
            rasterLayer.getDataStore().setRender(((FLyrRaster) layer).getRender());
180

    
181
            // Add layer to listen visual property changes. This is necessary
182
            // because we are initializing layer manually to avoid render filters changes.
183
            if(rasterLayer instanceof VisualPropertyListener){
184
                rasterLayer.getRender().addVisualPropertyListener((VisualPropertyListener) rasterLayer);
185
            }
186
        }
187

    
188
        View3DLocator.getManager().setLayerProperties(newLayer, oldLayerProperties);
189
        return newLayer;
190
    }
191

    
192

    
193

    
194
    private String getUniqueCacheId(FLayer layer) {
195
        // TODO This is not valid. We have to take in account more properties
196
        // to get unique cache id
197
        try {
198
            // Create MD5 Hash
199
            MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
200

    
201
            String name = layer.getName();
202
            long drawVersion = layer.getDrawVersion();
203
            String dataStoreFullName = null;
204
            if (layer instanceof SingleLayer) {
205
                dataStoreFullName = ((SingleLayer) layer).getDataStore().getFullName();
206
            }
207
            int hashCode = layer.hashCode();
208

    
209
            StringBuilder stb = new StringBuilder();
210
            stb.append(name);
211
            stb.append("$");
212
            stb.append(drawVersion);
213
            stb.append("$");
214
            stb.append(hashCode);
215
            stb.append("$");
216
            if (dataStoreFullName != null) {
217
                stb.append(dataStoreFullName);
218
                stb.append("$");
219
            }
220

    
221
            String id = stb.toString();
222
            digest.update(id.getBytes());
223
            byte messageDigest[] = digest.digest();
224

    
225
            // Create Hex String
226
            StringBuilder hexString = new StringBuilder();
227
            hexString.append(layer.getName());
228
            hexString.append("-");
229
            for (int i = 0; i < messageDigest.length; i++)
230
                hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
231
            return hexString.toString();
232

    
233
        } catch (NoSuchAlgorithmException e) {
234
            LOG.warn("MD5 algorith is not available", e);
235

    
236
            String name = layer.getName();
237
            long drawVersion = layer.getDrawVersion();
238
            String dataStoreFullName = null;
239
            if (layer instanceof SingleLayer) {
240
                dataStoreFullName = ((SingleLayer) layer).getDataStore().getFullName();
241
            }
242
            int hashCode = layer.hashCode();
243

    
244
            StringBuilder stb = new StringBuilder();
245
            stb.append(name);
246
            stb.append("$");
247
            stb.append(drawVersion);
248
            stb.append("$");
249
            stb.append(hashCode);
250
            stb.append("$");
251
            if (dataStoreFullName != null) {
252
                stb.append(dataStoreFullName);
253
                stb.append("$");
254
            }
255

    
256
            return stb.toString();
257
        }
258
    }
259

    
260
    private void createRasterTiledImageLayerParams(FLayer layer, AVList params,
261
        RasterLayerProperties3D layerProperties) {
262

    
263
        if (params == null) {
264
            params = new AVListImpl();
265
        }
266

    
267
        setBasicParameters(layer, params);
268

    
269
        setSectorParameters(layer, params);
270

    
271
        // Set resolution of layer
272
        params.setValue(AVKey.WIDTH, Integer.MAX_VALUE);
273
        params.setValue(AVKey.HEIGHT, Integer.MAX_VALUE);
274
        params.setValue(AVKey.IMAGE_FORMAT, "image/png");
275
        params.setValue(AVKey.PIXEL_FORMAT, AVKey.IMAGE);
276
        params.setValue(AVKey.TEXTURE_FORMAT, "image/dds");
277
        params.setValue(AVKey.FORMAT_SUFFIX, ".png");
278
        params.setValue(AVKey.AVAILABLE_IMAGE_FORMATS, new String[] { params.getValue(AVKey.IMAGE_FORMAT).toString() });
279
        params.setValue(AVKey.NETWORK_RETRIEVAL_ENABLED, false);
280
        params.setValue(AVKey.USE_MIP_MAPS, true);
281
        params.setValue(AVKey.USE_TRANSPARENT_TEXTURES, true);
282

    
283
        Sector sector = (Sector) params.getValue(AVKey.SECTOR);
284

    
285
        setTileParameters(layer, sector, params, layerProperties);
286

    
287
        setDetailLevelParameters(layer, sector, params, layerProperties);
288
    }
289

    
290
    private void createElevationModelParams(FLayer layer, AVList params) {
291

    
292
        if (params == null) {
293
            params = new AVListImpl();
294
        }
295

    
296
        setBasicParameters(layer, params);
297

    
298
        setSectorParameters(layer, params);
299

    
300
        if (layer instanceof FLyrRaster) {
301

    
302
            FLyrRaster rasterLayer = (FLyrRaster) layer;
303
            int[] dataType = rasterLayer.getDataStore().getDataType();
304

    
305
            switch (dataType[0]) {
306
            case Buffer.TYPE_BYTE:
307
                params.setValue(AVKey.DATA_TYPE, AVKey.INT8);
308
                break;
309
            case Buffer.TYPE_SHORT:
310
            case Buffer.TYPE_USHORT:
311
                params.setValue(AVKey.DATA_TYPE, AVKey.INT16);
312
                break;
313
            case Buffer.TYPE_INT:
314
                params.setValue(AVKey.DATA_TYPE, AVKey.INT32);
315
                break;
316
            case Buffer.TYPE_FLOAT:
317
                params.setValue(AVKey.DATA_TYPE, AVKey.FLOAT32);
318
                break;
319
            case Buffer.TYPE_DOUBLE:
320
                params.setValue(AVKey.DATA_TYPE, AVKey.FLOAT64);
321
                break;
322
            case Buffer.TYPE_UNDEFINED:
323
            default:
324
                return;
325
            }
326

    
327
            params.setValue(AVKey.WIDTH, (int) rasterLayer.getDataStore().getWidth());
328
            params.setValue(AVKey.HEIGHT, (int) rasterLayer.getDataStore().getHeight());
329

    
330
            Statistics statistics = rasterLayer.getDataStore().getStatistics();
331
            params.setValue(AVKey.ELEVATION_MIN, statistics.getMin()[0]);
332
            params.setValue(AVKey.ELEVATION_MAX, statistics.getMax()[0]);
333

    
334
        } else {
335

    
336
            // TODO Vectorial elevation
337
        }
338

    
339
        View3DManager manager = View3DLocator.getManager();
340
        LayerProperties3D layerProperties = manager.getLayerProperties(layer, null);
341
        ElevationLayerProperties3D elevLayerProperties;
342
        if (!(layerProperties instanceof ElevationLayerProperties3D)) {
343
            elevLayerProperties = new DefaultElevationLayerProperties3D();
344
        } else {
345
            elevLayerProperties = (ElevationLayerProperties3D) layerProperties;
346
        }
347

    
348
        params.setValue(AVKey.PIXEL_FORMAT, AVKey.ELEVATION);
349
        params.setValue(AVKey.IMAGE_FORMAT, "application/bil32");
350
        params.setValue(AVKey.MISSING_DATA_SIGNAL, elevLayerProperties.getNoDataValue());
351
        params.setValue(AVKey.ELEVATION_UNIT, elevLayerProperties.getElevationUnits());
352
        params.setValue(AVKey.BYTE_ORDER, AVKey.LITTLE_ENDIAN);
353
        params.setValue(AVKey.AVAILABLE_IMAGE_FORMATS, new String[] { params.getValue(AVKey.IMAGE_FORMAT).toString() });
354

    
355
        Sector sector = (Sector) params.getValue(AVKey.SECTOR);
356

    
357
        setTileParameters(layer, sector, params, elevLayerProperties);
358

    
359
        setDetailLevelParameters(layer, sector, params, elevLayerProperties);
360
    }
361

    
362
    private void setDetailLevelParameters(FLayer layer, Sector sector, AVList params,
363
        RasterLayerProperties3D layerProperties) {
364

    
365
        int numLevels;
366
        // If deatail levels are 0, compute best level of detail number
367
        if (layerProperties.getMinLevel() == 0 && layerProperties.getMaxLevel() == 0) {
368

    
369
            LatLon rasterTileDelta = this.computeRasterTileDelta(params);
370
            LatLon desiredLevelZeroDelta = this.computeDesiredTileDelta(sector);
371
            numLevels = computeNumLevels(desiredLevelZeroDelta, rasterTileDelta);
372

    
373
        } else {
374
            numLevels = layerProperties.getMaxLevel() - layerProperties.getMinLevel();
375
            params.setValue(AVKey.NUM_EMPTY_LEVELS, layerProperties.getMinLevel());
376

    
377
        }
378
        params.setValue(AVKey.NUM_LEVELS, numLevels);
379

    
380
        if (layer instanceof FLyrVect) {
381

    
382
            // Only rasterized vectorial layers
383
            double degrees = DEFAULT_RASTERIZED_LEVEL_ZERO * layerProperties.getLevelZeroResolutionMultiplier();
384
            params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA,
385
                new LatLon(Angle.fromDegrees(degrees), Angle.fromDegrees(degrees)));
386

    
387
        } else {
388

    
389
            LatLon rasterTileDelta = this.computeRasterTileDelta(params);
390
            double scale = Math.pow(2d, numLevels - 1);
391
            LatLon levelZeroTileDelta = LatLon.fromDegrees(
392
                scale * layerProperties.getLevelZeroResolutionMultiplier() * rasterTileDelta.getLatitude().degrees,
393
                scale * layerProperties.getLevelZeroResolutionMultiplier() * rasterTileDelta.getLongitude().degrees);
394
            params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA, levelZeroTileDelta);
395
        }
396

    
397
    }
398

    
399
    private void setSectorParameters(FLayer layer, AVList params) {
400
        MapControl3D mapControl3D = (MapControl3D) params.getValue(DefaultMapControl3D.GVSIG_MAPCONTROL3D);
401
        Sector sector = null;
402
        IProjection projection = mapControl3D.getMapContext().getProjection();
403
        try {
404
            sector = getSector(layer, projection);
405
        } catch (DataException e) {
406
            LOG.info("Can't create sector from layer {} with projection {}", new Object[] { layer, projection }, e);
407
            return;
408
        }
409

    
410
        params.setValue(AVKey.SECTOR, sector);
411
    }
412

    
413
    private void setTileParameters(FLayer layer, Sector sector, AVList params,
414
        RasterLayerProperties3D layerProperties) {
415

    
416
        params.setValue(AVKey.TILE_ORIGIN, new LatLon(sector.getMinLatitude(), sector.getMinLongitude()));
417
        // If tile sizes are 0, set defautlt values
418
        params.setValue(AVKey.TILE_WIDTH,
419
            layerProperties.getTileWidth() == 0 ? DEFAULT_TILE_WIDTH : layerProperties.getTileWidth());
420
        params.setValue(AVKey.TILE_HEIGHT,
421
            layerProperties.getTileHeight() == 0 ? DEFAULT_TILE_HEIGHT : layerProperties.getTileHeight());
422

    
423
    }
424

    
425
    private void setBasicParameters(FLayer layer, AVList params) {
426
        params.setValue(AVKey.DATASET_NAME, layer.getName());
427
        params.setValue(AVKey.DATA_CACHE_NAME, getUniqueCacheId(layer));
428
        params.setValue(AVKey.DISPLAY_NAME, layer.getName());
429
        params.setValue(AVKey.SERVICE_NAME, "Offline");
430
    }
431

    
432
    private Sector getSector(FLayer layer, IProjection projection) throws DataException {
433

    
434
//        ICoordTrans ct = projection.getCT(CRSFactory.getCRS("EPSG:4326"));
435
        Point2D p1 = null;
436
        Point2D p2 = null;
437
        Envelope envelope = layer.getFullEnvelope();
438

    
439
//        p1 = convert(ct, new Point2D.Double(envelope.getMinimum(0), envelope.getMinimum(1)));
440
//        p2 = convert(ct, new Point2D.Double(envelope.getMaximum(0), envelope.getMaximum(1)));
441

    
442
        p1 = new Point2D.Double(envelope.getMinimum(0), envelope
443
                .getMinimum(1));
444
        p2 = new Point2D.Double(envelope.getMaximum(0), envelope
445
                .getMaximum(1));
446

    
447
        double minLatitude =
448
            Double.isInfinite(p1.getY()) || p1.getY() < Angle.NEG90.degrees ? Angle.NEG90.degrees : p1.getY();
449
        double maxLatitude =
450
            Double.isInfinite(p2.getY()) || p2.getY() > Angle.POS90.degrees ? Angle.POS90.degrees : p2.getY();
451
        double minLongitude =
452
            Double.isInfinite(p1.getX()) || p1.getX() < Angle.NEG180.degrees ? Angle.NEG180.degrees : p1.getX();
453
        double maxLongitude =
454
            Double.isInfinite(p2.getX()) || p2.getX() > Angle.POS180.degrees ? Angle.POS180.degrees : p2.getX();
455

    
456
        Sector sector = new Sector(Sector.fromDegrees(minLatitude, maxLatitude, minLongitude, maxLongitude));
457

    
458
        return sector;
459
    }
460

    
461
    private int computeNumLevels(LatLon levelZeroDelta, LatLon lastLevelDelta) {
462
        // Compute the number of levels needed to achieve the given last level
463
        // tile delta, starting from the given
464
        // level zero tile delta.
465
        double numLatLevels = WWMath.logBase2(levelZeroDelta.getLatitude().getDegrees())
466
            - WWMath.logBase2(lastLevelDelta.getLatitude().getDegrees());
467
        double numLonLevels = WWMath.logBase2(levelZeroDelta.getLongitude().getDegrees())
468
            - WWMath.logBase2(lastLevelDelta.getLongitude().getDegrees());
469

    
470
        // Compute the maximum number of levels needed, but limit the number of
471
        // levels to positive integers greater
472
        // than or equal to one.
473
        int numLevels = (int) Math.ceil(Math.max(numLatLevels, numLonLevels));
474
        if (numLevels < 1)
475
            numLevels = 1;
476

    
477
        return numLevels;
478
    }
479

    
480
    private LatLon computeRasterTileDelta(AVList parameters) {
481

    
482
        Sector sector = (Sector) parameters.getValue(AVKey.SECTOR);
483
        int width = (Integer) parameters.getValue(AVKey.WIDTH);
484
        int height = (Integer) parameters.getValue(AVKey.HEIGHT);
485
        int tileWidth = (Integer) parameters.getValue(AVKey.TILE_WIDTH);
486
        int tileHeight = (Integer) parameters.getValue(AVKey.TILE_HEIGHT);
487

    
488
        LatLon pixelSize = this.computeRasterPixelSize(sector, width, height);
489
        // Compute the tile size in latitude and longitude, given a raster's
490
        // sector and dimension, and the tile
491
        // dimensions. In this computation a pixel is assumed to cover a finite
492
        // area.
493
        double latDelta = tileHeight * pixelSize.getLatitude().degrees;
494
        double lonDelta = tileWidth * pixelSize.getLongitude().degrees;
495
        return LatLon.fromDegrees(latDelta, lonDelta);
496
    }
497

    
498
    private LatLon computeRasterPixelSize(Sector sector, int width, int height) {
499
        // Compute the raster's pixel dimension in latitude and longitude. In
500
        // this computation a pixel is assumed to
501
        // cover a finite area.
502
        return LatLon.fromDegrees(sector.getDeltaLatDegrees() / height, sector.getDeltaLonDegrees() / width);
503
    }
504

    
505
    private LatLon computeDesiredTileDelta(Sector sector) {
506
        return LatLon.fromDegrees(sector.getDeltaLatDegrees(), sector.getDeltaLonDegrees());
507
    }
508

    
509
//    private Point2D convert(ICoordTrans ct, Point2D point) {
510
//        if (ct == null) {
511
//            return point;
512
//        }
513
//
514
//        return ct.convert(point, null);
515
//    }
516

    
517
}