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

History | View | Annotate | Download (15.4 KB)

1 443 llmarques
/**
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 446 llmarques
import org.gvsig.fmap.dal.exception.DataException;
59 443 llmarques
import org.gvsig.fmap.mapcontext.MapContext;
60 446 llmarques
import org.gvsig.fmap.mapcontext.layers.FLayer;
61
import org.gvsig.fmap.mapcontext.layers.operations.LayersVisitor;
62
import org.gvsig.tools.exception.BaseException;
63 471 llmarques
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 446 llmarques
import org.gvsig.tools.visitor.VisitCanceledException;
69 443 llmarques
import org.gvsig.view3d.swing.api.MapControl3D;
70
import org.gvsig.view3d.swing.api.View3DSwingManager.TYPE;
71 446 llmarques
import org.gvsig.view3d.swing.impl.data.DefaultLayerConverter;
72
import org.gvsig.view3d.swing.impl.data.LayerConverter;
73 460 llmarques
import org.slf4j.Logger;
74
import org.slf4j.LoggerFactory;
75 443 llmarques
76
/**
77 474 llmarques
 * Default implementation of {@link MapControl3D}.
78
 *
79 446 llmarques
 * @author <a href="mailto:lmarques@disid.com">Lluis Marques</a>
80 443 llmarques
 */
81 471 llmarques
@SuppressWarnings("deprecation")
82 460 llmarques
public class DefaultMapControl3D extends JPanel implements MapControl3D {
83 443 llmarques
84
    private static final long serialVersionUID = 2024899922367896097L;
85
86 456 llmarques
    private static final Logger LOG = LoggerFactory
87 443 llmarques
        .getLogger(DefaultMapControl3D.class);
88 474 llmarques
89 471 llmarques
    private ObservableHelper observableHelper;
90
91 452 llmarques
    /**
92
     * Name of gvSIG MapContext property
93
     */
94 471 llmarques
    public static final String GVSIG_MAPCONTROL3D =
95
        "org.gvsig.view3d.swing.api.MapControl3D";
96
97 457 llmarques
    /**
98
     * Name of gvSIG Layer property
99
     */
100 460 llmarques
    public static final String GVSIG_LAYER =
101
        "org.gvsig.fmap.mapcontext.layers.FLayer";
102 443 llmarques
103
    private MapContext mapContext;
104 446 llmarques
105 443 llmarques
    private WorldWindowGLJPanel wwd;
106
107 446 llmarques
    private StatusBar statusBar;
108
109 443 llmarques
    private TYPE type;
110 474 llmarques
111 471 llmarques
    private Cancellable cancellable;
112 443 llmarques
113 474 llmarques
    /**
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 443 llmarques
    public DefaultMapControl3D(MapContext theMapContext, TYPE type) {
124 446 llmarques
125 443 llmarques
        super(new BorderLayout());
126 446 llmarques
127 443 llmarques
        this.mapContext = theMapContext;
128
        this.type = type;
129 471 llmarques
        this.cancellable = getCancellable();
130
        this.observableHelper = new ObservableHelper();
131 443 llmarques
132
        // Set mode before instantiation
133
        if (type == TYPE.SPHERE) {
134
            setSpherePanelConfiguration();
135 445 llmarques
        } else if (type == TYPE.FLAT) {
136 443 llmarques
            setFlatPanelConfiguration();
137
        }
138
139 446 llmarques
        super.add(getWwd(), BorderLayout.CENTER);
140 443 llmarques
141 446 llmarques
        super.add(getStatusBar(), BorderLayout.SOUTH);
142 443 llmarques
143 446 llmarques
        try {
144
            addLayers();
145
        } catch (BaseException e) {
146 456 llmarques
            LOG.info("Can't add MapControl layers", e);
147 446 llmarques
        }
148 443 llmarques
149
    }
150
151 446 llmarques
    private void addGvSIGLayer(FLayer layer) throws DataException {
152
153
        LayerConverter converter = new DefaultLayerConverter();
154 471 llmarques
155 446 llmarques
        // TODO Check load mode to create WW Layer
156 471 llmarques
        Layer rasterTiledLayer = converter.convertToLayer(this, layer);
157 446 llmarques
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 443 llmarques
    @SuppressWarnings("rawtypes")
182 446 llmarques
    private void addWWLayer(Class layerClazz) throws InstantiationException,
183 443 llmarques
        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 446 llmarques
199 443 llmarques
    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 460 llmarques
214 459 llmarques
    public void dispose() {
215 474 llmarques
216 473 llmarques
        Thread disposeThread = new Thread(new Runnable() {
217 474 llmarques
218 473 llmarques
            public void run() {
219
                Notification beforeDisposeNotification =
220
                    new BaseNotification(
221 474 llmarques
                        MapControl3D.BEFORE_DISPOSE_MAPCONTEX3D_NOTIFICATION,
222
                        null);
223 460 llmarques
224 473 llmarques
                observableHelper.notifyObservers(DefaultMapControl3D.this,
225
                    beforeDisposeNotification);
226 460 llmarques
227 474 llmarques
                while (WorldWind.getRetrievalService().hasActiveTasks()) {
228 473 llmarques
                    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 474 llmarques
                        MapControl3D.AFTER_DISPOSE_MAPCONTEX3D_NOTIFICATION,
241
                        null);
242 473 llmarques
243 474 llmarques
                observableHelper.notifyObservers(DefaultMapControl3D.this,
244
                    afterDisposeNotification);
245 473 llmarques
            }
246
        }, "Dispose World Wind thread");
247 474 llmarques
248 473 llmarques
        disposeThread.start();
249 459 llmarques
    }
250 474 llmarques
251
    public Cancellable getCancellable() {
252
        if (this.cancellable == null) {
253 471 llmarques
            this.cancellable = new Cancellable() {
254 474 llmarques
255 471 llmarques
                private boolean cancel = false;
256 474 llmarques
257 471 llmarques
                public void setCanceled(boolean canceled) {
258
                    this.cancel = canceled;
259
                }
260 474 llmarques
261 471 llmarques
                public boolean isCanceled() {
262
                    return cancel;
263
                }
264
            };
265
        }
266 474 llmarques
267 471 llmarques
        return this.cancellable;
268
    }
269 443 llmarques
270
    public MapContext getMapContext() {
271
        return this.mapContext;
272
    }
273
274
    private StatusBar getStatusBar() {
275 446 llmarques
        if (statusBar == null) {
276
            statusBar = new StatusBar();
277
            this.add(statusBar, BorderLayout.PAGE_END);
278
            statusBar.setEventSource(wwd);
279
        }
280 443 llmarques
        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 474 llmarques
298
    private void disposeWwd() {
299 473 llmarques
        if (getWwd() != null) {
300
            this.wwd = null;
301
        }
302
    }
303 443 llmarques
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 446 llmarques
                addWWLayer(SkyGradientLayer.class);
391 443 llmarques
            } else if (globe instanceof EarthFlat) {
392
                getWwd().getModel().getLayers().add(new SkyColorLayer());
393 446 llmarques
                addWWLayer(SkyColorLayer.class);
394 443 llmarques
            }
395
        } catch (Exception e) {
396 460 llmarques
            LOG.warn("Can't add {} or {} to {}",
397
                new Object[] { SkyGradientLayer.class.getCanonicalName(),
398
                    SkyColorLayer.class.getCanonicalName(),
399
                    getWwd().getModel().toString() }, e);
400 443 llmarques
        }
401
    }
402
403
    public void showMiniMap() {
404
        try {
405 446 llmarques
            addWWLayer(WorldMapLayer.class);
406 443 llmarques
        } catch (Exception e) {
407 460 llmarques
            LOG.warn("Can't add {} to {}",
408
                new Object[] { WorldMapLayer.class.getCanonicalName(),
409
                    getWwd().getModel().toString() }, e);
410 443 llmarques
        }
411
    }
412
413
    public void showNortIndicator() {
414
        try {
415 446 llmarques
            addWWLayer(CompassLayer.class);
416 443 llmarques
        } catch (Exception e) {
417 460 llmarques
            LOG.warn("Can't add {} to {}",
418
                new Object[] { CompassLayer.class.getCanonicalName(),
419
                    getWwd().getModel().toString() }, e);
420 443 llmarques
        }
421
    }
422
423
    public void showScale() {
424
        try {
425 446 llmarques
            addWWLayer(ScalebarLayer.class);
426 443 llmarques
        } catch (Exception e) {
427 460 llmarques
            LOG.warn("Can't add {} to {}",
428
                new Object[] { ScalebarLayer.class.getCanonicalName(),
429
                    getWwd().getModel().toString() }, e);
430 443 llmarques
        }
431
    }
432
433
    public void showStarBackgroundLayer() {
434
        try {
435 446 llmarques
            addWWLayer(StarsLayer.class);
436 443 llmarques
        } catch (Exception e) {
437 460 llmarques
            LOG.warn("Can't add {} to {}",
438
                new Object[] { StarsLayer.class.getCanonicalName(),
439
                    getWwd().getModel().toString() }, e);
440 443 llmarques
        }
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 474 llmarques
453 471 llmarques
    public void addObserver(Observer o) {
454 474 llmarques
        if (observableHelper != null) {
455 471 llmarques
            observableHelper.addObserver(o);
456
        }
457
    }
458
459
    public void deleteObserver(Observer o) {
460 474 llmarques
        if (observableHelper != null) {
461 471 llmarques
            observableHelper.deleteObserver(o);
462
        }
463 474 llmarques
464 471 llmarques
    }
465
466
    public void deleteObservers() {
467 474 llmarques
        if (observableHelper != null) {
468 471 llmarques
            observableHelper.deleteObservers();
469
        }
470
    }
471 482 llmarques
472
    public boolean isAtmosphereVisible() {
473
        LayerList layerList = getWwd().getModel().getLayers();
474
        if (isAlreadyAdded(layerList, SkyGradientLayer.class)
475
            || isAlreadyAdded(layerList, SkyColorLayer.class)) {
476
            return true;
477
        }
478
        return false;
479
    }
480
481
    public boolean isMinimapVisible() {
482
        LayerList layerList = getWwd().getModel().getLayers();
483
        if (isAlreadyAdded(layerList, WorldMapLayer.class)) {
484
            return true;
485
        }
486
        return false;
487
    }
488
489
    public boolean isNorthIndicatorVisible() {
490
        LayerList layerList = getWwd().getModel().getLayers();
491
        if (isAlreadyAdded(layerList, CompassLayer.class)) {
492
            return true;
493
        }
494
        return false;
495
    }
496
497
    public boolean isStartBackgroundVisible(){
498
        LayerList layerList = getWwd().getModel().getLayers();
499
        if (isAlreadyAdded(layerList, StarsLayer.class)) {
500
            return true;
501
        }
502
        return false;
503
    }
504
505
    public boolean isScaleVisible() {
506
        LayerList layerList = getWwd().getModel().getLayers();
507
        if (isAlreadyAdded(layerList, ScalebarLayer.class)) {
508
            return true;
509
        }
510
        return false;
511
    }
512 443 llmarques
}