我使用自己的交互方法,因为我将NASA WorldWind嵌入到JavaFX中,而不是Swing中。视图在FXML中定义如下:
<?xml version="1.0" encoding="UTF-8"?>
...
<Pane xmlns:fx="http://javafx.com/fxml" fx:id="_mainPane"
fx:controller="view.MainCtrl" prefWidth="1600" prefHeight="900">
<stylesheets><URL value="@NavDb.css" /></stylesheets>
<BorderPane><SwingNode fx:id="_worldWindFxContainer" /></BorderPane>
...
控制器属性:
@FXML private SwingNode _worldWindFxContainer;
private final WorldWindowGLJPanel _worldWind = new WorldWindowGLJPanel();
private final RenderableLayer _routeLayer = new RenderableLayer();
private final RenderableLayer _alertLayer = new RenderableLayer();
private final Preferences _preferences = new Preferences();
WW初始化代码:
private void initWorldWind() {
WorldWind.setOfflineMode( _preferences.get( "WorldWind/offline", false ));
final OrbitView orbitVw = new FlatOrbitView();
final EarthFlat globe = new EarthFlat();
final Model model = new BasicModel();
globe.setProjection( FlatGlobe.PROJECTION_MERCATOR );
model.setGlobe( globe );
orbitVw.getOrbitViewLimits().setZoomLimits( 1.2E+04, 2.2E+07 );
_worldWind.setModelAndView( model, orbitVw );
_worldWind.getSceneController().setDeepPickEnabled( true );
_routeLayer.setName( "Route-Layer" );
_routeLayer.setPickEnabled( false );
_alertLayer.setName( "Alert-Layer" );
_alertLayer.setPickEnabled( true );
_alertLayer.setEnabled( true );
final LayerList layers = model.getLayers();
layers.add( _routeLayer );
layers.add( _alertLayer );
layers.removeIf( l -> l instanceof CompassLayer );
layers.removeIf( l -> l instanceof WorldMapLayer );
for(int i = 0; i < layers.size(); i++) {
final Layer l = layers.get( i );
if( l instanceof SkyGradientLayer ) {
layers.set( i, new SkyColorLayer());
}
}
final double lat = _preferences.get( "Startup/initial-location-lat", 0.0 );
final double lon = _preferences.get( "Startup/initial-location-lon", 0.0 );
final double zoomFactor = _preferences.get( "Startup/initial-zoom", 1.0 );
orbitVw.setEyePosition( Position.fromDegrees( lat, lon ));
orbitVw.setZoom( zoomFactor );
Platform.runLater(() -> {
final Interactions handler = new Interactions( _worldWind );
handler.setPicker( this );
_worldWindFxContainer.addEventHandler( InputEvent .ANY, handler );
_worldWindFxContainer.addEventFilter ( MouseEvent .ANY, event -> {
handler.handle( event );
event.consume();
});
_worldWindFxContainer.addEventFilter ( ScrollEvent.ANY, event -> {
handler.handle( event );
event.consume();
});
});
_worldWind.redrawNow();
}
来自JavaFx初始化代码:
SwingUtilities.invokeLater( this::initWorldWind );
交互类别:
public final class Interactions implements EventHandler<InputEvent> {
private final WorldWindowGLJPanel _wwPanel;
private final SceneController _sceneController;
private final OrbitView _view;
public Interactions( WorldWindowGLJPanel wwPanel ) {
_wwPanel = wwPanel;
_sceneController = _wwPanel.getSceneController();
_view = (OrbitView)_sceneController.getView();
}
private Position getPositionFromScreenPoint( double x, double y ) {
final View vw = _sceneController.getView();
final Line ray = vw.computeRayFromScreenPoint( x, y );
if( ray != null ) {
final Globe globe = _sceneController.getModel().getGlobe();
final Vec4 origin = ray.getOrigin();
final Vec4 direction = ray.getDirection().normalize3();
final Position pos =
RayCastingSupport.intersectRayWithTerrain( globe, origin, direction );
return pos;
}
return null;
}
Interactions.getPositionFromScreenPoint
是从FX鼠标处理程序调用的。
问题是:在我从世界的球形表示切换到平面表示后,RayCastingSupport.intersectRayWithTerrain()
总是返回null。
我还没有找到真正的答案,但我写了一个简化的方法来处理鼠标点击以移动平面图:
private Position getPositionFromScreenPoint( double x, double y ) {
final View vw = _sceneController.getView();
final Line ray = vw.computeRayFromScreenPoint( x, y );
final Vec4 origin = ray.getOrigin();
final Vec4 direction = ray.getDirection().normalize3();
final Globe globe = _sceneController.getModel().getGlobe();
final double gme = globe.getMaxElevation();
final Intersection[] inters = globe.intersect( new Line( origin, direction ), gme );
if( inters != null ) {
final Vec4 pt = inters[0].getIntersectionPoint();
final Position pos = globe.computePositionFromPoint( pt );
return pos;
}
return null;
}
我不明白为什么我必须为inters
检查null,但有时,它是null。。。