📄 viewinputhandler.java
字号:
{ Point point = constrainToSourceBounds(this.getMousePoint(), this.wwd); Point lastPoint = constrainToSourceBounds(this.getLastMousePoint(), this.wwd); if (point == null || lastPoint == null) { return; } Point movement = subtract(point, lastPoint); int headingInput = movement.x; int pitchInput = movement.y; // Switch the direction of heading change depending on whether the cursor is above or below // the center of the screen. if (this.wwd instanceof Component) { if (this.getMousePoint().y < ((Component) this.wwd).getHeight() / 2) { headingInput = -headingInput; } } ViewInputAttributes.DeviceAttributes deviceAttributes = this.attributes.getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE); ViewInputAttributes.ActionAttributes actionAttributes = this.attributes.getActionAttributes(ViewInputAttributes.DEVICE_MOUSE, ViewInputAttributes.VIEW_ROTATE); Angle headingChange = Angle.fromDegrees( this.rawInputToChangeInValue(headingInput, deviceAttributes, actionAttributes, SCALE_FUNC_ZOOM)); Angle pitchChange = Angle.fromDegrees( this.rawInputToChangeInValue(pitchInput, deviceAttributes, actionAttributes, SCALE_FUNC_ZOOM)); this.onRotateView(headingChange, pitchChange, actionAttributes); } @SuppressWarnings({"UnusedDeclaration"}) protected void handleMouseZoom(MouseEvent e) { Point point = constrainToSourceBounds(this.getMousePoint(), this.wwd); Point lastPoint = constrainToSourceBounds(this.getLastMousePoint(), this.wwd); if (point == null || lastPoint == null) { return; } Point movement = subtract(point, lastPoint); int zoomInput = movement.y; ViewInputAttributes.DeviceAttributes deviceAttributes = this.attributes.getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE); ViewInputAttributes.ActionAttributes actionAttributes = this.attributes.getActionAttributes(ViewInputAttributes.DEVICE_MOUSE, ViewInputAttributes.VIEW_ZOOM); double zoomChange = this.rawInputToChangeInValue(zoomInput, deviceAttributes, actionAttributes, SCALE_FUNC_ZOOM); this.onZoomView(zoomChange, actionAttributes); } protected Vec4 computeSelectedPointAt(Point point) { if (this.getSelectedPosition() == null) { return null; } View view = this.getView(); if (view == null) { return null; } // Reject a selected position if its elevation is above the eye elevation. When that happens, the user is // essentially dragging along the inside of a sphere, and the effects of dragging are reversed. To the user // this behavior appears unpredictable. double elevation = this.getSelectedPosition().getElevation(); if (view.getEyePosition().getElevation() <= elevation) { return null; } // Intersect with a somewhat larger or smaller Globe which will pass through the selected point, but has the // same proportions as the actual Globe. This will simulate dragging the selected position more accurately. Line ray = view.computeRayFromScreenPoint(point.getX(), point.getY()); Intersection[] intersections = this.wwd.getModel().getGlobe().intersect(ray, elevation); if (intersections == null || intersections.length == 0) { return null; } return this.nearestIntersectionPoint(ray, intersections); } protected Vec4 nearestIntersectionPoint(Line line, Intersection[] intersections) { Vec4 intersectionPoint = null; // Find the nearest intersection that's in front of the ray origin. double nearestDistance = Double.MAX_VALUE; for (Intersection intersection : intersections) { // Ignore any intersections behind the line origin. if (!this.isPointBehindLineOrigin(line, intersection.getIntersectionPoint())) { double d = intersection.getIntersectionPoint().distanceTo3(line.getOrigin()); if (d < nearestDistance) { intersectionPoint = intersection.getIntersectionPoint(); nearestDistance = d; } } } return intersectionPoint; } public boolean isPointBehindLineOrigin(Line line, Vec4 point) { double dot = point.subtract3(line.getOrigin()).dot3(line.getDirection()); return dot < 0.0; } protected LatLon getChangeInLocation(Point point1, Point point2, Vec4 vec1, Vec4 vec2) { // Modify the distance we'll actually travel based on the slope of world distance travelled to screen // distance travelled . A large slope means the user made a small change in screen space which resulted // in a large change in world space. We want to reduce the impact of that change to something reasonable. double dragSlope = this.computeDragSlope(point1, point2, vec1, vec2); double dragSlopeFactor = this.getDragSlopeFactor(); double scale = 1.0 / (1.0 + dragSlopeFactor * dragSlope * dragSlope); Position pos1 = this.wwd.getModel().getGlobe().computePositionFromPoint(vec1); Position pos2 = this.wwd.getModel().getGlobe().computePositionFromPoint(vec2); Angle azimuth = LatLon.greatCircleAzimuth(pos1, pos2); Angle distance = LatLon.greatCircleDistance(pos1, pos2); Angle adjustedDistance = Angle.fromDegrees(distance.getDegrees() * scale); LatLon adjustedPos2 = LatLon.greatCircleEndPosition(pos1, azimuth, adjustedDistance); // Return the distance to travel in angular degrees. return pos1.subtract(adjustedPos2); } protected double computeDragSlope(Point point1, Point point2, Vec4 vec1, Vec4 vec2) { View view = this.getView(); if (view == null) { return 0.0; } // Compute the screen space distance between point1 and point2. double dx = point2.getX() - point1.getX(); double dy = point2.getY() - point1.getY(); double pixelDistance = Math.sqrt(dx * dx + dy * dy); // Determine the distance from the eye to the point on the forward vector closest to vec1 and vec2 double d = view.getEyePoint().distanceTo3(vec1); // Compute the size of a screen pixel at the nearest of the two distances. double pixelSize = view.computePixelSizeAtDistance(d); // Return the ratio of world distance to screen distance. double slope = vec1.distanceTo3(vec2) / (pixelDistance * pixelSize); if (slope < 1.0) slope = 1.0; return slope - 1.0; } protected static Point constrainToSourceBounds(Point point, Object source) { if (point == null) return null; if (!(source instanceof Component)) return point; Component c = (Component) source; int x = (int) point.getX(); if (x < 0) x = 0; if (x > c.getWidth()) x = c.getWidth(); int y = (int) point.getY(); if (y < 0) y = 0; if (y > c.getHeight()) y = c.getHeight(); return new Point(x, y); } protected static Point subtract(Point a, Point b) { if (a == null || b == null) return null; return new Point((int)(a.getX() - b.getX()), (int)(a.getY() - b.getY())); } //**************************************************************// //******************** Mouse Wheel Events ********************// //**************************************************************// public void mouseWheelMoved(MouseWheelEvent e) { if (this.wwd == null) // include this test to ensure any derived implementation performs it { return; } if (e == null) // include this test to ensure any derived implementation performs it { return; } this.handleMouseWheelMoved(e); } protected void handleMouseWheelMoved(MouseWheelEvent e) { this.handleMouseWheelZoom(e); } protected void handleMouseWheelZoom(MouseWheelEvent e) { double zoomInput = e.getWheelRotation(); ViewInputAttributes.DeviceAttributes deviceAttributes = this.attributes.getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE_WHEEL); ViewInputAttributes.ActionAttributes actionAttributes = this.attributes.getActionAttributes(ViewInputAttributes.DEVICE_MOUSE_WHEEL, ViewInputAttributes.VIEW_ZOOM); double zoomChange = this.rawInputToChangeInValue(zoomInput, deviceAttributes, actionAttributes, SCALE_FUNC_ZOOM); this.onZoomView(zoomChange, actionAttributes); } //**************************************************************// //******************** Focus Events **************************// //**************************************************************// public void focusGained(FocusEvent e) { if (this.wwd == null) // include this test to ensure any derived implementation performs it { return; } if (e == null) // include this test to ensure any derived implementation performs it { return; } this.setWorldWindowFocusOwner(true); } public void focusLost(FocusEvent e) { if (this.wwd == null) // include this test to ensure any derived implementation performs it { return; } if (e == null) // include this test to ensure any derived implementation performs it { return; } this.setWorldWindowFocusOwner(false); if (this.isStopOnFocusLost()) this.onStopView(); this.keyEventState.clearKeyState(); } //**************************************************************// //******************** Rendering Events **********************// //**************************************************************// public void stageChanged(RenderingEvent e) { if (this.wwd == null) // include this test to ensure any derived implementation performs it { return; } if (e == null) // include this test to ensure any derived implementation performs it { return; } //noinspection StringEquality if (RenderingEvent.BEFORE_RENDERING == e.getStage()) { this.handleBeforeRendering(e); } } @SuppressWarnings({"UnusedDeclaration"}) protected void handleBeforeRendering(RenderingEvent e) { this.handlePerFrameInput(); View view = this.getView(); if (view == null) { return; } if (view instanceof OrbitView) { // Cancel any of our view changes if someone else has set a view state iterator. if (view.hasStateIterator()) this.orbitViewInputSupport.clearTargets(); if (this.orbitViewInputSupport.hasTargets()) this.orbitViewInputSupport.moveViewTowardTargets((OrbitView) view); } } //**************************************************************// //******************** Rendering Events **********************// //**************************************************************// protected void handlePerFrameInput() { // Process per-frame input only when the World Window is the focus owner. if (!this.isWorldWindowFocusOwner()) { return; } // Throttle the frequency at which we process per-frame input, which is usually invoked each frame. This helps // balance the input response of high and low framerate applications. long time = System.currentTimeMillis(); if (time - this.lastPerFrameInputTime > DEFAULT_PER_FRAME_INPUT_DELAY) { this.handlePerFrameKeyState(this.keyEventState, GENERATE_EVENTS); this.lastPerFrameInputTime = time; } else { // Determine whether or not the current key state would have generated a view change event. If so, issue // a repaint event to give the per-frame input a chance to run again. if (this.handlePerFrameKeyState(this.keyEventState, QUERY_EVENTS)) { View view = this.getView(); if (view != null) { view.firePropertyChange(AVKey.VIEW, null, view); } } } } // Interpret the current key state according to the specified target. If the target is KEY_POLL_GENERATE_EVENTS, // then the the key state will generate any appropriate view change events. If the target is KEY_POLL_QUERY_EVENTS, // then the key state will not generate events, and this will return whether or not any view change events would // have been generated. protected boolean handlePerFrameKeyState(KeyEventState keys, String target) { boolean isKeyEventTrigger; // If the rotate modifier is down, then invoke rotate commands. if ((keys.getModifiersEx() & KeyEvent.SHIFT_DOWN_MASK) != 0) { isKeyEventTrigger = this.handleKeyRotate(keys, target); } // If the zoom modifier is down, then invoke zoom commands. else if ((keys.getModifiersEx() & (KeyEvent.CTRL_DOWN_MASK | KeyEvent.META_DOWN_MASK)) != 0) { isKeyEventTrigger = this.handleKeyZoom(keys, target); } else { // Otherwise, invoke commands in priority order: zoom, rotate, then pan. If any succeeds the remaining // commands will not be invoked. if (!(isKeyEventTrigger = this.handleKeyRotate(keys, target))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -