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 / DefaultMapControl3D.java @ 486

History | View | Annotate | Download (15.7 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;
26

    
27
import gov.nasa.worldwind.Configuration;
28
import gov.nasa.worldwind.Model;
29
import gov.nasa.worldwind.WorldWind;
30
import gov.nasa.worldwind.avlist.AVKey;
31
import gov.nasa.worldwind.awt.WorldWindowGLJPanel;
32
import gov.nasa.worldwind.globes.Earth;
33
import gov.nasa.worldwind.globes.EarthFlat;
34
import gov.nasa.worldwind.globes.Globe;
35
import gov.nasa.worldwind.layers.CompassLayer;
36
import gov.nasa.worldwind.layers.Layer;
37
import gov.nasa.worldwind.layers.LayerList;
38
import gov.nasa.worldwind.layers.ScalebarLayer;
39
import gov.nasa.worldwind.layers.SkyColorLayer;
40
import gov.nasa.worldwind.layers.SkyGradientLayer;
41
import gov.nasa.worldwind.layers.StarsLayer;
42
import gov.nasa.worldwind.layers.ViewControlsLayer;
43
import gov.nasa.worldwind.layers.ViewControlsSelectListener;
44
import gov.nasa.worldwind.layers.WorldMapLayer;
45
import gov.nasa.worldwind.util.StatusBar;
46
import gov.nasa.worldwind.view.orbit.BasicOrbitView;
47
import gov.nasa.worldwind.view.orbit.FlatOrbitView;
48

    
49
import java.awt.BorderLayout;
50
import java.awt.Dimension;
51
import java.lang.reflect.Constructor;
52
import java.lang.reflect.InvocationTargetException;
53
import java.util.List;
54

    
55
import javax.swing.JComponent;
56
import javax.swing.JPanel;
57

    
58
import org.gvsig.fmap.dal.exception.DataException;
59
import org.gvsig.fmap.mapcontext.MapContext;
60
import org.gvsig.fmap.mapcontext.layers.FLayer;
61
import org.gvsig.fmap.mapcontext.layers.operations.LayersVisitor;
62
import org.gvsig.tools.exception.BaseException;
63
import org.gvsig.tools.observer.BaseNotification;
64
import org.gvsig.tools.observer.Notification;
65
import org.gvsig.tools.observer.ObservableHelper;
66
import org.gvsig.tools.observer.Observer;
67
import org.gvsig.tools.task.Cancellable;
68
import org.gvsig.tools.visitor.VisitCanceledException;
69
import org.gvsig.view3d.lib.api.View3DLocator;
70
import org.gvsig.view3d.lib.api.View3DManager;
71
import org.gvsig.view3d.lib.api.properties.LayerProperties3D;
72
import org.gvsig.view3d.swing.api.MapControl3D;
73
import org.gvsig.view3d.swing.api.View3DSwingManager.TYPE;
74
import org.gvsig.view3d.swing.impl.data.DefaultLayerConverter;
75
import org.gvsig.view3d.swing.impl.data.LayerConverter;
76
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
78

    
79
/**
80
 * Default implementation of {@link MapControl3D}.
81
 * 
82
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
83
 */
84
@SuppressWarnings("deprecation")
85
public class DefaultMapControl3D extends JPanel implements MapControl3D {
86

    
87
    private static final long serialVersionUID = 2024899922367896097L;
88

    
89
    private static final Logger LOG = LoggerFactory
90
        .getLogger(DefaultMapControl3D.class);
91

    
92
    private ObservableHelper observableHelper;
93

    
94
    /**
95
     * Name of gvSIG MapContext property
96
     */
97
    public static final String GVSIG_MAPCONTROL3D =
98
        "org.gvsig.view3d.swing.api.MapControl3D";
99

    
100
    /**
101
     * Name of gvSIG Layer property
102
     */
103
    public static final String GVSIG_LAYER =
104
        "org.gvsig.fmap.mapcontext.layers.FLayer";
105

    
106
    private MapContext mapContext;
107

    
108
    private WorldWindowGLJPanel wwd;
109

    
110
    private StatusBar statusBar;
111

    
112
    private TYPE type;
113

    
114
    private Cancellable cancellable;
115

    
116
    /**
117
     * Default constructor of {@link DefaultMapControl3D}. Initializes local
118
     * fileds, sets configuration depends on {@link TYPE} and adds
119
     * <code>MapContext</code> layers.
120
     * 
121
     * @param theMapContext
122
     *            associated <code>MapContext</code>
123
     * @param type
124
     *            Type of this {@link DefaultMapControl3D}. See {@link TYPE}.
125
     */
126
    public DefaultMapControl3D(MapContext theMapContext, TYPE type) {
127

    
128
        super(new BorderLayout());
129

    
130
        this.mapContext = theMapContext;
131
        this.type = type;
132
        this.cancellable = getCancellable();
133
        this.observableHelper = new ObservableHelper();
134

    
135
        // Set mode before instantiation
136
        if (type == TYPE.SPHERE) {
137
            setSpherePanelConfiguration();
138
        } else if (type == TYPE.FLAT) {
139
            setFlatPanelConfiguration();
140
        }
141

    
142
        super.add(getWwd(), BorderLayout.CENTER);
143

    
144
        super.add(getStatusBar(), BorderLayout.SOUTH);
145

    
146
        try {
147
            addLayers();
148
        } catch (BaseException e) {
149
            LOG.info("Can't add MapControl layers", e);
150
        }
151

    
152
    }
153

    
154
    private void addGvSIGLayer(FLayer layer) throws DataException {
155

    
156
        LayerConverter converter = new DefaultLayerConverter();
157
        
158
        View3DManager manager = View3DLocator.getManager();
159
        LayerProperties3D layerProperties = manager.getLayerProperties(layer);
160
        
161
        // TODO Check load mode to create WW Layer
162
        Layer rasterTiledLayer = converter.convertToLayer(this, layer);
163

    
164
        getWwd().getModel().getLayers().add(rasterTiledLayer);
165
    }
166

    
167
    private void addLayers() throws BaseException {
168
        mapContext.getLayers().accept(new LayersVisitor() {
169

    
170
            public void visit(Object obj) throws VisitCanceledException,
171
                BaseException {
172
                throw new UnsupportedOperationException();
173

    
174
            }
175

    
176
            public void visit(FLayer layer) throws BaseException {
177
                // TODO Make new threads to add layers
178
                if (layer.isAvailable() && layer.isVisible()) {
179
                    addGvSIGLayer(layer);
180
                }
181
            }
182
        });
183

    
184
        getWwd().redraw();
185
    }
186

    
187
    @SuppressWarnings("rawtypes")
188
    private void addWWLayer(Class layerClazz) throws InstantiationException,
189
        IllegalAccessException, IllegalArgumentException,
190
        InvocationTargetException {
191
        LayerList layerList = getWwd().getModel().getLayers();
192

    
193
        if (isAlreadyAdded(layerList, layerClazz)) {
194
            return;
195
        }
196

    
197
        Constructor[] constructors = layerClazz.getConstructors();
198
        for (int i = 0; i < constructors.length; i++) {
199
            if (constructors[i].getParameterTypes().length == 0) {
200
                layerList.add((Layer) constructors[i].newInstance());
201
            }
202
        }
203
    }
204

    
205
    private void addNavigation() {
206

    
207
        ViewControlsLayer controlsLayer = new ViewControlsLayer();
208

    
209
        Model model = getWwd().getModel();
210
        model.getLayers().add(controlsLayer);
211

    
212
        getWwd().addSelectListener(
213
            new ViewControlsSelectListener(wwd, controlsLayer));
214
    }
215

    
216
    public JComponent asJComponent() {
217
        return this;
218
    }
219

    
220
    public void dispose() {
221

    
222
        Thread disposeThread = new Thread(new Runnable() {
223

    
224
            public void run() {
225
                Notification beforeDisposeNotification =
226
                    new BaseNotification(
227
                        MapControl3D.BEFORE_DISPOSE_MAPCONTEX3D_NOTIFICATION,
228
                        null);
229

    
230
                observableHelper.notifyObservers(DefaultMapControl3D.this,
231
                    beforeDisposeNotification);
232

    
233
                while (WorldWind.getRetrievalService().hasActiveTasks()) {
234
                    try {
235
                        Thread.sleep(100);
236
                    } catch (InterruptedException e) {
237
                        LOG.warn("This thread has been interrupted, dispose action can not be performed");
238
                        return;
239
                    }
240
                }
241

    
242
                disposeWwd();
243

    
244
                Notification afterDisposeNotification =
245
                    new BaseNotification(
246
                        MapControl3D.AFTER_DISPOSE_MAPCONTEX3D_NOTIFICATION,
247
                        null);
248

    
249
                observableHelper.notifyObservers(DefaultMapControl3D.this,
250
                    afterDisposeNotification);
251
            }
252
        }, "Dispose World Wind thread");
253

    
254
        disposeThread.start();
255
    }
256

    
257
    public Cancellable getCancellable() {
258
        if (this.cancellable == null) {
259
            this.cancellable = new Cancellable() {
260

    
261
                private boolean cancel = false;
262

    
263
                public void setCanceled(boolean canceled) {
264
                    this.cancel = canceled;
265
                }
266

    
267
                public boolean isCanceled() {
268
                    return cancel;
269
                }
270
            };
271
        }
272

    
273
        return this.cancellable;
274
    }
275

    
276
    public MapContext getMapContext() {
277
        return this.mapContext;
278
    }
279

    
280
    private StatusBar getStatusBar() {
281
        if (statusBar == null) {
282
            statusBar = new StatusBar();
283
            this.add(statusBar, BorderLayout.PAGE_END);
284
            statusBar.setEventSource(wwd);
285
        }
286
        return statusBar;
287
    }
288

    
289
    public TYPE getType() {
290
        return this.type;
291
    }
292

    
293
    public double getVerticalExaggeration() {
294
        return getWwd().getSceneController().getVerticalExaggeration();
295
    }
296

    
297
    protected WorldWindowGLJPanel getWwd() {
298
        if (this.wwd == null) {
299
            intializeWWPanel();
300
        }
301
        return this.wwd;
302
    }
303

    
304
    private void disposeWwd() {
305
        if (getWwd() != null) {
306
            this.wwd = null;
307
        }
308
    }
309

    
310
    public void hideAtmosphere() {
311
        hideLayer(SkyGradientLayer.class);
312
    }
313

    
314
    @SuppressWarnings("rawtypes")
315
    private void hideLayer(Class layerClazz) {
316
        LayerList layers = getWwd().getModel().getLayers();
317
        List<Layer> layersByClass = layers.getLayersByClass(layerClazz);
318
        layers.removeAll(layersByClass);
319
    }
320

    
321
    public void hideMiniMap() {
322
        hideLayer(WorldMapLayer.class);
323
    }
324

    
325
    public void hideNorthIndicator() {
326
        hideLayer(CompassLayer.class);
327
    }
328

    
329
    public void hideScale() {
330
        hideLayer(ScalebarLayer.class);
331
    }
332

    
333
    public void hideStarBackground() {
334
        hideLayer(StarsLayer.class);
335
    }
336

    
337
    private void intializeWWPanel() {
338
        wwd = new WorldWindowGLJPanel();
339
        wwd.setPreferredSize(new Dimension(800, 600));
340

    
341
        // Create the default model as described in the current worldwind
342
        // properties.
343
        Model m =
344
            (Model) WorldWind
345
                .createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
346
        getWwd().setModel(m);
347

    
348
        // Add view control layer
349
        addNavigation();
350
    }
351

    
352
    private boolean isAlreadyAdded(LayerList layerList,
353
        @SuppressWarnings("rawtypes") Class clazz) {
354

    
355
        List<Layer> layersByClass = layerList.getLayersByClass(clazz);
356

    
357
        return layersByClass.size() > 0;
358
    }
359

    
360
    public void reloadLayers() {
361
        // TODO
362
        throw new UnsupportedOperationException();
363
    }
364

    
365
    private void removeAllLayers() {
366
        getWwd().getModel().getLayers().removeAll();
367
    }
368

    
369
    private void setFlatPanelConfiguration() {
370
        Configuration.setValue(AVKey.GLOBE_CLASS_NAME,
371
            EarthFlat.class.getName());
372
        Configuration.setValue(AVKey.VIEW_CLASS_NAME,
373
            FlatOrbitView.class.getName());
374
    }
375

    
376
    public void setMapContext(MapContext theMapContext) {
377
        this.mapContext = theMapContext;
378
    }
379

    
380
    private void setSpherePanelConfiguration() {
381
        Configuration.setValue(AVKey.GLOBE_CLASS_NAME, Earth.class.getName());
382
        Configuration.setValue(AVKey.VIEW_CLASS_NAME,
383
            BasicOrbitView.class.getName());
384
    }
385

    
386
    public void setVerticalExaggeration(double verticalExaggeration) {
387
        getWwd().getSceneController().setVerticalExaggeration(
388
            verticalExaggeration);
389
    }
390

    
391
    public void showAtmosphere() {
392
        try {
393
            Globe globe = getWwd().getModel().getGlobe();
394
            if (globe instanceof Earth) {
395
                getWwd().getModel().getLayers().add(new SkyGradientLayer());
396
                addWWLayer(SkyGradientLayer.class);
397
            } else if (globe instanceof EarthFlat) {
398
                getWwd().getModel().getLayers().add(new SkyColorLayer());
399
                addWWLayer(SkyColorLayer.class);
400
            }
401
        } catch (Exception e) {
402
            LOG.warn("Can't add {} or {} to {}",
403
                new Object[] { SkyGradientLayer.class.getCanonicalName(),
404
                    SkyColorLayer.class.getCanonicalName(),
405
                    getWwd().getModel().toString() }, e);
406
        }
407
    }
408

    
409
    public void showMiniMap() {
410
        try {
411
            addWWLayer(WorldMapLayer.class);
412
        } catch (Exception e) {
413
            LOG.warn("Can't add {} to {}",
414
                new Object[] { WorldMapLayer.class.getCanonicalName(),
415
                    getWwd().getModel().toString() }, e);
416
        }
417
    }
418

    
419
    public void showNortIndicator() {
420
        try {
421
            addWWLayer(CompassLayer.class);
422
        } catch (Exception e) {
423
            LOG.warn("Can't add {} to {}",
424
                new Object[] { CompassLayer.class.getCanonicalName(),
425
                    getWwd().getModel().toString() }, e);
426
        }
427
    }
428

    
429
    public void showScale() {
430
        try {
431
            addWWLayer(ScalebarLayer.class);
432
        } catch (Exception e) {
433
            LOG.warn("Can't add {} to {}",
434
                new Object[] { ScalebarLayer.class.getCanonicalName(),
435
                    getWwd().getModel().toString() }, e);
436
        }
437
    }
438

    
439
    public void showStarBackgroundLayer() {
440
        try {
441
            addWWLayer(StarsLayer.class);
442
        } catch (Exception e) {
443
            LOG.warn("Can't add {} to {}",
444
                new Object[] { StarsLayer.class.getCanonicalName(),
445
                    getWwd().getModel().toString() }, e);
446
        }
447
    }
448

    
449
    public void synchronizeLayers() {
450
        // TODO
451
        throw new UnsupportedOperationException();
452
    }
453

    
454
    public void synchronizeViewPorts() {
455
        // TODO
456
        throw new UnsupportedOperationException();
457
    }
458

    
459
    public void addObserver(Observer o) {
460
        if (observableHelper != null) {
461
            observableHelper.addObserver(o);
462
        }
463
    }
464

    
465
    public void deleteObserver(Observer o) {
466
        if (observableHelper != null) {
467
            observableHelper.deleteObserver(o);
468
        }
469

    
470
    }
471

    
472
    public void deleteObservers() {
473
        if (observableHelper != null) {
474
            observableHelper.deleteObservers();
475
        }
476
    }
477

    
478
    public boolean isAtmosphereVisible() {
479
        LayerList layerList = getWwd().getModel().getLayers();
480
        if (isAlreadyAdded(layerList, SkyGradientLayer.class)
481
            || isAlreadyAdded(layerList, SkyColorLayer.class)) {
482
            return true;
483
        }
484
        return false;
485
    }
486

    
487
    public boolean isMinimapVisible() {
488
        LayerList layerList = getWwd().getModel().getLayers();
489
        if (isAlreadyAdded(layerList, WorldMapLayer.class)) {
490
            return true;
491
        }
492
        return false;
493
    }
494

    
495
    public boolean isNorthIndicatorVisible() {
496
        LayerList layerList = getWwd().getModel().getLayers();
497
        if (isAlreadyAdded(layerList, CompassLayer.class)) {
498
            return true;
499
        }
500
        return false;
501
    }
502
    
503
    public boolean isStartBackgroundVisible(){
504
        LayerList layerList = getWwd().getModel().getLayers();
505
        if (isAlreadyAdded(layerList, StarsLayer.class)) {
506
            return true;
507
        }
508
        return false;
509
    }
510

    
511
    public boolean isScaleVisible() {
512
        LayerList layerList = getWwd().getModel().getLayers();
513
        if (isAlreadyAdded(layerList, ScalebarLayer.class)) {
514
            return true;
515
        }
516
        return false;
517
    }
518
}