Statistics
| Revision:

svn-gvsig-desktop / branches / org.gvsig.desktop-2018a / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.mapcontext / org.gvsig.fmap.mapcontext.impl / src / main / java / org / gvsig / fmap / mapcontext / raster / impl / DefaultRasterLayer.java @ 43876

History | View | Annotate | Download (21.5 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-2016 gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.mapcontext.raster.impl;
24

    
25
import java.awt.Graphics2D;
26
import java.awt.Point;
27
import java.awt.geom.Point2D;
28
import java.awt.image.BufferedImage;
29
import java.io.File;
30
import java.util.List;
31
import java.util.Observable;
32
import java.util.Observer;
33
import java.util.Set;
34
import java.util.TreeSet;
35
import java.util.logging.Level;
36
import java.util.logging.Logger;
37

    
38
import org.cresques.cts.ICoordTrans;
39
import org.slf4j.LoggerFactory;
40

    
41
import org.gvsig.compat.print.PrintAttributes;
42
import org.gvsig.fmap.dal.DataStore;
43
import org.gvsig.fmap.dal.exception.DataException;
44
import org.gvsig.fmap.dal.exception.InitializeException;
45
import org.gvsig.fmap.dal.exception.ReadException;
46
import org.gvsig.fmap.dal.raster.BandAttributeDescriptor;
47
import org.gvsig.fmap.dal.raster.BandDescriptor;
48
import org.gvsig.fmap.dal.raster.RasterQuery;
49
import org.gvsig.fmap.dal.raster.RasterSet;
50
import org.gvsig.fmap.dal.raster.RasterStore;
51
import org.gvsig.fmap.dal.raster.RasterStoreNotification;
52
import org.gvsig.fmap.dal.serverexplorer.filesystem.FilesystemStoreParameters;
53
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
54
import org.gvsig.fmap.geom.GeometryLocator;
55
import org.gvsig.fmap.geom.GeometryManager;
56
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
57
import org.gvsig.fmap.geom.primitive.Envelope;
58
import org.gvsig.fmap.mapcontext.MapContextLocator;
59
import org.gvsig.fmap.mapcontext.MapContextManager;
60
import org.gvsig.fmap.mapcontext.ViewPort;
61
import org.gvsig.fmap.mapcontext.exceptions.LoadLayerException;
62
import org.gvsig.fmap.mapcontext.layers.FLayer;
63
import org.gvsig.fmap.mapcontext.layers.FLyrDefault;
64
import org.gvsig.fmap.mapcontext.layers.LayerInformationBuilder;
65
import org.gvsig.fmap.mapcontext.raster.api.RasterLayer;
66
import org.gvsig.fmap.mapcontext.raster.api.legend.RasterLegendEvent;
67
import org.gvsig.fmap.mapcontext.raster.api.legend.listeners.RasterLegendChangedListener;
68
import org.gvsig.fmap.mapcontext.rendering.legend.ILegend;
69
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
70
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendClearEvent;
71
import org.gvsig.fmap.mapcontext.rendering.legend.events.SymbolLegendEvent;
72
import org.gvsig.metadata.exceptions.MetadataException;
73
import org.gvsig.raster.lib.buffer.api.BufferDimensions;
74
import org.gvsig.raster.lib.buffer.api.BufferLocator;
75
import org.gvsig.raster.lib.buffer.api.statistics.Statistics;
76
import org.gvsig.raster.lib.legend.api.RasterLegend;
77
import org.gvsig.tools.ToolsLocator;
78
import org.gvsig.tools.dispose.DisposeUtils;
79
import org.gvsig.tools.dynobject.DynObjectSet;
80
import org.gvsig.tools.dynobject.DynStruct;
81
import org.gvsig.tools.exception.BaseException;
82
import org.gvsig.tools.i18n.I18nManager;
83
import org.gvsig.tools.locator.LocatorException;
84
import org.gvsig.tools.persistence.PersistenceManager;
85
import org.gvsig.tools.persistence.Persistent;
86
import org.gvsig.tools.persistence.PersistentState;
87
import org.gvsig.tools.persistence.exception.PersistenceException;
88
import org.gvsig.tools.task.Cancellable;
89
import org.gvsig.tools.task.SimpleTaskStatus;
90
import org.gvsig.tools.task.TaskStatusManager;
91
import org.gvsig.tools.util.Callable;
92

    
93
/**
94
 * Capa b?sica Raster.
95
 *
96
 */
97
public class DefaultRasterLayer extends FLyrDefault implements RasterLayer, RasterLegendChangedListener, Observer {
98

    
99
    final static private org.slf4j.Logger logger = LoggerFactory.getLogger(DefaultRasterLayer.class);
100

    
101
    private RasterStore store;
102
    private RasterLegend legend;
103
    // private Cancellable cancel;
104
    private RasterQuery baseQuery;
105
    private Statistics statistics;
106

    
107
    public static class RegisterPersistence implements Callable {
108

    
109
        @Override
110
        public Object call() {
111
            PersistenceManager manager = ToolsLocator.getPersistenceManager();
112
            DynStruct definition =
113
                manager.addDefinition(DefaultRasterLayer.class, "DefaultRasterLayer",
114
                    "DefaultRasterLayer Persistence definition", null, null);
115
            definition.extend(PersistenceManager.PERSISTENCE_NAMESPACE, "FLyrDefault");
116
            definition.addDynFieldObject("legend").setClassOfValue(RasterLegend.class).setMandatory(true);
117
            definition.addDynFieldObject("store").setClassOfValue(RasterStore.class).setMandatory(true);
118
            definition.addDynFieldObject("baseQuery").setClassOfValue(RasterQuery.class).setMandatory(false);
119

    
120
            return Boolean.TRUE;
121
        }
122
    }
123

    
124
    /**
125
     * Creates a new DefaultRasterLayer
126
     *
127
     * @throws LoadLayerException
128
     */
129
    public DefaultRasterLayer() throws LoadLayerException {
130
        super();
131
    }
132

    
133
    /**
134
     * Creates a new DefaultRasterLayer
135
     *
136
     * @param store
137
     * @param legend
138
     */
139
    public DefaultRasterLayer(RasterStore store, RasterLegend legend) {
140
        super();
141
        ToolsLocator.getDisposableManager().bind(store);
142
        this.store = store;
143
        this.setLegend(legend);
144
    }
145

    
146
    @Override
147
    public void saveToState(PersistentState state) throws PersistenceException {
148
        try {
149
            super.saveToState(state);
150

    
151
            state.set("store", (Persistent) this.store);
152
            state.set("legend", (Persistent) this.legend);
153
            state.set("baseQuery", (Persistent) this.baseQuery);
154

    
155
        } catch (PersistenceException | RuntimeException ex) {
156
            logger.warn("Can't save to persistent state the layer '" + this.getName() + "'.");
157
            throw ex;
158
        }
159
    }
160

    
161
    @Override
162
    public void loadFromState(PersistentState state) throws PersistenceException {
163

    
164
        try {
165
            super.loadFromState(state);
166

    
167
            this.store = (RasterStore) state.get("store");
168
            this.legend = (RasterLegend) state.get("legend");
169
            this.baseQuery = (RasterQuery) state.get("baseQuery");
170

    
171
        } catch (PersistenceException | RuntimeException ex) {
172
            logger.warn("Can't load from persietent state the layer '" + this.getName() + "'.");
173
            throw ex;
174
        }
175

    
176
    }
177

    
178
    private void setLegend(RasterLegend legend) {
179
        if (this.legend == legend) {
180
            return;
181
        }
182
        if (this.legend != null && this.legend.equals(legend)) {
183
            return;
184
        }
185
        RasterLegend oldLegend = this.legend;
186
        if (oldLegend != null) {
187
             oldLegend.removeLegendListener( this);
188
//             oldLegend.deleteDrawingObserver(this);
189
        }
190
        this.legend = legend;
191
//        if (this.legend != null) {
192
//             this.legend.addDrawingObserver(this);
193
//             this.legend.addLegendListener( this);
194
//        }
195

    
196
        this.legend.addLegendListener(this);
197

    
198
        LegendChangedEvent e = LegendChangedEvent.createLegendChangedEvent(oldLegend, this.legend);
199
        // FIXME: cuando se arregle LegendChangeEvent para que admita capas
200
        // raster (y no solo las ClassifiableVectorial) descomentarizar la siguiente l?nea
201
        // e.setLayer(this);
202
        updateDrawVersion();
203
        callLegendChanged(e);
204
    }
205

    
206
    /**
207
     * Devuelve la Leyenda de la capa.
208
     *
209
     * @return Leyenda.
210
     */
211
    @Override
212
    public RasterLegend getLegend(){
213
        if (legend == null) {
214
            MapContextManager mapContextManager = MapContextLocator.getMapContextManager();
215
            RasterLegend theLegend = (RasterLegend) mapContextManager.getLegend(store);
216
            this.setLegend(theLegend);
217
      }
218
        return legend;
219
    }
220

    
221
    @Override
222
    public DataStore getDataStore() {
223
        return this.store;
224
    }
225

    
226
    @Override
227
    public void setDataStore(DataStore dataStore) throws LoadLayerException {
228

    
229
        if (this.store != null) {
230
            DisposeUtils.disposeQuietly(this.store);
231
        }
232

    
233
        this.store = (RasterStore) dataStore;
234
        ToolsLocator.getDisposableManager().bind(dataStore);
235
        
236
        MapContextManager mapContextManager = MapContextLocator.getMapContextManager();
237
        RasterLegend theLegend = (RasterLegend) mapContextManager.getLegend(store);
238
        this.setLegend(theLegend);
239
    }
240

    
241
    @Override
242
    public Envelope getFullEnvelope() throws ReadException {
243
        Envelope rAux;
244
        try {
245
            rAux = getRasterStore().getEnvelope();
246
        } catch (BaseException e) {
247
            throw new ReadException(getName(), e);
248
        }
249

    
250
        // Esto es para cuando se crea una capa nueva con el fullExtent de ancho
251
        // y alto 0.
252
        if (rAux == null || rAux.isEmpty() || rAux.getMaximum(0) - rAux.getMinimum(0) == 0
253
            && rAux.getMaximum(1) - rAux.getMinimum(1) == 0) {
254
            try {
255
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
256
                rAux = geomManager.createEnvelope(0, 0, 90, 90, SUBTYPES.GEOM2D);
257
            } catch (CreateEnvelopeException e) {
258
                logger.warn("Error creating the envelope", e);
259
            }
260
        }
261
        // Si existe reproyecci?n, reproyectar el extent
262
        ICoordTrans ct = getCoordTrans();
263
        if (ct != null) {
264
            rAux = rAux.convert(ct);
265
        }
266
        return rAux;
267
    }
268

    
269
    @Override
270
    public void draw(BufferedImage image, final Graphics2D g, final ViewPort viewPort, Cancellable cancel, double scale)
271
        throws ReadException {
272
        if (!this.isWithinScale(scale)) {
273
            return;
274
        }
275
        if (cancel.isCanceled()) {
276
            return;
277
        }
278

    
279
        RasterQuery rasterQuery = createRasterQuery();
280
        Envelope reprojectedViewPortEnvelope = (Envelope) viewPort.getAdjustedEnvelope(); // .getEnvelope();
281
        ICoordTrans ct = getCoordTrans();
282
        if (ct != null) {
283
            try {
284
                reprojectedViewPortEnvelope = (Envelope) reprojectedViewPortEnvelope.clone();
285
                reprojectedViewPortEnvelope = reprojectedViewPortEnvelope.convert(ct.getInverted());
286
            } catch (CloneNotSupportedException e) {
287
                this.setAvailable(false);
288
                this.setError(e);
289
                throw new ReadException(getName(), e);
290
            }
291
        }
292

    
293
        double pixelSize = reprojectedViewPortEnvelope.getLength(0) / (double) viewPort.getImageWidth();
294

    
295
        rasterQuery.setPixelSize(pixelSize);
296
        rasterQuery.setClip(reprojectedViewPortEnvelope);
297

    
298
        RasterSet rasterSet = null;
299
        SimpleTaskStatus taskStatus = null;
300
        try {
301

    
302
            long tini = System.currentTimeMillis();
303

    
304
            // TODO Task status should be used to cancel
305
            TaskStatusManager manager = ToolsLocator.getTaskStatusManager();
306
            taskStatus = manager.createDefaultSimpleTaskStatus("Draw " + getDataStore().getName());
307
            taskStatus.setAutoremove(true);
308
            taskStatus.add();
309
            rasterSet = getRasterStore().getRasterSet(rasterQuery);
310
            if (!rasterSet.isEmpty()) {
311
                getLegend().draw(g, rasterSet, viewPort, taskStatus);
312
                logger.debug("Layer " + this.getName() + " drawn in " + (System.currentTimeMillis() - tini)
313
                    + " milliseconds.");
314
            }
315
            
316

    
317
        } catch (DataException e) {
318
            if( taskStatus!=null ) {
319
                taskStatus.abort();
320
                taskStatus = null;
321
            }
322
            this.setAvailable(false);
323
            this.setError(e);
324
            throw new ReadException(getName(), e);
325
        } finally {
326
            if (rasterSet != null) {
327
                DisposeUtils.dispose(rasterSet);
328
                rasterSet = null;
329
            }
330
            if( taskStatus!=null ) {
331
                taskStatus.terminate();
332
                taskStatus = null;
333
            }
334
        }
335

    
336
    }
337

    
338
    @Override
339
    public void print(Graphics2D g, ViewPort viewPort, Cancellable cancel, double scale, PrintAttributes properties)
340
        throws ReadException {
341

    
342
        // TODO legend doesn't have print method
343
        throw new UnsupportedOperationException();
344

    
345
    }
346

    
347
    @Override
348
    public Set<RasterStore> getMetadataChildren() throws MetadataException {
349
        Set<RasterStore> ret = new TreeSet<>();
350
        ret.add(this.store);
351
        return ret;
352
    }
353

    
354
    @Override
355
    public Object getMetadataID() throws MetadataException {
356
        return "Layer(" + this.getName() + "):" + this.store.getMetadataID();
357
    }
358

    
359
    @Override
360
    public void update(Observable observable, Object notification) {
361
        if (observable.equals(this.store)) {
362
            if (notification instanceof RasterStoreNotification) {
363
                RasterStoreNotification event = (RasterStoreNotification) notification;
364
                if (event.getType() == RasterStoreNotification.AFTER_REFRESH
365
                    || event.getType() == RasterStoreNotification.SELECTION_CHANGE) {
366
                    this.updateDrawVersion();
367
                } else if (event.getType() == RasterStoreNotification.RESOURCE_CHANGED) {
368
                    this.setAvailable(false);
369
                }
370
            }
371
        }
372
    }
373

    
374
    @Override
375
    public RasterStore getRasterStore() {
376
        return this.store;
377
    }
378

    
379
    @Override
380
    public void setBaseQuery(RasterQuery baseQuery) {
381
        this.baseQuery = baseQuery;
382
    }
383

    
384
    @Override
385
    public RasterQuery getBaseQuery() {
386
        return this.baseQuery;
387
    }
388

    
389
    @Override
390
    public RasterQuery createRasterQuery() {
391
        if (this.baseQuery == null) {
392
            return this.getRasterStore().createRasterQuery();
393
        }
394
        try {
395
            return (RasterQuery) baseQuery.clone();
396
        } catch (CloneNotSupportedException ex) {
397
            throw new RuntimeException(ex);
398
        }
399
    }
400

    
401
    @Override
402
    protected void doDispose() throws BaseException {
403
        logger.debug("Dispose DefaultRasterLayer '"+(this.getDataStore()==null?"NULL":this.getDataStore().getFullName()+"'"));
404

    
405
        DisposeUtils.dispose(this.store);
406
        this.layerListeners.clear();
407
        this.store = null;
408
        this.legend = null;
409
        this.baseQuery = null;
410
    }
411

    
412
    @Override
413
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel) throws LoadLayerException, DataException {
414

    
415
        return getInfo(p, tolerance, cancel, true);
416
    }
417

    
418
    @Override
419
    public DynObjectSet getInfo(Point p, double tolerance, Cancellable cancel, boolean fast) throws LoadLayerException,
420
        DataException {
421

    
422
        Point2D infop = new Point2D.Double(p.x, p.y);
423
        org.gvsig.fmap.geom.primitive.Point pReal = this.getMapContext().getViewPort().convertToMapPoint(infop);
424

    
425
        // TODO:
426
        return null;
427
    }
428

    
429
    @Override
430
    public DynObjectSet getInfo(org.gvsig.fmap.geom.primitive.Point p, double tolerance) throws LoadLayerException,
431
        DataException {
432
        // TODO Auto-generated method stub
433
        return null;
434
    }
435

    
436
    @Override
437
    public String getTocImageIcon() {
438
        //FIXME: Subir esto a la clase abstracta
439
        return MapContextLocator.getMapContextManager().getIconLayer(this.getDataStore());
440
    }
441

    
442
    @Override
443
    public void setLegend(ILegend legend) {
444
        if (legend instanceof RasterLegend) {
445
            setLegend((RasterLegend) legend);
446
        } else {
447
            throw new IllegalArgumentException("The legend isn't a RasterLegend.");
448
        }
449
    }
450

    
451
    @Override
452
    public String getInfoString() {
453
        RasterStore rasterStore = this.getRasterStore();
454
        Envelope envelope = null;
455
        try {
456
            envelope = rasterStore.getEnvelope();
457
        } catch (LocatorException | DataException | CreateEnvelopeException e) {
458
        }
459
        int bands = rasterStore.getBands();
460
        int rows = -1;
461
        int columns = -1;
462
        String pixelSize = "-/-";
463
        try {
464
            BufferDimensions dimensions = rasterStore.getDimensions();
465
            rows = dimensions.getRows();
466
            columns = dimensions.getColumns();
467
            pixelSize = String.format("%.3f/%.3f", dimensions.getPixelSizeX(), dimensions.getPixelSizeY());
468
        } catch (InitializeException ex) {
469
        }
470
        I18nManager i18nManager = ToolsLocator.getI18nManager();
471
        LayerInformationBuilder builder = MapContextLocator.getMapContextManager().createLayerInformationBuilder();
472

    
473
        builder.title().labelkey("Data_source");
474
        builder.property().labelkey("Source_type").value(store.getProviderName());
475
        builder.property().labelkey("origen").value(store.getFullName());
476
        if (store.getParameters() instanceof FilesystemStoreParameters) {
477
            File f = ((FilesystemStoreParameters) (store.getParameters())).getFile();
478
            if (f != null) {
479
                builder.property().labelkey("size").value("%d bytes", f.length());
480
            }
481
        }
482

    
483
        builder.property().labelkey("_bands").value("%d", bands);
484
        builder.property().labelkey("_rows").value("%d", rows);
485
        builder.property().labelkey("_columns").value("%d", columns);
486
        builder.property().labelkey("_pixel_size").value("%s", pixelSize);
487
        builder.property().labelkey("transparency").value("%d", this.getTransparency());
488

    
489
        builder.title().labelkey("_Coordenadas_geograficas");
490
        builder.envelope().value(envelope);
491

    
492
        builder.title().labelkey("_Projection");
493
        builder.property().value(this.getProjection());
494
        builder.text().asWKT(this.getProjection());
495

    
496
        for (int i = 0; i < bands; i++) {
497
            builder.title().labelkey(i18nManager.getTranslation("_band") + " " + i);
498

    
499
            BandDescriptor bandDescriptor = rasterStore.getBandDescriptor(i);
500

    
501
            builder.property().labelkey("_name").value(bandDescriptor.getName());
502
            builder.property().labelkey("_description").value(bandDescriptor.getDescription());
503
            builder.property().labelkey("_dataType")
504
                .value(BufferLocator.getBufferManager().getTypeName(bandDescriptor.getDataType()));
505

    
506
            if (bandDescriptor.getNoData() != null) {
507
                builder.property().labelkey("_noData").value(bandDescriptor.getNoData().toString());
508
            } else {
509
                builder.property().labelkey("_noData").value(i18nManager.getTranslation("_null"));
510
            }
511

    
512
            for (BandAttributeDescriptor bandAttributeDescriptor : bandDescriptor) {
513
                builder.property().labelkey("_name").value(bandAttributeDescriptor.getName());
514
                builder.property().labelkey("_description").value(bandAttributeDescriptor.getDescription());
515
                builder.property().labelkey("_units").value(bandAttributeDescriptor.getUnits());
516

    
517
                builder.title().labelkey("_values");
518

    
519
                List<Object> attributeValues = bandAttributeDescriptor.getAvailableValues();
520

    
521
                for (Object value : attributeValues) {
522
                    if (value != null) {
523
                        builder.property().labelkey("_units").value(bandAttributeDescriptor.getUnits());
524
                    } else {
525
                        builder.property().labelkey("_units").value(bandAttributeDescriptor.getUnits());
526
                    }
527
                }
528
            }
529
        }
530

    
531
        return builder.toString();
532
    }
533

    
534
    @Override
535
    public Statistics getStatistics(SimpleTaskStatus status) {
536
        if (statistics == null) {
537
            RasterSet rasterSet = null;
538
            try {
539
                rasterSet = getRasterStore().getRasterSet();
540
                statistics = rasterSet.getStatistics(status);
541
            } catch (DataException e) {
542
                logger.warn("Can't get layer's statistics", e);
543
            } finally {
544
                DisposeUtils.dispose(rasterSet);
545
            }
546
        }
547
        return statistics;
548
    }
549

    
550
    @Override
551
    public void recalculateStatistics() {
552
        this.statistics = null;
553
    }
554

    
555
    @Override
556
    public FLayer cloneLayer() throws Exception {
557
        RasterLegend clonedLegend = (RasterLegend)this.legend.cloneLegend();
558
        DefaultRasterLayer cloned = new DefaultRasterLayer(this.store, clonedLegend);
559
        cloned.setName(this.getName());
560
        cloned.setProjection(this.getProjection());
561

    
562
        return cloned;
563
    }
564

    
565
    @Override
566
    public boolean symbolChanged(SymbolLegendEvent e) {
567
        //FIXME: Remove when fixed hierarchy of legend events
568
        throw new UnsupportedOperationException("There aren't any symbols in a raster legend.");
569
    }
570

    
571
    @Override
572
    public void legendCleared(LegendClearEvent event) {
573
        //FIXME: Remove when fixed hierarchy of legend events
574
        throw new UnsupportedOperationException("Can't clear a raster legend.");
575
    }
576

    
577
    @Override
578
    public boolean colorInterpretationChanged(RasterLegendEvent e) {
579
        this.updateDrawVersion();
580

    
581
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
582
        this.callLegendChanged(ev);
583
        return true;
584
    }
585

    
586
    @Override
587
    public boolean operationListChanged(RasterLegendEvent e) {
588
        this.updateDrawVersion();
589

    
590
        LegendChangedEvent ev = LegendChangedEvent.createLegendChangedEvent(legend, e);
591
        this.callLegendChanged(ev);
592
        return true;
593
    }
594
}