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 / DefaultSynchronizer.java @ 708

History | View | Annotate | Download (21 KB)

1
package org.gvsig.view3d.swing.impl;
2

    
3
import java.awt.geom.Point2D;
4
import java.util.ArrayList;
5
import java.util.HashMap;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Map.Entry;
9

    
10
import org.slf4j.Logger;
11
import org.slf4j.LoggerFactory;
12

    
13
import org.gvsig.fmap.dal.exception.DataException;
14
import org.gvsig.fmap.geom.primitive.Envelope;
15
import org.gvsig.fmap.mapcontext.MapContext;
16
import org.gvsig.fmap.mapcontext.ViewPort;
17
import org.gvsig.fmap.mapcontext.events.ColorEvent;
18
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
19
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
20
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
21
import org.gvsig.fmap.mapcontext.layers.CancelationException;
22
import org.gvsig.fmap.mapcontext.layers.FLayer;
23
import org.gvsig.fmap.mapcontext.layers.FLayers;
24
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
25
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
26
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
27
import org.gvsig.fmap.mapcontext.layers.LayerListener;
28
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
29
import org.gvsig.fmap.mapcontext.layers.operations.LayersVisitor;
30
import org.gvsig.fmap.mapcontext.layers.vectorial.FLyrVect;
31
import org.gvsig.fmap.mapcontext.rendering.legend.events.LegendChangedEvent;
32
import org.gvsig.fmap.mapcontext.rendering.legend.events.listeners.LegendListener;
33
import org.gvsig.tools.exception.BaseException;
34
import org.gvsig.tools.visitor.VisitCanceledException;
35
import org.gvsig.view3d.lib.api.View3DLocator;
36
import org.gvsig.view3d.lib.api.View3DManager;
37
import org.gvsig.view3d.lib.api.layers.LayerLegendListener;
38
import org.gvsig.view3d.lib.api.layers.NwwVectorLayer;
39
import org.gvsig.view3d.lib.api.properties.E3DLayerLoadingModes;
40
import org.gvsig.view3d.lib.api.properties.ElevationLayerProperties3D;
41
import org.gvsig.view3d.lib.api.properties.LayerProperties3D;
42
import org.gvsig.view3d.lib.api.properties.RasterLayerProperties3D;
43
import org.gvsig.view3d.swing.api.View3DSwingLocator;
44
import org.gvsig.view3d.swing.api.View3DSwingManager;
45
import org.gvsig.view3d.swing.api.properties.GeneralProperties3D;
46
import org.gvsig.view3d.swing.api.properties.MapControlProperties3D;
47
import org.gvsig.view3d.swing.impl.layers.raster.DefaultTiledImageLayer;
48

    
49
import gov.nasa.worldwind.WorldWindow;
50
import gov.nasa.worldwind.avlist.AVKey;
51
import gov.nasa.worldwind.avlist.AVList;
52
import gov.nasa.worldwind.geom.Angle;
53
import gov.nasa.worldwind.geom.Box;
54
import gov.nasa.worldwind.geom.Position;
55
import gov.nasa.worldwind.geom.Sector;
56
import gov.nasa.worldwind.globes.ElevationModel;
57
import gov.nasa.worldwind.layers.Layer;
58
import gov.nasa.worldwind.layers.LayerList;
59
import gov.nasa.worldwind.terrain.CompoundElevationModel;
60
import gov.nasa.worldwind.view.orbit.OrbitView;
61

    
62
public class DefaultSynchronizer {
63

    
64
    private static final Logger LOG = LoggerFactory.getLogger(DefaultSynchronizer.class);
65

    
66
    private Map<FLayer, LAYER_SYNCHRONIZE_STATUS> dataLayerRegister = new HashMap<FLayer, LAYER_SYNCHRONIZE_STATUS>();
67

    
68
    private Map<FLayer, LAYER_SYNCHRONIZE_STATUS> elevationModelLayerRegister =
69
        new HashMap<FLayer, LAYER_SYNCHRONIZE_STATUS>();
70

    
71
    private DefaultMapControl3D mapControl3D;
72
    private MapContext mapContext;
73
    private WorldWindow wwd;
74

    
75
    private Object synchronizingLayerLock = new Object();
76

    
77
    protected DefaultSynchronizer(DefaultMapControl3D theMapControl3D, MapContext theMapContext, WorldWindow wwd) {
78

    
79
        this.mapControl3D = theMapControl3D;
80
        this.mapContext = theMapContext;
81
        this.wwd = wwd;
82

    
83
        intializeRegisters();
84

    
85
        addLayerCollectionListener(mapContext.getLayers());
86
        FLayers layers = mapContext.getLayers();
87
        addLayerListener(layers);
88
        addLegendListeners(layers);
89
        addViewPortListener(mapContext.getViewPort());
90
    }
91

    
92
    private void intializeRegisters() {
93

    
94
        FLayers layers = mapContext.getLayers();
95

    
96
        try {
97
            layers.accept(new LayersVisitor() {
98

    
99
                public void visit(Object obj) throws VisitCanceledException, BaseException {
100
                    throw new UnsupportedOperationException();
101

    
102
                }
103

    
104
                public void visit(FLayer layer) throws BaseException {
105

    
106
                    View3DManager manager = View3DLocator.getManager();
107
                    LayerProperties3D layerProperties = manager.getLayerProperties(layer, null);
108

    
109
                    if (layerProperties instanceof ElevationLayerProperties3D) {
110
                        elevationModelLayerRegister.put(layer, LAYER_SYNCHRONIZE_STATUS.CLEAN);
111
                    } else {
112
                        // raster and vector layers
113
                        dataLayerRegister.put(layer, LAYER_SYNCHRONIZE_STATUS.CLEAN);
114
                    }
115
                }
116
            });
117
        } catch (BaseException e) {
118
            LOG.error("Can't initialize register of layers to auto synchronize.", e);
119
            mapControl3D.getProperties().setAutoLayerSynchronize(false);
120
        }
121
    }
122

    
123
    private void addLayerListener(FLayer layer) {
124
        if (layer == null) {
125
            return;
126
        }
127
        layer.addLayerListener(getLayerListener());
128
    }
129

    
130
    private void addLayerCollectionListener(FLayers layers) {
131

    
132
        if (layers == null) {
133
            return;
134
        }
135

    
136
        layers.addLayerCollectionListener(new LayerCollectionListener() {
137

    
138
            public void layerAdded(LayerCollectionEvent e) {
139
                FLayer affectedLayer = e.getAffectedLayer();
140
                affectedLayer.addLayerListener(getLayerListener());
141
                if (affectedLayer instanceof FLyrVect) {
142
                    FLyrVect vectorLayer = (FLyrVect) affectedLayer;
143
                    vectorLayer.addLegendListener(getLegendListener(vectorLayer));
144
                }
145
                updateLayerState(affectedLayer, LAYER_SYNCHRONIZE_STATUS.ADD);
146
                if (mapControl3D.getProperties().getAutoLayerSynchronize()) {
147
                    synchronizeLayers();
148
                }
149
            }
150

    
151
            public void layerAdding(LayerCollectionEvent e) throws CancelationException {
152
            }
153

    
154
            public void layerMoved(LayerPositionEvent e) {
155
                FLayer affectedLayer = e.getAffectedLayer();
156
                int oldPos = e.getOldPos();
157
                int newPos = e.getNewPos();
158
                moveLayer(affectedLayer, oldPos, newPos);
159
            }
160

    
161
            public void layerMoving(LayerPositionEvent e) throws CancelationException {
162
            }
163

    
164
            public void layerRemoved(LayerCollectionEvent e) {
165
            }
166

    
167
            public void layerRemoving(LayerCollectionEvent e) throws CancelationException {
168
                FLayer affectedLayer = e.getAffectedLayer();
169
                updateLayerState(affectedLayer, LAYER_SYNCHRONIZE_STATUS.REMOVE);
170
                if (mapControl3D.getProperties().getAutoLayerSynchronize()) {
171
                    synchronizeLayers();
172
                }
173
            }
174

    
175
            public void visibilityChanged(LayerCollectionEvent e) throws CancelationException {
176
            }
177
        });
178
    }
179

    
180
    private void addLegendListeners(FLayers layers) {
181
        try {
182
            layers.accept(new LayersVisitor() {
183

    
184
                public void visit(Object obj) throws VisitCanceledException, BaseException {
185
                    throw new UnsupportedOperationException();
186
                }
187

    
188
                public void visit(FLayer layer) throws BaseException {
189
                    if (layer instanceof FLyrVect) {
190
                        FLyrVect vectorLayer = (FLyrVect) layer;
191
                        vectorLayer.addLegendListener(getLegendListener(vectorLayer));
192
                    }
193
                }
194
            });
195
        } catch (BaseException e) {
196
            LOG.error("Can't initialize register of layers to auto synchronize.", e);
197
            mapControl3D.getProperties().setAutoLayerSynchronize(false);
198
        }
199
    }
200

    
201
    private LayerListener getLayerListener() {
202
        return new LayerListener() {
203

    
204
            public void activationChanged(LayerEvent e) {
205
            }
206

    
207
            public void drawValueChanged(LayerEvent e) {
208
                FLayer layer = e.getSource();
209

    
210
//                LayerProperties3D layerProperties = View3DLocator.getManager().getLayerProperties(layer, null);
211
//                if (layerProperties instanceof ElevationLayerProperties3D && dataLayerRegister.containsKey(layer)) {
212
//                    updateLayerState(layer, LAYER_SYNCHRONIZE_STATUS.ADD);
213
//                } else if (layerProperties.getClass().getCanonicalName()
214
//                    .equals(RasterLayerProperties3D.class.getCanonicalName())
215
//                    && elevationModelLayerRegister.containsKey(layer)) {
216
//                    updateLayerState(layer, LAYER_SYNCHRONIZE_STATUS.ADD);
217
//                } else {
218
                    updateLayerState(layer, LAYER_SYNCHRONIZE_STATUS.DIRTY);
219
//                }
220

    
221
                MapControlProperties3D properties = mapControl3D.getProperties();
222
                if (properties != null && properties.getAutoLayerSynchronize()) {
223
                    synchronizeLayers();
224
                }
225
            }
226

    
227
            public void editionChanged(LayerEvent e) {
228
            }
229

    
230
            public void nameChanged(LayerEvent e) {
231
            }
232

    
233
            public void visibilityChanged(LayerEvent e) {
234
                FLayer layer = e.getSource();
235

    
236
                updateLayerState(layer, LAYER_SYNCHRONIZE_STATUS.DIRTY);
237
                if (mapControl3D.getProperties().getAutoLayerSynchronize()) {
238
                    synchronizeLayers();
239
                }
240
            }
241
        };
242
    }
243

    
244
    private LegendListener getLegendListener(FLyrVect vectorLayer) {
245
        return new LayerLegendListener(vectorLayer) {
246

    
247
            @Override
248
            public void legendChanged(LegendChangedEvent e) {
249
                updateLayerState(mVectorLayer, LAYER_SYNCHRONIZE_STATUS.SYMBOL_CHANGED);
250
                MapControlProperties3D properties = mapControl3D.getProperties();
251
                if (properties.getAutoLayerSynchronize()) {
252
                    synchronizeLayers();
253
                }
254
            }
255
        };
256
    }
257

    
258
    private void addViewPortListener(ViewPort viewPort) {
259

    
260
        viewPort.addViewPortListener(new ViewPortListener() {
261

    
262
            public void projectionChanged(ProjectionEvent e) {
263
            }
264

    
265
            public void extentChanged(ExtentEvent e) {
266
                MapControlProperties3D properties = mapControl3D.getProperties();
267
                boolean autoViewSynchronize = properties.getAutoViewPortSynchronize();
268
                if (autoViewSynchronize) {
269
                    synchronizeViewPorts();
270
                }
271
            }
272

    
273
            public void backColorChanged(ColorEvent e) {
274
            }
275
        });
276
    }
277

    
278
    private Layer getDataLayer(FLayer layer) {
279
        LayerList layersList = wwd.getModel().getLayers();
280
        for (Layer nwwLayer : layersList) {
281
            if (nwwLayer instanceof DefaultTiledImageLayer || nwwLayer instanceof NwwVectorLayer) {
282
                AVList constructionParams = (AVList) nwwLayer.getValue(AVKey.CONSTRUCTION_PARAMETERS);
283
                if (constructionParams != null) {
284
                    FLayer likedLayer = (FLayer) constructionParams.getValue(E3DLayerLoadingModes.GVSIG_LAYER);
285
                    if (likedLayer != null && layer.equals(likedLayer)) {
286
                        return nwwLayer;
287
                    }
288
                }
289
            }
290
        }
291
        return null;
292
    }
293

    
294
    private ElevationModel getElevationModel(FLayer layer) {
295
        ElevationModel elevationModel = wwd.getModel().getGlobe().getElevationModel();
296

    
297
        if (elevationModel instanceof CompoundElevationModel) {
298
            CompoundElevationModel compoundModel = (CompoundElevationModel) elevationModel;
299
            List<ElevationModel> elevationModels = compoundModel.getElevationModels();
300

    
301
            for (ElevationModel eModel : elevationModels) {
302
                if (eModel.getName().equals(layer.getName())) {
303
                    return eModel;
304
                }
305
            }
306
            return null;
307
        }
308

    
309
        if (elevationModel.getName().equals(layer.getName())) {
310
            return elevationModel;
311
        }
312
        return null;
313
    }
314

    
315
    private void updateLayerState(FLayer layer, LAYER_SYNCHRONIZE_STATUS status) {
316

    
317
        View3DManager manager = View3DLocator.getManager();
318
        LayerProperties3D layerProperties = manager.getLayerProperties(layer, null);
319
        synchronized (synchronizingLayerLock) {
320
            if (layerProperties instanceof ElevationLayerProperties3D) {
321
                if (dataLayerRegister.containsKey(layer)) {
322
                    dataLayerRegister.remove(layer);
323
                }
324

    
325
                if (elevationModelLayerRegister.containsKey(layer) || status == LAYER_SYNCHRONIZE_STATUS.ADD) {
326
                    elevationModelLayerRegister.put(layer, status);
327
                }
328
            } else {
329
                if (elevationModelLayerRegister.containsKey(layer)) {
330
                    elevationModelLayerRegister.remove(layer);
331
                }
332
                if (dataLayerRegister.containsKey(layer) || status == LAYER_SYNCHRONIZE_STATUS.ADD) {
333
                    dataLayerRegister.put(layer, status);
334
                }
335
            }
336
        }
337
    }
338

    
339
    protected void synchronizeLayers() {
340

    
341
        List<FLayer> removedLayers = new ArrayList<FLayer>();
342

    
343
        synchronized (synchronizingLayerLock) {
344
            // Synchronize dataLayers
345
            for (Entry<FLayer, LAYER_SYNCHRONIZE_STATUS> entry : dataLayerRegister.entrySet()) {
346

    
347
                FLayer gvsigLayer = entry.getKey();
348
                LAYER_SYNCHRONIZE_STATUS status = dataLayerRegister.get(gvsigLayer);
349

    
350
                switch (status) {
351
                case ADD:
352
                    addLayer(gvsigLayer);
353
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
354
                    break;
355
                case REMOVE:
356
                    removeLayer(gvsigLayer);
357
                    removedLayers.add(gvsigLayer);
358
                    break;
359
                case SYMBOL_CHANGED:
360
                    updateLayerSymbol(gvsigLayer);
361
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
362
                    break;
363
                case DIRTY:
364
                    updateLayer(gvsigLayer);
365
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
366
                    break;
367
                case CLEAN:
368
                    break;
369
                }
370
            }
371

    
372
            // Synchronize elevationModelLayerRegister
373
            for (Entry<FLayer, LAYER_SYNCHRONIZE_STATUS> entry : elevationModelLayerRegister.entrySet()) {
374

    
375
                FLayer eModelLayer = entry.getKey();
376
                LAYER_SYNCHRONIZE_STATUS status = elevationModelLayerRegister.get(eModelLayer);
377

    
378
                switch (status) {
379
                case ADD:
380
                    addLayer(eModelLayer);
381
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
382
                    break;
383
                case REMOVE:
384
                    removeLayer(eModelLayer);
385
                    removedLayers.add(eModelLayer);
386
                    break;
387
                case DIRTY:
388
                    updateLayer(eModelLayer);
389
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
390
                    break;
391
                case CLEAN:
392
                    break;
393

    
394
                case SYMBOL_CHANGED:
395
                    // unused for elevation at the time
396
                    break;
397
                }
398
            }
399

    
400
            for (FLayer fLayer : removedLayers) {
401
                if (dataLayerRegister.containsKey(fLayer)) {
402
                    dataLayerRegister.remove(fLayer);
403
                    break;
404
                } else if (elevationModelLayerRegister.containsKey(fLayer)) {
405
                    elevationModelLayerRegister.remove(fLayer);
406
                    break;
407
                }
408
            }
409
        }
410
    }
411

    
412
    protected void synchronizeViewPorts() {
413

    
414
        // Convert envelope to WorldWind sector
415
        ViewPort viewPort = this.mapContext.getViewPort();
416
        Envelope envelope = viewPort.getEnvelope();
417
        Sector sector = getSector(envelope);
418

    
419
        // Create a bounding box for the specified sector in order to estimate
420
        // its size in model coordinates.
421
        Box extent =
422
            Sector.computeBoundingBox(wwd.getModel().getGlobe(), mapControl3D.getVerticalExaggeration(), sector);
423

    
424
        // Estimate the distance between the center position and the eye
425
        // position that is necessary to cause the sector to
426
        // fill a viewport with the specified field of view. Note that we change
427
        // the distance between the center and eye
428
        // position here, and leave the field of view constant.
429
        Angle fov = wwd.getView().getFieldOfView();
430
        double zoom = extent.getRadius() / fov.cosHalfAngle() / fov.tanHalfAngle();
431

    
432
        View3DSwingManager swingManager = View3DSwingLocator.getManager();
433
        GeneralProperties3D general3dProperties = swingManager.getGeneral3DProperties();
434

    
435
        if (general3dProperties.getViewPortAnimation()) {
436
            wwd.getView().goTo(new Position(sector.getCentroid(), 0d), zoom);
437
        } else {
438
            ((OrbitView) wwd.getView()).setCenterPosition(new Position(sector.getCentroid(), 0d));
439
            ((OrbitView) wwd.getView()).setZoom(zoom);
440
            wwd.redraw();
441
        }
442
    }
443

    
444
    private Sector getSector(Envelope envelope) {
445

    
446
        Point2D p1 = null;
447
        Point2D p2 = null;
448

    
449
        p1 = new Point2D.Double(envelope.getMinimum(0), envelope.getMinimum(1));
450
        p2 = new Point2D.Double(envelope.getMaximum(0), envelope.getMaximum(1));
451

    
452
        double minLatitude =
453
            Double.isInfinite(p1.getY()) || p1.getY() < Angle.NEG90.degrees ? Angle.NEG90.degrees : p1.getY();
454
        double maxLatitude =
455
            Double.isInfinite(p2.getY()) || p2.getY() > Angle.POS90.degrees ? Angle.POS90.degrees : p2.getY();
456
        double minLongitude =
457
            Double.isInfinite(p1.getX()) || p1.getX() < Angle.NEG180.degrees ? Angle.NEG180.degrees : p1.getX();
458
        double maxLongitude =
459
            Double.isInfinite(p2.getX()) || p2.getX() > Angle.POS180.degrees ? Angle.POS180.degrees : p2.getX();
460

    
461
        Sector sector = new Sector(Sector.fromDegrees(minLatitude, maxLatitude, minLongitude, maxLongitude));
462

    
463
        return sector;
464
    }
465

    
466
    private void updateLayer(FLayer layer) {
467
        int index = getLayerIndex(layer);
468
        if (removeLayer(layer)) {
469
            addLayer(layer, index);
470
        }
471
    }
472

    
473
    private void updateLayerSymbol(FLayer layer) {
474
        Layer nwwLayer = getDataLayer(layer);
475
        if (nwwLayer instanceof NwwVectorLayer) {
476
            NwwVectorLayer nwwVectorLayer = (NwwVectorLayer) nwwLayer;
477
            if (layer instanceof FLyrVect) {
478
                FLyrVect gvsigVectorLayer = (FLyrVect) layer;
479
                nwwVectorLayer.updateLegend();
480
            }
481
        }
482
    }
483

    
484
    private int getLayerIndex(FLayer layer) {
485

    
486
        View3DManager manager = View3DLocator.getManager();
487
        LayerProperties3D layerProperties = manager.getLayerProperties(layer, null);
488

    
489
        int index = 0;
490
        if (layerProperties instanceof ElevationLayerProperties3D) {
491
            ElevationModel layerEModel = getElevationModel(layer);
492
            CompoundElevationModel eModel = (CompoundElevationModel) wwd.getModel().getGlobe().getElevationModel();
493
            if (layerEModel != null) {
494
                index = eModel.getElevationModels().indexOf(layerEModel);
495
            } else {
496
                return eModel.getElevationModels().size();
497
            }
498
        } else {
499
            Layer dataLayer = getDataLayer(layer);
500
            if (dataLayer != null) {
501
                index = wwd.getModel().getLayers().indexOf(dataLayer);
502
            } else {
503
                return wwd.getModel().getLayers().size();
504
            }
505
        }
506

    
507
        return index;
508
    }
509

    
510
    private void addLayer(FLayer layer) {
511
        try {
512
            this.mapControl3D.addGvSIGLayer(layer);
513
        } catch (DataException e) {
514
            LOG.error("Can't add {} to MapControl3D", layer.getName());
515
        }
516
    }
517

    
518
    private boolean addLayer(FLayer layer, int pos) {
519
        try {
520
            this.mapControl3D.addGvSIGLayer(layer, pos);
521
            return true;
522
        } catch (DataException e) {
523
            LOG.error("Can't add {} to MapControl3D", layer.getName());
524
            return false;
525
        }
526
    }
527

    
528
    private boolean removeLayer(FLayer layer) {
529

    
530
        ElevationModel eModel = getElevationModel(layer);
531

    
532
        if (eModel != null) {
533
            CompoundElevationModel compoundEModel =
534
                (CompoundElevationModel) wwd.getModel().getGlobe().getElevationModel();
535
            compoundEModel.removeElevationModel(eModel);
536
            return true;
537
        } else {
538
            Layer dataLayer = getDataLayer(layer);
539
            if (dataLayer != null) {
540
                wwd.getModel().getLayers().remove(dataLayer);
541
                return true;
542
            }
543
        }
544
        return false;
545
    }
546

    
547
    private void moveLayer(FLayer layer, int oldPos, int newPos) {
548

    
549
        int index = getLayerIndex(layer);
550
        removeLayer(layer);
551
        addLayer(layer, index + (newPos - oldPos));
552
    }
553
}
554

    
555
enum LAYER_SYNCHRONIZE_STATUS {
556
    ADD, CLEAN, DIRTY, REMOVE, SYMBOL_CHANGED
557
};