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); }
protected Vec4[] calculateBentNormals(int width, int height, Vec4[] verts, int padding) { int padding2 = padding * 2; if (verts.length != (width + padding2) * (height + padding2)) throw new IllegalStateException("Illegal vertices length"); Vec4[] norms = new Vec4[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Vec4 vec = verts[getArrayIndex(width + padding2, height + padding2, x + padding, y + padding)]; if (vec != null) { Vec4 vecnorm = vec.normalize3(); Vec4[] maxes = new Vec4[16]; double[] angles = new double[16]; for (int i = 0; i < angles.length; i++) { angles[i] = Double.MAX_VALUE; } // 2 3 4 5 6 // 1 7 // 0 8 // 15 9 // 14 13 12 11 10 // for (int i = 1; i <= padding; i++) for (int i = 2; i <= padding; i += 2) { Vec4[] vecs = new Vec4[16]; vecs[0] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i, y + padding)]; vecs[2] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i, y + padding - i)]; vecs[4] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding, y + padding - i)]; vecs[6] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i, y + padding - i)]; vecs[8] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i, y + padding)]; vecs[10] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i, y + padding + i)]; vecs[12] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding, y + padding + i)]; vecs[14] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i, y + padding + i)]; if (i % 2 == 0) { int i2 = i / 2; vecs[1] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i, y + padding - i2)]; vecs[3] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i2, y + padding - i)]; vecs[5] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i2, y + padding - i)]; vecs[7] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i, y + padding - i2)]; vecs[9] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i, y + padding + i2)]; vecs[11] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding + i2, y + padding + i)]; vecs[13] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i2, y + padding + i)]; vecs[15] = verts[ getArrayIndex( width + padding2, height + padding2, x + padding - i, y + padding + i2)]; } for (int j = 0; j < maxes.length; j++) { if (vecs[j] != null) { Vec4 v = vecs[j].subtract3(vec).normalize3(); double angle = Math.acos(v.dot3(vecnorm)); if (angle < angles[j]) { angles[j] = angle; maxes[j] = v; } } } } Vec4 normal = Vec4.ZERO; for (int i = 0; i < maxes.length; i++) { if (maxes[i] != null) { Vec4 n = maxes[i].cross3(vecnorm).cross3(maxes[i]); normal = normal.add3(n); } } if (normal != Vec4.ZERO) { norms[getArrayIndex(width, height, x, y)] = normal.normalize3(); } } } } return norms; }