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

History | View | Annotate | Download (17.8 KB)

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

    
3
import gov.nasa.worldwind.WorldWindow;
4
import gov.nasa.worldwind.avlist.AVKey;
5
import gov.nasa.worldwind.avlist.AVList;
6
import gov.nasa.worldwind.geom.Angle;
7
import gov.nasa.worldwind.geom.Box;
8
import gov.nasa.worldwind.geom.Position;
9
import gov.nasa.worldwind.geom.Sector;
10
import gov.nasa.worldwind.globes.ElevationModel;
11
import gov.nasa.worldwind.layers.Layer;
12
import gov.nasa.worldwind.terrain.CompoundElevationModel;
13
import gov.nasa.worldwind.view.orbit.OrbitView;
14

    
15
import java.awt.geom.Point2D;
16
import java.util.ArrayList;
17
import java.util.HashMap;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Map.Entry;
21

    
22
import org.gvsig.fmap.dal.exception.DataException;
23
import org.gvsig.fmap.geom.primitive.Envelope;
24
import org.gvsig.fmap.mapcontext.MapContext;
25
import org.gvsig.fmap.mapcontext.ViewPort;
26
import org.gvsig.fmap.mapcontext.events.ColorEvent;
27
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
28
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
29
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
30
import org.gvsig.fmap.mapcontext.layers.CancelationException;
31
import org.gvsig.fmap.mapcontext.layers.FLayer;
32
import org.gvsig.fmap.mapcontext.layers.FLayers;
33
import org.gvsig.fmap.mapcontext.layers.LayerCollectionEvent;
34
import org.gvsig.fmap.mapcontext.layers.LayerCollectionListener;
35
import org.gvsig.fmap.mapcontext.layers.LayerEvent;
36
import org.gvsig.fmap.mapcontext.layers.LayerListener;
37
import org.gvsig.fmap.mapcontext.layers.LayerPositionEvent;
38
import org.gvsig.fmap.mapcontext.layers.operations.LayersVisitor;
39
import org.gvsig.tools.exception.BaseException;
40
import org.gvsig.tools.visitor.VisitCanceledException;
41
import org.gvsig.view3d.lib.api.View3DLocator;
42
import org.gvsig.view3d.lib.api.View3DManager;
43
import org.gvsig.view3d.lib.api.properties.LayerProperties3D;
44
import org.gvsig.view3d.swing.api.View3DSwingLocator;
45
import org.gvsig.view3d.swing.api.View3DSwingManager;
46
import org.gvsig.view3d.swing.api.properties.GeneralProperties3D;
47
import org.gvsig.view3d.swing.api.properties.MapControlProperties3D;
48
import org.gvsig.view3d.swing.impl.data.DefaultTiledImageLayer;
49
import org.slf4j.Logger;
50
import org.slf4j.LoggerFactory;
51

    
52
public class DefaultSynchronizer {
53

    
54
    private static final Logger LOG = LoggerFactory
55
        .getLogger(DefaultSynchronizer.class);
56

    
57
    private Map<FLayer, LAYER_SYNCHRONIZE_STATUS> tiledlayerRegister =
58
        new HashMap<FLayer, LAYER_SYNCHRONIZE_STATUS>();
59

    
60
    private Map<FLayer, LAYER_SYNCHRONIZE_STATUS> elevationModelLayerRegister =
61
        new HashMap<FLayer, LAYER_SYNCHRONIZE_STATUS>();
62

    
63
    private DefaultMapControl3D mapControl3D;
64
    private MapContext mapContext;
65
    private WorldWindow wwd;
66
    
67
    private Object synchronizingLayerLock = new Object();
68

    
69
    protected DefaultSynchronizer(DefaultMapControl3D theMapControl3D,
70
        MapContext theMapContext, WorldWindow wwd) {
71

    
72
        this.mapControl3D = theMapControl3D;
73
        this.mapContext = theMapContext;
74
        this.wwd = wwd;
75

    
76
        intializeRegisters();
77

    
78
        addLayerCollectionListener(mapContext.getLayers());
79
        addLayerListener(mapContext.getLayers());
80
        addViewPortListener(mapContext.getViewPort());
81
    }
82

    
83
    private void intializeRegisters() {
84

    
85
        FLayers layers = mapContext.getLayers();
86

    
87
        try {
88
            layers.accept(new LayersVisitor() {
89

    
90
                public void visit(Object obj) throws VisitCanceledException,
91
                    BaseException {
92
                    throw new UnsupportedOperationException();
93

    
94
                }
95

    
96
                public void visit(FLayer layer) throws BaseException {
97

    
98
                    View3DManager manager = View3DLocator.getManager();
99
                    LayerProperties3D layerProperties =
100
                        manager.getLayerProperties(layer);
101

    
102
                    if (layerProperties.getElevation() == true) {
103
                        elevationModelLayerRegister.put(layer,
104
                            LAYER_SYNCHRONIZE_STATUS.CLEAN);
105
                    } else {
106
                        tiledlayerRegister.put(layer,
107
                            LAYER_SYNCHRONIZE_STATUS.CLEAN);
108
                    }
109
                }
110
            });
111
        } catch (BaseException e) {
112
            LOG.error(
113
                "Can't initialize register of layers to auto synchronize.", e);
114
            mapControl3D.getProperties().setAutoLayerSynchronize(false);
115
        }
116
    }
117

    
118
    private void addLayerListener(FLayer layer) {
119
        if (layer == null) {
120
            return;
121
        }
122
        layer.addLayerListener(getLayerListener());
123
    }
124

    
125
    private void addLayerCollectionListener(FLayers layers) {
126

    
127
        if (layers == null) {
128
            return;
129
        }
130

    
131
        layers.addLayerCollectionListener(new LayerCollectionListener() {
132

    
133
            public void layerAdded(LayerCollectionEvent e) {
134
                FLayer affectedLayer = e.getAffectedLayer();
135
                affectedLayer.addLayerListener(getLayerListener());
136
                updateLayerState(affectedLayer, LAYER_SYNCHRONIZE_STATUS.ADD);
137
                if (mapControl3D.getProperties().getAutoLayerSynchronize()) {
138
                    synchronizeLayers();
139
                }
140
            }
141

    
142
            public void layerAdding(LayerCollectionEvent e)
143
                throws CancelationException {
144
            }
145

    
146
            public void layerMoved(LayerPositionEvent e) {
147
                FLayer affectedLayer = e.getAffectedLayer();
148
                int oldPos = e.getOldPos();
149
                int newPos = e.getNewPos();
150
                moveLayer(affectedLayer, oldPos, newPos);
151
            }
152

    
153
            public void layerMoving(LayerPositionEvent e)
154
                throws CancelationException {
155
            }
156

    
157
            public void layerRemoved(LayerCollectionEvent e) {
158
            }
159

    
160
            public void layerRemoving(LayerCollectionEvent e)
161
                throws CancelationException {
162
                FLayer affectedLayer = e.getAffectedLayer();
163
                updateLayerState(affectedLayer, LAYER_SYNCHRONIZE_STATUS.REMOVE);
164
                if (mapControl3D.getProperties().getAutoLayerSynchronize()) {
165
                    synchronizeLayers();
166
                }
167
            }
168

    
169
            public void visibilityChanged(LayerCollectionEvent e)
170
                throws CancelationException {
171
            }
172
        });
173
    }
174

    
175
    private LayerListener getLayerListener() {
176
        return new LayerListener() {
177

    
178
            public void activationChanged(LayerEvent e) {
179
            }
180

    
181
            public void drawValueChanged(LayerEvent e) {
182
                FLayer layer = e.getSource();
183
                updateLayerState(layer, LAYER_SYNCHRONIZE_STATUS.DIRTY);
184

    
185
                MapControlProperties3D properties =
186
                    mapControl3D.getProperties();
187
                if (properties.getAutoLayerSynchronize()) {
188
                    synchronizeLayers();
189
                }
190
            }
191

    
192
            public void editionChanged(LayerEvent e) {
193
            }
194

    
195
            public void nameChanged(LayerEvent e) {
196
            }
197

    
198
            public void visibilityChanged(LayerEvent e) {
199
                FLayer layer = e.getSource();
200

    
201
                updateLayerState(layer, LAYER_SYNCHRONIZE_STATUS.DIRTY);
202
                if (mapControl3D.getProperties().getAutoLayerSynchronize()) {
203
                    synchronizeLayers();
204
                }
205
            }
206
        };
207
    }
208
    
209
    private void addViewPortListener(ViewPort viewPort) {
210
        
211
        viewPort.addViewPortListener(new ViewPortListener() {
212
            
213
            public void projectionChanged(ProjectionEvent e) {
214
            }
215
            
216
            public void extentChanged(ExtentEvent e) {
217
                MapControlProperties3D properties =
218
                    mapControl3D.getProperties();
219
                boolean autoViewSynchronize =
220
                    properties.getAutoViewPortSynchronize();
221
                if (autoViewSynchronize) {
222
                    synchronizeViewPorts();
223
                }
224
            }
225
            
226
            public void backColorChanged(ColorEvent e) {
227
            }
228
        });
229
    }
230

    
231

    
232
    private Layer getTileImageLayer(FLayer layer) {
233
        List<Layer> layers =
234
            wwd.getModel().getLayers().getLayersByClass(DefaultTiledImageLayer.class);
235
        for (Layer tiledLayer : layers) {
236
            AVList constructionParams =
237
                (AVList) tiledLayer.getValue(AVKey.CONSTRUCTION_PARAMETERS);
238
            if (constructionParams != null) {
239
                FLayer likedLayer =
240
                    (FLayer) constructionParams
241
                        .getValue(DefaultMapControl3D.GVSIG_LAYER);
242
                if (layer.equals(likedLayer)) {
243
                    return tiledLayer;
244
                }
245
            }
246
        }
247
        return null;
248
    }
249

    
250
    private ElevationModel getElevationModel(FLayer layer) {
251
        ElevationModel elevationModel = wwd.getModel().getGlobe().getElevationModel();
252

    
253
        if (elevationModel instanceof CompoundElevationModel) {
254
            CompoundElevationModel compoundModel =
255
                (CompoundElevationModel) elevationModel;
256
            List<ElevationModel> elevationModels =
257
                compoundModel.getElevationModels();
258

    
259
            for (ElevationModel eModel : elevationModels) {
260
                if (eModel.getName().equals(layer.getName())) {
261
                    return eModel;
262
                }
263
            }
264
            return null;
265
        }
266

    
267
        if (elevationModel.getName().equals(layer.getName())) {
268
            return elevationModel;
269
        }
270
        return null;
271
    }
272

    
273
    private void updateLayerState(FLayer layer, LAYER_SYNCHRONIZE_STATUS status) {
274

    
275
        View3DManager manager = View3DLocator.getManager();
276
        LayerProperties3D layerProperties = manager.getLayerProperties(layer);
277
        synchronized (synchronizingLayerLock) {
278
            if (layerProperties.getElevation() == true) {
279

    
280
                if (tiledlayerRegister.containsKey(layer)) {
281
                    tiledlayerRegister.remove(layer);
282
                }
283

    
284
                if (elevationModelLayerRegister.containsKey(layer)
285
                    || status == LAYER_SYNCHRONIZE_STATUS.ADD) {
286
                    elevationModelLayerRegister.put(layer, status);
287
                }
288
            } else {
289

    
290
                if (elevationModelLayerRegister.containsKey(layer)) {
291
                    elevationModelLayerRegister.remove(layer);
292
                }
293
                if (tiledlayerRegister.containsKey(layer)
294
                    || status == LAYER_SYNCHRONIZE_STATUS.ADD) {
295
                    tiledlayerRegister.put(layer, status);
296
                }
297
            }
298
        }
299
    }
300

    
301
    protected void synchronizeLayers() {
302

    
303
        List<FLayer> removedLayers = new ArrayList<FLayer>();
304

    
305
        synchronized (synchronizingLayerLock) {
306
            // Synchronize tiledImageLayers
307
            for (Entry<FLayer, LAYER_SYNCHRONIZE_STATUS> entry : tiledlayerRegister
308
                .entrySet()) {
309

    
310
                FLayer tiledLayer = entry.getKey();
311
                LAYER_SYNCHRONIZE_STATUS status =
312
                    tiledlayerRegister.get(tiledLayer);
313

    
314
                switch (status) {
315
                case ADD:
316
                    addLayer(tiledLayer);
317
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
318
                    break;
319
                case REMOVE:
320
                    removeLayer(tiledLayer);
321
                    removedLayers.add(tiledLayer);
322
                    break;
323
                case DIRTY:
324
                    updateLayer(tiledLayer);
325
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
326
                    break;
327
                case CLEAN:
328
                    break;
329
                }
330
            }
331

    
332
            // Synchronize elevationModelLayerRegister
333
            for (Entry<FLayer, LAYER_SYNCHRONIZE_STATUS> entry : elevationModelLayerRegister
334
                .entrySet()) {
335

    
336
                FLayer eModelLayer = entry.getKey();
337
                LAYER_SYNCHRONIZE_STATUS status =
338
                    elevationModelLayerRegister.get(eModelLayer);
339

    
340
                switch (status) {
341
                case ADD:
342
                    addLayer(eModelLayer);
343
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
344
                    break;
345
                case REMOVE:
346
                    removeLayer(eModelLayer);
347
                    removedLayers.add(eModelLayer);
348
                    break;
349
                case DIRTY:
350
                    updateLayer(eModelLayer);
351
                    entry.setValue(LAYER_SYNCHRONIZE_STATUS.CLEAN);
352
                    break;
353
                case CLEAN:
354
                    break;
355
                }
356
            }
357

    
358
            for (FLayer fLayer : removedLayers) {
359
                if (tiledlayerRegister.containsKey(fLayer)) {
360
                    tiledlayerRegister.remove(fLayer);
361
                    break;
362
                } else if (elevationModelLayerRegister.containsKey(fLayer)) {
363
                    elevationModelLayerRegister.remove(fLayer);
364
                    break;
365
                }
366
            }
367
        }
368
    }
369

    
370
    protected void synchronizeViewPorts() {
371
        
372
        // Convert envelope to WorldWind sector
373
        ViewPort viewPort = this.mapContext.getViewPort();
374
        Envelope envelope = viewPort.getEnvelope();
375
        Sector sector = getSector(envelope);
376
        
377
        // Create a bounding box for the specified sector in order to estimate
378
        // its size in model coordinates.
379
        Box extent = Sector.computeBoundingBox(wwd.getModel().getGlobe(),
380
            mapControl3D.getVerticalExaggeration(), sector);
381
        
382
        // Estimate the distance between the center position and the eye
383
        // position that is necessary to cause the sector to
384
        // fill a viewport with the specified field of view. Note that we change
385
        // the distance between the center and eye
386
        // position here, and leave the field of view constant.
387
        Angle fov = wwd.getView().getFieldOfView();
388
        double zoom = extent.getRadius() / fov.cosHalfAngle() / fov.tanHalfAngle();
389
        
390
        View3DSwingManager swingManager = View3DSwingLocator.getManager();
391
        GeneralProperties3D general3dProperties = swingManager.getGeneral3DProperties();
392
        
393
        if(general3dProperties.getViewPortAnimation()){
394
            wwd.getView().goTo(new Position(sector.getCentroid(), 0d), zoom);
395
        } else {
396
            ((OrbitView) wwd.getView()).setCenterPosition(new Position(sector
397
                .getCentroid(), 0d));
398
            ((OrbitView) wwd.getView()).setZoom(zoom);
399
            wwd.redraw();
400
        }
401
    }
402

    
403
    private Sector getSector(Envelope envelope) {
404

    
405
        Point2D p1 = null;
406
        Point2D p2 = null;
407

    
408
        p1 = new Point2D.Double(envelope.getMinimum(0), envelope.getMinimum(1));
409
        p2 = new Point2D.Double(envelope.getMaximum(0), envelope.getMaximum(1));
410

    
411
        double minLatitude =
412
            Double.isInfinite(p1.getY()) || p1.getY() < Angle.NEG90.degrees
413
                ? Angle.NEG90.degrees : p1.getY();
414
        double maxLatitude =
415
            Double.isInfinite(p2.getY()) || p2.getY() > Angle.POS90.degrees
416
                ? Angle.POS90.degrees : p2.getY();
417
        double minLongitude =
418
            Double.isInfinite(p1.getX()) || p1.getX() < Angle.NEG180.degrees
419
                ? Angle.NEG180.degrees : p1.getX();
420
        double maxLongitude =
421
            Double.isInfinite(p2.getX()) || p2.getX() > Angle.POS180.degrees
422
                ? Angle.POS180.degrees : p2.getX();
423

    
424
        Sector sector =
425
            new Sector(Sector.fromDegrees(minLatitude, maxLatitude,
426
                minLongitude, maxLongitude));
427

    
428
        return sector;
429
    }
430
    
431
    private void updateLayer(FLayer layer) {
432
        int index = getLayerIndex(layer);
433
        removeLayer(layer);
434
        addLayer(layer, index);
435
    }
436

    
437
    private int getLayerIndex(FLayer layer) {
438
        
439
        View3DManager manager = View3DLocator.getManager();
440
        LayerProperties3D layerProperties = manager.getLayerProperties(layer);
441
        
442
        int index = 0;
443
        if(layerProperties.getElevation()){
444
            ElevationModel layerEModel = getElevationModel(layer);
445
            CompoundElevationModel eModel =
446
                (CompoundElevationModel) wwd.getModel().getGlobe().getElevationModel();
447
            if(layerEModel != null){
448
                
449
                index = eModel.getElevationModels().indexOf(layerEModel);
450
            } else {
451
                return eModel.getElevationModels().size();
452
            }
453
        } else {
454
            
455
            Layer tileImageLayer = getTileImageLayer(layer);
456
            if(tileImageLayer != null){
457
                index = wwd.getModel().getLayers().indexOf(tileImageLayer);
458
            } else {
459
                return wwd.getModel().getLayers().size();
460
            }
461
        }
462
        
463
        return index;
464
    }
465

    
466
    private void addLayer(FLayer layer) {
467
        try {
468
            this.mapControl3D.addGvSIGLayer(layer);
469
        } catch (DataException e) {
470
            LOG.error("Can't add {} to MapControl3D", layer.getName());
471
        }
472
    }
473

    
474
    private void addLayer(FLayer layer, int pos) {
475
        try {
476
            this.mapControl3D.addGvSIGLayer(layer, pos);
477
        } catch (DataException e) {
478
            LOG.error("Can't add {} to MapControl3D", layer.getName());
479
        }
480
    }
481

    
482
    private void removeLayer(FLayer layer) {
483

    
484
        ElevationModel eModel = getElevationModel(layer);
485
        Layer tiledImageLayer = getTileImageLayer(layer);
486

    
487
        if (eModel != null) {
488
            CompoundElevationModel compoundEModel =
489
                (CompoundElevationModel) wwd.getModel().getGlobe().getElevationModel();
490
            compoundEModel.removeElevationModel(eModel);
491
        } else if (tiledImageLayer != null) {
492
            wwd.getModel().getLayers().remove(tiledImageLayer);
493
        }
494
    }
495

    
496
    private void moveLayer(FLayer layer, int oldPos, int newPos) {
497
        
498
        int index = getLayerIndex(layer);
499
        removeLayer(layer);
500
        addLayer(layer, index + (newPos - oldPos));
501
    }
502
}
503

    
504
enum LAYER_SYNCHRONIZE_STATUS {
505
    ADD, CLEAN, DIRTY, REMOVE
506
};