我使用自己的交互方法,因为我将 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 。