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

History | View | Annotate | Download (14.2 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
 * Default implementation of {@link MapControl3D}.
78
 * 
79
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
80
 */
81
@SuppressWarnings("deprecation")
82
public class DefaultMapControl3D extends JPanel implements MapControl3D {
83

    
84
    private static final long serialVersionUID = 2024899922367896097L;
85

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

    
89
    private ObservableHelper observableHelper;
90

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

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

    
103
    private MapContext mapContext;
104

    
105
    private WorldWindowGLJPanel wwd;
106

    
107
    private StatusBar statusBar;
108

    
109
    private TYPE type;
110

    
111
    private Cancellable cancellable;
112

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

    
125
        super(new BorderLayout());
126

    
127
        this.mapContext = theMapContext;
128
        this.type = type;
129
        this.cancellable = getCancellable();
130
        this.observableHelper = new ObservableHelper();
131

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

    
139
        super.add(getWwd(), BorderLayout.CENTER);
140

    
141
        super.add(getStatusBar(), BorderLayout.SOUTH);
142

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

    
149
    }
150

    
151
    private void addGvSIGLayer(FLayer layer) throws DataException {
152

    
153
        LayerConverter converter = new DefaultLayerConverter();
154

    
155
        // TODO Check load mode to create WW Layer
156
        Layer rasterTiledLayer = converter.convertToLayer(this, layer);
157

    
158
        getWwd().getModel().getLayers().add(rasterTiledLayer);
159
    }
160

    
161
    private void addLayers() throws BaseException {
162
        mapContext.getLayers().accept(new LayersVisitor() {
163

    
164
            public void visit(Object obj) throws VisitCanceledException,
165
                BaseException {
166
                throw new UnsupportedOperationException();
167

    
168
            }
169

    
170
            public void visit(FLayer layer) throws BaseException {
171
                // TODO Make new threads to add layers
172
                if (layer.isAvailable() && layer.isVisible()) {
173
                    addGvSIGLayer(layer);
174
                }
175
            }
176
        });
177

    
178
        getWwd().redraw();
179
    }
180

    
181
    @SuppressWarnings("rawtypes")
182
    private void addWWLayer(Class layerClazz) throws InstantiationException,
183
        IllegalAccessException, IllegalArgumentException,
184
        InvocationTargetException {
185
        LayerList layerList = getWwd().getModel().getLayers();
186

    
187
        if (isAlreadyAdded(layerList, layerClazz)) {
188
            return;
189
        }
190

    
191
        Constructor[] constructors = layerClazz.getConstructors();
192
        for (int i = 0; i < constructors.length; i++) {
193
            if (constructors[i].getParameterTypes().length == 0) {
194
                layerList.add((Layer) constructors[i].newInstance());
195
            }
196
        }
197
    }
198

    
199
    private void addNavigation() {
200

    
201
        ViewControlsLayer controlsLayer = new ViewControlsLayer();
202

    
203
        Model model = getWwd().getModel();
204
        model.getLayers().add(controlsLayer);
205

    
206
        getWwd().addSelectListener(
207
            new ViewControlsSelectListener(wwd, controlsLayer));
208
    }
209

    
210
    public JComponent asJComponent() {
211
        return this;
212
    }
213

    
214
    public void dispose() {
215

    
216
        Thread disposeThread = new Thread(new Runnable() {
217

    
218
            public void run() {
219
                Notification beforeDisposeNotification =
220
                    new BaseNotification(
221
                        MapControl3D.BEFORE_DISPOSE_MAPCONTEX3D_NOTIFICATION,
222
                        null);
223

    
224
                observableHelper.notifyObservers(DefaultMapControl3D.this,
225
                    beforeDisposeNotification);
226

    
227
                while (WorldWind.getRetrievalService().hasActiveTasks()) {
228
                    try {
229
                        Thread.sleep(100);
230
                    } catch (InterruptedException e) {
231
                        LOG.warn("This thread has been interrupted, dispose action can not be performed");
232
                        return;
233
                    }
234
                }
235

    
236
                disposeWwd();
237

    
238
                Notification afterDisposeNotification =
239
                    new BaseNotification(
240
                        MapControl3D.AFTER_DISPOSE_MAPCONTEX3D_NOTIFICATION,
241
                        null);
242

    
243
                observableHelper.notifyObservers(DefaultMapControl3D.this,
244
                    afterDisposeNotification);
245
            }
246
        }, "Dispose World Wind thread");
247

    
248
        disposeThread.start();
249
    }
250

    
251
    public Cancellable getCancellable() {
252
        if (this.cancellable == null) {
253
            this.cancellable = new Cancellable() {
254

    
255
                private boolean cancel = false;
256

    
257
                public void setCanceled(boolean canceled) {
258
                    this.cancel = canceled;
259
                }
260

    
261
                public boolean isCanceled() {
262
                    return cancel;
263
                }
264
            };
265
        }
266

    
267
        return this.cancellable;
268
    }
269

    
270
    public MapContext getMapContext() {
271
        return this.mapContext;
272
    }
273

    
274
    private StatusBar getStatusBar() {
275
        if (statusBar == null) {
276
            statusBar = new StatusBar();
277
            this.add(statusBar, BorderLayout.PAGE_END);
278
            statusBar.setEventSource(wwd);
279
        }
280
        return statusBar;
281
    }
282

    
283
    public TYPE getType() {
284
        return this.type;
285
    }
286

    
287
    public double getVerticalExaggeration() {
288
        return getWwd().getSceneController().getVerticalExaggeration();
289
    }
290

    
291
    protected WorldWindowGLJPanel getWwd() {
292
        if (this.wwd == null) {
293
            intializeWWPanel();
294
        }
295
        return this.wwd;
296
    }
297

    
298
    private void disposeWwd() {
299
        if (getWwd() != null) {
300
            this.wwd = null;
301
        }
302
    }
303

    
304
    public void hideAtmosphere() {
305
        hideLayer(SkyGradientLayer.class);
306
    }
307

    
308
    @SuppressWarnings("rawtypes")
309
    private void hideLayer(Class layerClazz) {
310
        LayerList layers = getWwd().getModel().getLayers();
311
        List<Layer> layersByClass = layers.getLayersByClass(layerClazz);
312
        layers.removeAll(layersByClass);
313
    }
314

    
315
    public void hideMiniMap() {
316
        hideLayer(WorldMapLayer.class);
317
    }
318

    
319
    public void hideNorthIndicator() {
320
        hideLayer(CompassLayer.class);
321
    }
322

    
323
    public void hideScale() {
324
        hideLayer(ScalebarLayer.class);
325
    }
326

    
327
    public void hideStarBackground() {
328
        hideLayer(StarsLayer.class);
329
    }
330

    
331
    private void intializeWWPanel() {
332
        wwd = new WorldWindowGLJPanel();
333
        wwd.setPreferredSize(new Dimension(800, 600));
334

    
335
        // Create the default model as described in the current worldwind
336
        // properties.
337
        Model m =
338
            (Model) WorldWind
339
                .createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
340
        getWwd().setModel(m);
341

    
342
        // Add view control layer
343
        addNavigation();
344
    }
345

    
346
    private boolean isAlreadyAdded(LayerList layerList,
347
        @SuppressWarnings("rawtypes") Class clazz) {
348

    
349
        List<Layer> layersByClass = layerList.getLayersByClass(clazz);
350

    
351
        return layersByClass.size() > 0;
352
    }
353

    
354
    public void reloadLayers() {
355
        // TODO
356
        throw new UnsupportedOperationException();
357
    }
358

    
359
    private void removeAllLayers() {
360
        getWwd().getModel().getLayers().removeAll();
361
    }
362

    
363
    private void setFlatPanelConfiguration() {
364
        Configuration.setValue(AVKey.GLOBE_CLASS_NAME,
365
            EarthFlat.class.getName());
366
        Configuration.setValue(AVKey.VIEW_CLASS_NAME,
367
            FlatOrbitView.class.getName());
368
    }
369

    
370
    public void setMapContext(MapContext theMapContext) {
371
        this.mapContext = theMapContext;
372
    }
373

    
374
    private void setSpherePanelConfiguration() {
375
        Configuration.setValue(AVKey.GLOBE_CLASS_NAME, Earth.class.getName());
376
        Configuration.setValue(AVKey.VIEW_CLASS_NAME,
377
            BasicOrbitView.class.getName());
378
    }
379

    
380
    public void setVerticalExaggeration(double verticalExaggeration) {
381
        getWwd().getSceneController().setVerticalExaggeration(
382
            verticalExaggeration);
383
    }
384

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

    
403
    public void showMiniMap() {
404
        try {
405
            addWWLayer(WorldMapLayer.class);
406
        } catch (Exception e) {
407
            LOG.warn("Can't add {} to {}",
408
                new Object[] { WorldMapLayer.class.getCanonicalName(),
409
                    getWwd().getModel().toString() }, e);
410
        }
411
    }
412

    
413
    public void showNortIndicator() {
414
        try {
415
            addWWLayer(CompassLayer.class);
416
        } catch (Exception e) {
417
            LOG.warn("Can't add {} to {}",
418
                new Object[] { CompassLayer.class.getCanonicalName(),
419
                    getWwd().getModel().toString() }, e);
420
        }
421
    }
422

    
423
    public void showScale() {
424
        try {
425
            addWWLayer(ScalebarLayer.class);
426
        } catch (Exception e) {
427
            LOG.warn("Can't add {} to {}",
428
                new Object[] { ScalebarLayer.class.getCanonicalName(),
429
                    getWwd().getModel().toString() }, e);
430
        }
431
    }
432

    
433
    public void showStarBackgroundLayer() {
434
        try {
435
            addWWLayer(StarsLayer.class);
436
        } catch (Exception e) {
437
            LOG.warn("Can't add {} to {}",
438
                new Object[] { StarsLayer.class.getCanonicalName(),
439
                    getWwd().getModel().toString() }, e);
440
        }
441
    }
442

    
443
    public void synchronizeLayers() {
444
        // TODO
445
        throw new UnsupportedOperationException();
446
    }
447

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

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

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

    
464
    }
465

    
466
    public void deleteObservers() {
467
        if (observableHelper != null) {
468
            observableHelper.deleteObservers();
469
        }
470
    }
471
}