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++; } }
/** * 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); }