private void makeRadialWallTerrainConformant( DrawContext dc, int pillars, int stacks, float[] verts, double[] altitudes, boolean[] terrainConformant, Vec4 referenceCenter) { Globe globe = dc.getGlobe(); Matrix transform = this.computeTransform(dc.getGlobe(), dc.getVerticalExaggeration()); for (int p = 0; p <= pillars; p++) { int index = p; index = 3 * index; Vec4 vec = new Vec4(verts[index], verts[index + 1], verts[index + 2]); vec = vec.transformBy4(transform); Position pos = globe.computePositionFromPoint(vec); for (int s = 0; s <= stacks; s++) { double elevation = altitudes[s]; if (terrainConformant[s]) elevation += this.computeElevationAt(dc, pos.getLatitude(), pos.getLongitude()); vec = globe.computePointFromPosition(pos.getLatitude(), pos.getLongitude(), elevation); index = p + s * (pillars + 1); index = 3 * index; verts[index] = (float) (vec.x - referenceCenter.x); verts[index + 1] = (float) (vec.y - referenceCenter.y); verts[index + 2] = (float) (vec.z - referenceCenter.z); } } }
/** * Performs one line of sight calculation between the reference position and a specified grid * position. * * @param gridPosition the grid position. * @throws InterruptedException if the operation is interrupted. */ protected void performIntersection(Position gridPosition) throws InterruptedException { // Intersect the line between this grid point and the selected position. Intersection[] intersections = this.terrain.intersect(this.referencePosition, gridPosition); if (intersections == null || intersections.length == 0) { // No intersection, so the line goes from the center to the grid point. this.sightLines.add(new Position[] {this.referencePosition, gridPosition}); return; } // Only the first intersection is shown. Vec4 iPoint = intersections[0].getIntersectionPoint(); Vec4 gPoint = terrain.getSurfacePoint( gridPosition.getLatitude(), gridPosition.getLongitude(), gridPosition.getAltitude()); // Check to see whether the intersection is beyond the grid point. if (iPoint.distanceTo3(this.referencePoint) >= gPoint.distanceTo3(this.referencePoint)) { // Intersection is beyond the grid point; the line goes from the center to the grid point. this.addSightLine(this.referencePosition, gridPosition); return; } // Compute the position corresponding to the intersection. Position iPosition = this.terrain.getGlobe().computePositionFromPoint(iPoint); // The sight line goes from the user-selected position to the intersection position. this.addSightLine(this.referencePosition, new Position(iPosition, 0)); // Keep track of the intersection positions. this.addIntersectionPosition(iPosition); this.updateProgress(); }
private void makePartialCylinderTerrainConformant( DrawContext dc, int slices, int stacks, float[] verts, double[] altitudes, boolean[] terrainConformant, Vec4 referenceCenter) { Globe globe = dc.getGlobe(); Matrix transform = this.computeTransform(dc.getGlobe(), dc.getVerticalExaggeration()); for (int i = 0; i <= slices; i++) { int index = i * (stacks + 1); index = 3 * index; Vec4 vec = new Vec4(verts[index], verts[index + 1], verts[index + 2]); vec = vec.transformBy4(transform); Position p = globe.computePositionFromPoint(vec); for (int j = 0; j <= stacks; j++) { double elevation = altitudes[j]; if (terrainConformant[j]) elevation += this.computeElevationAt(dc, p.getLatitude(), p.getLongitude()); vec = globe.computePointFromPosition(p.getLatitude(), p.getLongitude(), elevation); index = j + i * (stacks + 1); index = 3 * index; verts[index] = (float) (vec.x - referenceCenter.x); verts[index + 1] = (float) (vec.y - referenceCenter.y); verts[index + 2] = (float) (vec.z - referenceCenter.z); } } }
/** * Setup the view to a first person mode (zoom = 0) * * @param view the orbit view to set into a first person view. */ protected void setupFirstPersonView(OrbitView view) { if (view.getZoom() == 0) // already in first person mode return; Vec4 eyePoint = view.getEyePoint(); // Center pos at eye pos Position centerPosition = wwd.getModel().getGlobe().computePositionFromPoint(eyePoint); // Compute pitch and heading relative to center position Vec4 normal = wwd.getModel() .getGlobe() .computeSurfaceNormalAtLocation( centerPosition.getLatitude(), centerPosition.getLongitude()); Vec4 north = wwd.getModel() .getGlobe() .computeNorthPointingTangentAtLocation( centerPosition.getLatitude(), centerPosition.getLongitude()); // Pitch view.setPitch(Angle.POS180.subtract(view.getForwardVector().angleBetween3(normal))); // Heading Vec4 perpendicular = view.getForwardVector().perpendicularTo3(normal); Angle heading = perpendicular.angleBetween3(north); double direction = Math.signum(-normal.cross3(north).dot3(perpendicular)); view.setHeading(heading.multiply(direction)); // Zoom view.setZoom(0); // Center pos view.setCenterPosition(centerPosition); }
@Override protected List<Vec4> computeMinimalGeometry(Globe globe, double verticalExaggeration) { double[] angles = this.computeAngles(); // Angles are equal, fall back to building a closed cylinder. if (angles == null) return super.computeMinimalGeometry(globe, verticalExaggeration); double[] radii = this.getRadii(); Matrix transform = this.computeTransform(globe, verticalExaggeration); GeometryBuilder gb = this.getGeometryBuilder(); int count = gb.getPartialDiskVertexCount(MINIMAL_GEOMETRY_SLICES, MINIMAL_GEOMETRY_LOOPS); int numCoords = 3 * count; float[] verts = new float[numCoords]; gb.makePartialDiskVertices( (float) radii[0], (float) radii[1], // Inner radius, outer radius. MINIMAL_GEOMETRY_SLICES, MINIMAL_GEOMETRY_LOOPS, // Slices, loops, (float) angles[0], (float) angles[2], // Start angle, sweep angle. verts); List<LatLon> locations = new ArrayList<LatLon>(); for (int i = 0; i < numCoords; i += 3) { Vec4 v = new Vec4(verts[i], verts[i + 1], verts[i + 2]); v = v.transformBy4(transform); locations.add(globe.computePositionFromPoint(v)); } ArrayList<Vec4> points = new ArrayList<Vec4>(); this.makeExtremePoints(globe, verticalExaggeration, locations, points); return points; }
private void makePartialDiskTerrainConformant( DrawContext dc, int numCoords, float[] verts, double altitude, boolean terrainConformant, Vec4 referenceCenter) { Globe globe = dc.getGlobe(); Matrix transform = this.computeTransform(dc.getGlobe(), dc.getVerticalExaggeration()); for (int i = 0; i < numCoords; i += 3) { Vec4 vec = new Vec4(verts[i], verts[i + 1], verts[i + 2]); vec = vec.transformBy4(transform); Position p = globe.computePositionFromPoint(vec); double elevation = altitude; if (terrainConformant) elevation += this.computeElevationAt(dc, p.getLatitude(), p.getLongitude()); vec = globe.computePointFromPosition(p.getLatitude(), p.getLongitude(), elevation); verts[i] = (float) (vec.x - referenceCenter.x); verts[i + 1] = (float) (vec.y - referenceCenter.y); verts[i + 2] = (float) (vec.z - referenceCenter.z); } }
protected double computeLength(Globe globe, boolean followTerrain) { if (this.positions == null || this.positions.size() < 2) return -1; if (this.subdividedPositions == null) { // Subdivide path so as to have at least segments smaller then maxSegmentLenth. If follow // terrain, // subdivide so as to have at least lengthTerrainSamplingSteps segments, but no segments // shorter then // DEFAULT_MIN_SEGMENT_LENGTH either. double maxLength = this.maxSegmentLength; if (followTerrain) { // Recurse to compute overall path length not following terrain double pathLength = computeLength(globe, !followTerrain); // Determine segment length to have enough sampling points maxLength = pathLength / this.lengthTerrainSamplingSteps; maxLength = Math.min(Math.max(maxLength, DEFAULT_MIN_SEGMENT_LENGTH), getMaxSegmentLength()); } this.subdividedPositions = subdividePositions(globe, this.positions, maxLength, followTerrain, this.pathType); } // Sum each segment length double length = 0; Vec4 p1 = globe.computePointFromPosition(this.subdividedPositions.get(0)); for (int i = 1; i < subdividedPositions.size(); i++) { Vec4 p2 = globe.computePointFromPosition(this.subdividedPositions.get(i)); length += p1.distanceTo3(p2); p1 = p2; } return length; }
protected void assembleHeightControlPoints() { if (this.controlPoints.size() < 2) return; // Add one control point for the height between the first and second vertices. // TODO: ensure that this control point is visible Position firstVertex = this.controlPoints.get(0).getPosition(); Position secondVertex = this.controlPoints.get(1).getPosition(); Globe globe = this.wwd.getModel().getGlobe(); // Get cartesian points for the vertices Vec4 firstPoint = globe.computePointFromPosition(firstVertex); Vec4 secondPoint = globe.computePointFromPosition(secondVertex); // Find the midpoint of the line segment that connects the vertices Vec4 halfwayPoint = firstPoint.add3(secondPoint).divide3(2.0); Position halfwayPosition = globe.computePositionFromPoint(halfwayPoint); this.controlPoints.add( new ControlPointMarker( CHANGE_HEIGHT_ACTION, halfwayPosition, halfwayPoint, this.heightControlAttributes, this.controlPoints.size())); }
protected boolean areShapesIntersecting(Airspace a1, Airspace a2) { if ((a1 instanceof SphereAirspace) && (a2 instanceof SphereAirspace)) { SphereAirspace s1 = (SphereAirspace) a1; SphereAirspace s2 = (SphereAirspace) a2; LatLon location1 = s1.getLocation(); LatLon location2 = s2.getLocation(); double altitude1 = s1.getAltitudes()[0]; double altitude2 = s2.getAltitudes()[0]; boolean terrainConforming1 = s1.isTerrainConforming()[0]; boolean terrainConforming2 = s2.isTerrainConforming()[0]; // We have to compute the 3D coordinates of the sphere's center ourselves here. Vec4 p1 = terrainConforming1 ? this.getSurfacePoint(location1, altitude1) : this.getPoint(location1, altitude1); Vec4 p2 = terrainConforming2 ? this.getSurfacePoint(location2, altitude2) : this.getPoint(location2, altitude2); double r1 = s1.getRadius(); double r2 = s2.getRadius(); double d = p1.distanceTo3(p2); return d <= (r1 + r2); } return false; }
protected void makeTessellatedLocations( Globe globe, int subdivisions, List<LatLon> locations, List<LatLon> tessellatedLocations) { ArrayList<Vec4> points = new ArrayList<Vec4>(); for (LatLon ll : locations) { points.add(globe.computePointFromLocation(ll)); } //noinspection StringEquality if (WWMath.computeWindingOrderOfLocations(locations) != AVKey.COUNTER_CLOCKWISE) Collections.reverse(locations); Vec4 centerPoint = Vec4.computeAveragePoint(points); Vec4 surfaceNormal = globe.computeSurfaceNormalAtPoint(centerPoint); int numPoints = points.size(); float[] coords = new float[3 * numPoints]; for (int i = 0; i < numPoints; i++) { points.get(i).toFloatArray(coords, 3 * i, 3); } GeometryBuilder gb = new GeometryBuilder(); GeometryBuilder.IndexedTriangleArray tessellatedPoints = gb.tessellatePolygon(0, numPoints, coords, surfaceNormal); for (int i = 0; i < subdivisions; i++) { gb.subdivideIndexedTriangleArray(tessellatedPoints); } for (int i = 0; i < tessellatedPoints.getVertexCount(); i++) { Vec4 v = Vec4.fromFloatArray(tessellatedPoints.getVertices(), 3 * i, 3); tessellatedLocations.add(globe.computePositionFromPoint(v)); } }
protected void requestTile(DrawContext dc, Tile tile) { Vec4 centroid = dc.getGlobe().computePointFromPosition(tile.getSector().getCentroid(), 0); if (this.getReferencePoint() != null) tile.setPriority(centroid.distanceTo3(this.getReferencePoint())); RequestTask task = new RequestTask(tile, this); this.getRequestQ().add(task); }
protected void assembleVertexControlPoints(DrawContext dc) { Terrain terrain = dc.getTerrain(); ExtrudedPolygon polygon = this.getPolygon(); Position refPos = polygon.getReferencePosition(); Vec4 refPoint = terrain.getSurfacePoint(refPos.getLatitude(), refPos.getLongitude(), 0); int altitudeMode = polygon.getAltitudeMode(); double height = polygon.getHeight(); Vec4 vaa = null; double vaaLength = 0; // used to compute independent length of each cap vertex double vaLength = 0; int i = 0; for (LatLon location : polygon.getOuterBoundary()) { Vec4 vert; // Compute the top/cap point. if (altitudeMode == WorldWind.CONSTANT || !(location instanceof Position)) { if (vaa == null) { // Compute the vector lengths of the top and bottom points at the reference position. vaa = refPoint.multiply3(height / refPoint.getLength3()); vaaLength = vaa.getLength3(); vaLength = refPoint.getLength3(); } // Compute the bottom point, which is on the terrain. vert = terrain.getSurfacePoint(location.getLatitude(), location.getLongitude(), 0); double delta = vaLength - vert.dot3(refPoint) / vaLength; vert = vert.add3(vaa.multiply3(1d + delta / vaaLength)); } else if (altitudeMode == WorldWind.RELATIVE_TO_GROUND) { vert = terrain.getSurfacePoint( location.getLatitude(), location.getLongitude(), ((Position) location).getAltitude()); } else // WorldWind.ABSOLUTE { vert = terrain .getGlobe() .computePointFromPosition( location.getLatitude(), location.getLongitude(), ((Position) location).getAltitude() * terrain.getVerticalExaggeration()); } Position vertexPosition = this.wwd.getModel().getGlobe().computePositionFromPoint(vert); this.controlPoints.add( new ControlPointMarker( MOVE_VERTEX_ACTION, vertexPosition, vert, this.vertexControlAttributes, i)); i++; } }
protected static boolean isNameVisible( DrawContext dc, PlaceNameService service, Position namePosition) { double elevation = dc.getVerticalExaggeration() * namePosition.getElevation(); Vec4 namePoint = dc.getGlobe() .computePointFromPosition( namePosition.getLatitude(), namePosition.getLongitude(), elevation); Vec4 eyeVec = dc.getView().getEyePoint(); double dist = eyeVec.distanceTo3(namePoint); return dist >= service.getMinDisplayDistance() && dist <= service.getMaxDisplayDistance(); }
protected void onHorizontalTranslateRel( Angle forwardChange, Angle sideChange, ViewInputAttributes.ActionAttributes actionAttribs) { View view = this.getView(); if (view == null) // include this test to ensure any derived implementation performs it { return; } if (forwardChange.equals(Angle.ZERO) && sideChange.equals(Angle.ZERO)) { return; } if (view instanceof BasicFlyView) { Vec4 forward = view.getForwardVector(); Vec4 up = view.getUpVector(); Vec4 side = forward.transformBy3(Matrix.fromAxisAngle(Angle.fromDegrees(90), up)); forward = forward.multiply3(forwardChange.getDegrees()); side = side.multiply3(sideChange.getDegrees()); Vec4 eyePoint = view.getEyePoint(); eyePoint = eyePoint.add3(forward.add3(side)); Position newPosition = view.getGlobe().computePositionFromPoint(eyePoint); this.setEyePosition(this.uiAnimControl, view, newPosition, actionAttribs); view.firePropertyChange(AVKey.VIEW, null, view); } }
protected Matrix transformModelView(Matrix modelView, IDelegateView view) { if (disableHeadTransform) { return modelView; } Vec4 translation = RiftUtils.toVec4(eyePoses[eye].Position); double translationScale = getHeadTranslationScale(view); Quaternion rotation = RiftUtils.toQuaternion(eyePoses[eye].Orientation); Matrix translationM = Matrix.fromTranslation(translation.multiply3(-translationScale)); Matrix rotationM = Matrix.fromQuaternion(rotation.getInverse()); return rotationM.multiply(translationM.multiply(modelView)); }
private float[] vectorToArray(Vec4... vectors) { double[] temp = new double[4]; int counter = 0; float[] vf = new float[vectors.length * 4]; for (Vec4 v : vectors) { temp = v.toArray4(temp, 0); for (int i = 0; i < temp.length; i++) { vf[counter] = (float) temp[i]; counter++; } } return vf; }
private void makeCap( DrawContext dc, GeometryBuilder.IndexedTriangleArray ita, double altitude, boolean terrainConformant, int orientation, Matrix locationTransform, Vec4 referenceCenter, int indexPos, int[] indices, int vertexPos, float[] vertices, float[] normals) { GeometryBuilder gb = this.getGeometryBuilder(); Globe globe = dc.getGlobe(); int indexCount = ita.getIndexCount(); int vertexCount = ita.getVertexCount(); int[] locationIndices = ita.getIndices(); float[] locationVerts = ita.getVertices(); this.copyIndexArray( indexCount, (orientation == GeometryBuilder.INSIDE), locationIndices, vertexPos, indexPos, indices); for (int i = 0; i < vertexCount; i++) { int index = 3 * i; Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]); vec = vec.transformBy4(locationTransform); Position pos = globe.computePositionFromPoint(vec); vec = this.computePointFromPosition( dc, pos.getLatitude(), pos.getLongitude(), altitude, terrainConformant); index = 3 * (vertexPos + i); vertices[index] = (float) (vec.x - referenceCenter.x); vertices[index + 1] = (float) (vec.y - referenceCenter.y); vertices[index + 2] = (float) (vec.z - referenceCenter.z); } gb.makeIndexedTriangleArrayNormals( indexPos, indexCount, indices, vertexPos, vertexCount, vertices, normals); }
private void makeSectionVertices( DrawContext dc, int locationPos, float[] locations, double[] altitude, boolean[] terrainConformant, int subdivisions, Matrix locationTransform, Vec4 referenceCenter, int vertexPos, float[] vertices) { GeometryBuilder gb = this.getGeometryBuilder(); int numPoints = gb.getSubdivisionPointsVertexCount(subdivisions); Globe globe = dc.getGlobe(); int index1 = 3 * locationPos; int index2 = 3 * (locationPos + 1); float[] locationVerts = new float[3 * numPoints]; gb.makeSubdivisionPoints( locations[index1], locations[index1 + 1], locations[index1 + 2], locations[index2], locations[index2 + 1], locations[index2 + 2], subdivisions, locationVerts); for (int i = 0; i < numPoints; i++) { int index = 3 * i; Vec4 vec = new Vec4(locationVerts[index], locationVerts[index + 1], locationVerts[index + 2]); vec = vec.transformBy4(locationTransform); Position pos = globe.computePositionFromPoint(vec); for (int j = 0; j < 2; j++) { vec = this.computePointFromPosition( dc, pos.getLatitude(), pos.getLongitude(), altitude[j], terrainConformant[j]); index = 2 * i + j; index = 3 * (vertexPos + index); vertices[index] = (float) (vec.x - referenceCenter.x); vertices[index + 1] = (float) (vec.y - referenceCenter.y); vertices[index + 2] = (float) (vec.z - referenceCenter.z); } } }
protected void render(DrawContext dc, Vec4 p1, Vec4 p2, double radius) { // To compute the rotation of the cylinder axis to the orientation of the vector between the // two points, // this method performs the same operation as Vec4.axisAngle() but with a "v2" of <0, 0, 1>. // Compute rotation angle double length = p1.distanceTo3(p2); Vec4 u1 = new Vec4((p2.x - p1.x) / length, (p2.y - p1.y) / length, (p2.z - p1.z) / length); double angle = Math.acos(u1.z); // Compute the direction cosine factors that define the rotation axis double A = -u1.y; double B = u1.x; double L = Math.sqrt(A * A + B * B); GL gl = dc.getGL(); // pushReferenceCenter performs the translation of the pipe's origin to point p1 and the // necessary // push/pop of the modelview stack. Otherwise we'd need to include a glPushMatrix and // gl.glTranslated(p1.x, p1.y, p1.z) above the rotation, and a corresponding glPopMatrix after // the // call to glCallIst. dc.getView().pushReferenceCenter(dc, p1); gl.glRotated(angle * TO_DEGREES, A / L, B / L, 0); gl.glScaled( radius, radius, length / 2); // length / 2 because cylinder is created with length 2 dc.getGL().glCallList(this.glListId); dc.getView().popReferenceCenter(dc); }
// Draw the scale label private void drawLabel(DrawContext dc, String text, Vec4 screenPoint) { TextRenderer textRenderer = OGLTextRenderer.getOrCreateTextRenderer(dc.getTextRendererCache(), this.defaultFont); Rectangle2D nameBound = textRenderer.getBounds(text); int x = (int) (screenPoint.x() - nameBound.getWidth() / 2d); int y = (int) screenPoint.y(); textRenderer.begin3DRendering(); textRenderer.setColor(this.getBackgroundColor(this.color)); textRenderer.draw(text, x + 1, y - 1); textRenderer.setColor(this.color); textRenderer.draw(text, x, y); textRenderer.end3DRendering(); }
protected void addToolTip(DrawContext dc, WWIcon icon, Vec4 iconPoint) { if (icon.getToolTipFont() == null && icon.getToolTipText() == null) return; Vec4 screenPoint = dc.getView().project(iconPoint); if (screenPoint == null) return; if (icon.getToolTipOffset() != null) screenPoint = screenPoint.add3(icon.getToolTipOffset()); OrderedText tip = new OrderedText( icon.getToolTipText(), icon.getToolTipFont(), screenPoint, icon.getToolTipTextColor(), 0d); dc.addOrderedRenderable(tip); }
/** * Add a vertex to the polygon's outer boundary. * * @param mousePoint the point at which the mouse was clicked. The new vertex will be placed as * near as possible to this point, at the elevation of the polygon. */ protected void addVertex(Point mousePoint) { // Try to find the edge that is closest to a ray passing through the screen point. We're trying // to determine // the user's intent as to which edge a new two control points should be added to. Line ray = this.wwd.getView().computeRayFromScreenPoint(mousePoint.getX(), mousePoint.getY()); Vec4 pickPoint = this.intersectPolygonAltitudeAt(ray); double nearestDistance = Double.MAX_VALUE; int newVertexIndex = 0; // Loop through the control points and determine which edge is closest to the pick point for (int i = 0; i < this.controlPoints.size(); i++) { ControlPointMarker thisMarker = (ControlPointMarker) this.controlPoints.get(i); ControlPointMarker nextMarker = (ControlPointMarker) this.controlPoints.get((i + 1) % this.controlPoints.size()); Vec4 pointOnEdge = AirspaceEditorUtil.nearestPointOnSegment(thisMarker.point, nextMarker.point, pickPoint); if (!AirspaceEditorUtil.isPointBehindLineOrigin(ray, pointOnEdge)) { double d = pointOnEdge.distanceTo3(pickPoint); if (d < nearestDistance) { newVertexIndex = i + 1; nearestDistance = d; } } } Position newPosition = this.wwd.getModel().getGlobe().computePositionFromPoint(pickPoint); // Copy the outer boundary list ArrayList<Position> positionList = new ArrayList<Position>(this.controlPoints.size()); for (LatLon position : this.getPolygon().getOuterBoundary()) { positionList.add((Position) position); } // Add the new vertex positionList.add(newVertexIndex, newPosition); this.getPolygon().setOuterBoundary(positionList); }
protected Extent computeExtent(Globe globe, double verticalExaggeration) { List<Vec4> points = this.computeMinimalGeometry(globe, verticalExaggeration); if (points == null || points.isEmpty()) return null; // Add a point at the center of this polygon to the points used to compute its extent. The // center point captures // the curvature of the globe when the polygon's minimal geometry only contain any points near // the polygon's // edges. Vec4 centerPoint = Vec4.computeAveragePoint(points); LatLon centerLocation = globe.computePositionFromPoint(centerPoint); this.makeExtremePoints(globe, verticalExaggeration, Arrays.asList(centerLocation), points); return Box.computeBoundingBox(points); }
/** * Returns the vector element at the specified position, as a {@link Vec4}. This buffer's logical * vector size must be either 2, 3 or 4. * * @param position the logical vector position. * @return the vector at the specified vector position. * @throws IllegalArgumentException if the position is out of range, or if this buffer cannot * store a Vec4. */ public Vec4 getVector(int position) { if (position < 0 || position >= this.getSize()) { String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4) { String message = Logging.getMessage("generic.BufferIncompatible", this); Logging.logger().severe(message); throw new IllegalArgumentException(message); } double[] compArray = new double[this.coordsPerVec]; this.get(position, compArray); return Vec4.fromDoubleArray(compArray, 0, this.coordsPerVec); }
public void lookAt(Position lookAtPos, long timeToMove) { BasicFlyView view = (BasicFlyView) this.getView(); Vec4 lookDirection; double distanceToSurface; Vec4 currentLookAtPt = view.getCenterPoint(); Position newPosition; if (currentLookAtPt == null) { view.getGlobe().computePointFromPosition(lookAtPos); double elevAtLookAtPos = view.getGlobe().getElevation(lookAtPos.getLatitude(), lookAtPos.getLongitude()); newPosition = new Position(lookAtPos, elevAtLookAtPos + 10000); } else { Vec4 currentEyePt = view.getEyePoint(); distanceToSurface = currentEyePt.distanceTo3(currentLookAtPt); lookDirection = currentLookAtPt.subtract3(currentEyePt).normalize3(); Vec4 newLookAtPt = view.getGlobe().computePointFromPosition(lookAtPos); Vec4 flyToPoint = newLookAtPt.add3(lookDirection.multiply3(-distanceToSurface)); newPosition = view.getGlobe().computePositionFromPoint(flyToPoint); } ViewUtil.ViewState viewCoords = view.getViewState(newPosition, lookAtPos); FlyToFlyViewAnimator panAnimator = FlyToFlyViewAnimator.createFlyToFlyViewAnimator( view, view.getEyePosition(), newPosition, view.getHeading(), viewCoords.getHeading(), view.getPitch(), viewCoords.getPitch(), view.getEyePosition().getElevation(), viewCoords.getPosition().getElevation(), timeToMove, WorldWind.ABSOLUTE); this.gotoAnimControl.put(VIEW_ANIM_PAN, panAnimator); this.getView().firePropertyChange(AVKey.VIEW, null, this.getView()); view.firePropertyChange(AVKey.VIEW, null, view); }
/** * Sets the vector element at the specified position, as a Vec4. This buffer's logical vector size * must be either 2, 3 or 4. * * @param position the logical vector position. * @param vec the vector to set. * @throws IllegalArgumentException if the position is out of range, if the vector is null, or if * this buffer cannot store a Vec4. */ public void putVector(int position, Vec4 vec) { if (position < 0 || position >= this.getSize()) { String message = Logging.getMessage("generic.ArgumentOutOfRange", "position < 0 or position >= size"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (vec == null) { String message = Logging.getMessage("nullValue.Vec4IsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (this.coordsPerVec != 2 && this.coordsPerVec != 3 && this.coordsPerVec != 4) { String message = Logging.getMessage("generic.BufferIncompatible", this); Logging.logger().severe(message); throw new IllegalArgumentException(message); } double[] compArray = new double[this.coordsPerVec]; vec.toDoubleArray(compArray, 0, this.coordsPerVec); this.put(position, compArray); }
/** * Computes the lat/lon of the pickPoint over the world map * * @param dc the current <code>DrawContext</code> * @param locationSW the screen location of the bottom left corner of the map * @param mapSize the world map screen dimension in pixels * @return the picked Position */ protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimension mapSize) { Position pickPosition = null; Point pickPoint = dc.getPickPoint(); if (pickPoint != null) { Rectangle viewport = dc.getView().getViewport(); // Check if pickpoint is inside the map if (pickPoint.getX() >= locationSW.getX() && pickPoint.getX() < locationSW.getX() + mapSize.width && viewport.height - pickPoint.getY() >= locationSW.getY() && viewport.height - pickPoint.getY() < locationSW.getY() + mapSize.height) { double lon = (pickPoint.getX() - locationSW.getX()) / mapSize.width * 360 - 180; double lat = (viewport.height - pickPoint.getY() - locationSW.getY()) / mapSize.height * 180 - 90; double pickAltitude = 1000e3; pickPosition = new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lon), pickAltitude); } } return pickPosition; }
protected double computeHorizonDistance(Vec4 eyePoint) { double horizon = 0; // Compute largest distance to flat globe 'corners'. if (this.globe != null && eyePoint != null) { double dist = 0; Vec4 p; // Use max distance to six points around the map p = this.globe.computePointFromPosition(Angle.POS90, Angle.NEG180, 0); // NW dist = Math.max(dist, eyePoint.distanceTo3(p)); p = this.globe.computePointFromPosition(Angle.POS90, Angle.POS180, 0); // NE dist = Math.max(dist, eyePoint.distanceTo3(p)); p = this.globe.computePointFromPosition(Angle.NEG90, Angle.NEG180, 0); // SW dist = Math.max(dist, eyePoint.distanceTo3(p)); p = this.globe.computePointFromPosition(Angle.NEG90, Angle.POS180, 0); // SE dist = Math.max(dist, eyePoint.distanceTo3(p)); p = this.globe.computePointFromPosition(Angle.ZERO, Angle.POS180, 0); // E dist = Math.max(dist, eyePoint.distanceTo3(p)); p = this.globe.computePointFromPosition(Angle.ZERO, Angle.NEG180, 0); // W dist = Math.max(dist, eyePoint.distanceTo3(p)); horizon = dist; } return horizon; }
/** * Reset the view to an orbit view state if in first person mode (zoom = 0) * * @param view the orbit view to reset */ protected void resetOrbitView(OrbitView view) { if (view.getZoom() > 0) // already in orbit view mode return; // Find out where on the terrain the eye is looking at in the viewport center // TODO: if no terrain is found in the viewport center, iterate toward viewport bottom until it // is found Vec4 centerPoint = computeSurfacePoint(view, view.getHeading(), view.getPitch()); // Reset the orbit view center point heading, pitch and zoom if (centerPoint != null) { Vec4 eyePoint = view.getEyePoint(); // Center pos on terrain surface Position centerPosition = wwd.getModel().getGlobe().computePositionFromPoint(centerPoint); // Compute pitch and heading relative to center position Vec4 normal = wwd.getModel() .getGlobe() .computeSurfaceNormalAtLocation( centerPosition.getLatitude(), centerPosition.getLongitude()); Vec4 north = wwd.getModel() .getGlobe() .computeNorthPointingTangentAtLocation( centerPosition.getLatitude(), centerPosition.getLongitude()); // Pitch view.setPitch(Angle.POS180.subtract(view.getForwardVector().angleBetween3(normal))); // Heading Vec4 perpendicular = view.getForwardVector().perpendicularTo3(normal); Angle heading = perpendicular.angleBetween3(north); double direction = Math.signum(-normal.cross3(north).dot3(perpendicular)); view.setHeading(heading.multiply(direction)); // Zoom view.setZoom(eyePoint.distanceTo3(centerPoint)); // Center pos view.setCenterPosition(centerPosition); } }
/** * Compute points on either side of a line segment. This method requires a point on the line, and * either a next point, previous point, or both. * * @param point Center point about which to compute side points. * @param prev Previous point on the line. May be null if {@code next} is non-null. * @param next Next point on the line. May be null if {@code prev} is non-null. * @param leftPositions Left position will be added to this list. * @param rightPositions Right position will be added to this list. * @param halfWidth Distance from the center line to the left or right lines. * @param globe Current globe. */ protected void generateParallelPoints( Vec4 point, Vec4 prev, Vec4 next, List<Position> leftPositions, List<Position> rightPositions, double halfWidth, Globe globe) { if ((point == null) || (prev == null && next == null)) { String message = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (leftPositions == null || rightPositions == null) { String message = Logging.getMessage("nullValue.PositionListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (globe == null) { String message = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } Vec4 offset; Vec4 normal = globe.computeSurfaceNormalAtPoint(point); // Compute vector in the direction backward along the line. Vec4 backward = (prev != null) ? prev.subtract3(point) : point.subtract3(next); // Compute a vector perpendicular to segment BC, and the globe normal vector. Vec4 perpendicular = backward.cross3(normal); double length; // If both next and previous points are supplied then calculate the angle that bisects the angle // current, next, prev. if (next != null && prev != null && !Vec4.areColinear(prev, point, next)) { // Compute vector in the forward direction. Vec4 forward = next.subtract3(point); // Calculate the vector that bisects angle ABC. offset = forward.normalize3().add3(backward.normalize3()); offset = offset.normalize3(); // Compute the scalar triple product of the vector BC, the normal vector, and the offset // vector to // determine if the offset points to the left or the right of the control line. double tripleProduct = perpendicular.dot3(offset); if (tripleProduct < 0) { offset = offset.multiply3(-1); } // Determine the length of the offset vector that will keep the left and right lines parallel // to the control // line. Angle theta = backward.angleBetween3(offset); if (!Angle.ZERO.equals(theta)) length = halfWidth / theta.sin(); else length = halfWidth; } else { offset = perpendicular.normalize3(); length = halfWidth; } offset = offset.multiply3(length); // Determine the left and right points by applying the offset. Vec4 ptRight = point.add3(offset); Vec4 ptLeft = point.subtract3(offset); // Convert cartesian points to geographic. Position posLeft = globe.computePositionFromPoint(ptLeft); Position posRight = globe.computePositionFromPoint(ptRight); leftPositions.add(posLeft); rightPositions.add(posRight); }