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 @ 473

History | View | Annotate | Download (13.8 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.swing.api.MapControl3D;
70
import org.gvsig.view3d.swing.api.View3DSwingManager.TYPE;
71
import org.gvsig.view3d.swing.impl.data.DefaultLayerConverter;
72
import org.gvsig.view3d.swing.impl.data.LayerConverter;
73
import org.slf4j.Logger;
74
import org.slf4j.LoggerFactory;
75

    
76
/**
77
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
78
 *
79
 */
80
@SuppressWarnings("deprecation")
81
public class DefaultMapControl3D extends JPanel implements MapControl3D {
82

    
83
    private static final long serialVersionUID = 2024899922367896097L;
84

    
85
    private static final Logger LOG = LoggerFactory
86
        .getLogger(DefaultMapControl3D.class);
87
    
88
    private ObservableHelper observableHelper;
89

    
90
    /**
91
     * Name of gvSIG MapContext property
92
     */
93
    public static final String GVSIG_MAPCONTROL3D =
94
        "org.gvsig.view3d.swing.api.MapControl3D";
95

    
96
    /**
97
     * Name of gvSIG Layer property
98
     */
99
    public static final String GVSIG_LAYER =
100
        "org.gvsig.fmap.mapcontext.layers.FLayer";
101

    
102
    private MapContext mapContext;
103

    
104
    private WorldWindowGLJPanel wwd;
105

    
106
    private StatusBar statusBar;
107

    
108
    private TYPE type;
109
    
110
    private Cancellable cancellable;
111

    
112
    public DefaultMapControl3D(MapContext theMapContext, TYPE type) {
113

    
114
        super(new BorderLayout());
115

    
116
        this.mapContext = theMapContext;
117
        this.type = type;
118
        this.cancellable = getCancellable();
119
        this.observableHelper = new ObservableHelper();
120

    
121
        // Set mode before instantiation
122
        if (type == TYPE.SPHERE) {
123
            setSpherePanelConfiguration();
124
        } else if (type == TYPE.FLAT) {
125
            setFlatPanelConfiguration();
126
        }
127

    
128
        super.add(getWwd(), BorderLayout.CENTER);
129

    
130
        super.add(getStatusBar(), BorderLayout.SOUTH);
131

    
132
        try {
133
            addLayers();
134
        } catch (BaseException e) {
135
            LOG.info("Can't add MapControl layers", e);
136
        }
137

    
138
    }
139

    
140
    private void addGvSIGLayer(FLayer layer) throws DataException {
141

    
142
        LayerConverter converter = new DefaultLayerConverter();
143

    
144
        // TODO Check load mode to create WW Layer
145
        Layer rasterTiledLayer = converter.convertToLayer(this, layer);
146

    
147
        getWwd().getModel().getLayers().add(rasterTiledLayer);
148
    }
149

    
150
    private void addLayers() throws BaseException {
151
        mapContext.getLayers().accept(new LayersVisitor() {
152

    
153
            public void visit(Object obj) throws VisitCanceledException,
154
                BaseException {
155
                throw new UnsupportedOperationException();
156

    
157
            }
158

    
159
            public void visit(FLayer layer) throws BaseException {
160
                // TODO Make new threads to add layers
161
                if (layer.isAvailable() && layer.isVisible()) {
162
                    addGvSIGLayer(layer);
163
                }
164
            }
165
        });
166

    
167
        getWwd().redraw();
168
    }
169

    
170
    @SuppressWarnings("rawtypes")
171
    private void addWWLayer(Class layerClazz) throws InstantiationException,
172
        IllegalAccessException, IllegalArgumentException,
173
        InvocationTargetException {
174
        LayerList layerList = getWwd().getModel().getLayers();
175

    
176
        if (isAlreadyAdded(layerList, layerClazz)) {
177
            return;
178
        }
179

    
180
        Constructor[] constructors = layerClazz.getConstructors();
181
        for (int i = 0; i < constructors.length; i++) {
182
            if (constructors[i].getParameterTypes().length == 0) {
183
                layerList.add((Layer) constructors[i].newInstance());
184
            }
185
        }
186
    }
187

    
188
    private void addNavigation() {
189

    
190
        ViewControlsLayer controlsLayer = new ViewControlsLayer();
191

    
192
        Model model = getWwd().getModel();
193
        model.getLayers().add(controlsLayer);
194

    
195
        getWwd().addSelectListener(
196
            new ViewControlsSelectListener(wwd, controlsLayer));
197
    }
198

    
199
    public JComponent asJComponent() {
200
        return this;
201
    }
202

    
203
    public void dispose() {
204
        
205
        Thread disposeThread = new Thread(new Runnable() {
206
            
207
            public void run() {
208
                Notification beforeDisposeNotification =
209
                    new BaseNotification(
210
                        MapControl3D.BEFORE_DISPOSE_MAPCONTEX3D_NOTIFICATION, null);
211

    
212
                observableHelper.notifyObservers(DefaultMapControl3D.this,
213
                    beforeDisposeNotification);
214

    
215
                while(WorldWind.getRetrievalService().hasActiveTasks()){
216
                    try {
217
                        Thread.sleep(100);
218
                    } catch (InterruptedException e) {
219
                        LOG.warn("This thread has been interrupted, dispose action can not be performed");
220
                        return;
221
                    }
222
                }
223

    
224
                disposeWwd();
225

    
226
                Notification afterDisposeNotification =
227
                    new BaseNotification(
228
                        MapControl3D.AFTER_DISPOSE_MAPCONTEX3D_NOTIFICATION, null);
229

    
230
                observableHelper
231
                    .notifyObservers(DefaultMapControl3D.this, afterDisposeNotification);
232
            }
233
        }, "Dispose World Wind thread");
234
        
235
        disposeThread.start();
236
    }
237
    
238
    public Cancellable getCancellable(){
239
        if(this.cancellable == null){
240
            this.cancellable = new Cancellable() {
241
                
242
                private boolean cancel = false;
243
                
244
                public void setCanceled(boolean canceled) {
245
                    this.cancel = canceled;
246
                }
247
                
248
                public boolean isCanceled() {
249
                    return cancel;
250
                }
251
            };
252
        }
253
        
254
        return this.cancellable;
255
    }
256

    
257
    public MapContext getMapContext() {
258
        return this.mapContext;
259
    }
260

    
261
    private StatusBar getStatusBar() {
262
        if (statusBar == null) {
263
            statusBar = new StatusBar();
264
            this.add(statusBar, BorderLayout.PAGE_END);
265
            statusBar.setEventSource(wwd);
266
        }
267
        return statusBar;
268
    }
269

    
270
    public TYPE getType() {
271
        return this.type;
272
    }
273

    
274
    public double getVerticalExaggeration() {
275
        return getWwd().getSceneController().getVerticalExaggeration();
276
    }
277

    
278
    protected WorldWindowGLJPanel getWwd() {
279
        if (this.wwd == null) {
280
            intializeWWPanel();
281
        }
282
        return this.wwd;
283
    }
284
    
285
    private void disposeWwd(){
286
        if (getWwd() != null) {
287
            this.wwd = null;
288
        }
289
    }
290

    
291
    public void hideAtmosphere() {
292
        hideLayer(SkyGradientLayer.class);
293
    }
294

    
295
    @SuppressWarnings("rawtypes")
296
    private void hideLayer(Class layerClazz) {
297
        LayerList layers = getWwd().getModel().getLayers();
298
        List<Layer> layersByClass = layers.getLayersByClass(layerClazz);
299
        layers.removeAll(layersByClass);
300
    }
301

    
302
    public void hideMiniMap() {
303
        hideLayer(WorldMapLayer.class);
304
    }
305

    
306
    public void hideNorthIndicator() {
307
        hideLayer(CompassLayer.class);
308
    }
309

    
310
    public void hideScale() {
311
        hideLayer(ScalebarLayer.class);
312
    }
313

    
314
    public void hideStarBackground() {
315
        hideLayer(StarsLayer.class);
316
    }
317

    
318
    private void intializeWWPanel() {
319
        wwd = new WorldWindowGLJPanel();
320
        wwd.setPreferredSize(new Dimension(800, 600));
321

    
322
        // Create the default model as described in the current worldwind
323
        // properties.
324
        Model m =
325
            (Model) WorldWind
326
                .createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
327
        getWwd().setModel(m);
328

    
329
        // Add view control layer
330
        addNavigation();
331
    }
332

    
333
    private boolean isAlreadyAdded(LayerList layerList,
334
        @SuppressWarnings("rawtypes") Class clazz) {
335

    
336
        List<Layer> layersByClass = layerList.getLayersByClass(clazz);
337

    
338
        return layersByClass.size() > 0;
339
    }
340

    
341
    public void reloadLayers() {
342
        // TODO
343
        throw new UnsupportedOperationException();
344
    }
345

    
346
    private void removeAllLayers() {
347
        getWwd().getModel().getLayers().removeAll();
348
    }
349

    
350
    private void setFlatPanelConfiguration() {
351
        Configuration.setValue(AVKey.GLOBE_CLASS_NAME,
352
            EarthFlat.class.getName());
353
        Configuration.setValue(AVKey.VIEW_CLASS_NAME,
354
            FlatOrbitView.class.getName());
355
    }
356

    
357
    public void setMapContext(MapContext theMapContext) {
358
        this.mapContext = theMapContext;
359
    }
360

    
361
    private void setSpherePanelConfiguration() {
362
        Configuration.setValue(AVKey.GLOBE_CLASS_NAME, Earth.class.getName());
363
        Configuration.setValue(AVKey.VIEW_CLASS_NAME,
364
            BasicOrbitView.class.getName());
365
    }
366

    
367
    public void setVerticalExaggeration(double verticalExaggeration) {
368
        getWwd().getSceneController().setVerticalExaggeration(
369
            verticalExaggeration);
370
    }
371

    
372
    public void showAtmosphere() {
373
        try {
374
            Globe globe = getWwd().getModel().getGlobe();
375
            if (globe instanceof Earth) {
376
                getWwd().getModel().getLayers().add(new SkyGradientLayer());
377
                addWWLayer(SkyGradientLayer.class);
378
            } else if (globe instanceof EarthFlat) {
379
                getWwd().getModel().getLayers().add(new SkyColorLayer());
380
                addWWLayer(SkyColorLayer.class);
381
            }
382
        } catch (Exception e) {
383
            LOG.warn("Can't add {} or {} to {}",
384
                new Object[] { SkyGradientLayer.class.getCanonicalName(),
385
                    SkyColorLayer.class.getCanonicalName(),
386
                    getWwd().getModel().toString() }, e);
387
        }
388
    }
389

    
390
    public void showMiniMap() {
391
        try {
392
            addWWLayer(WorldMapLayer.class);
393
        } catch (Exception e) {
394
            LOG.warn("Can't add {} to {}",
395
                new Object[] { WorldMapLayer.class.getCanonicalName(),
396
                    getWwd().getModel().toString() }, e);
397
        }
398
    }
399

    
400
    public void showNortIndicator() {
401
        try {
402
            addWWLayer(CompassLayer.class);
403
        } catch (Exception e) {
404
            LOG.warn("Can't add {} to {}",
405
                new Object[] { CompassLayer.class.getCanonicalName(),
406
                    getWwd().getModel().toString() }, e);
407
        }
408
    }
409

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

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

    
430
    public void synchronizeLayers() {
431
        // TODO
432
        throw new UnsupportedOperationException();
433
    }
434

    
435
    public void synchronizeViewPorts() {
436
        // TODO
437
        throw new UnsupportedOperationException();
438
    }
439
    
440
    public void addObserver(Observer o) {
441
        if(observableHelper != null){
442
            observableHelper.addObserver(o);
443
        }
444
    }
445

    
446
    public void deleteObserver(Observer o) {
447
        if(observableHelper != null){
448
            observableHelper.deleteObserver(o);
449
        }
450
        
451
    }
452

    
453
    public void deleteObservers() {
454
        if(observableHelper != null){
455
            observableHelper.deleteObservers();
456
        }
457
    }
458
}