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 |
}; |