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)); } }
/** * Computes a <code>Box</code> that bounds a specified buffer of points. Principal axes are * computed for the points and used to form a <code>Box</code>. This returns <code>null</code> if * the buffer is empty or contains only a partial point. * * <p>The buffer must contain XYZ coordinate tuples which are either tightly packed or offset by * the specified stride. The stride specifies the number of buffer elements between the first * coordinate of consecutive tuples. For example, a stride of 3 specifies that each tuple is * tightly packed as XYZXYZXYZ, whereas a stride of 5 specifies that there are two elements * between each tuple as XYZabXYZab (the elements "a" and "b" are ignored). The stride must be at * least 3. If the buffer's length is not evenly divisible into stride-sized tuples, this ignores * the remaining elements that follow the last complete tuple. * * @param buffer the buffer containing the point coordinates for which to compute a bounding * volume. * @param stride the number of elements between the first coordinate of consecutive points. If * stride is 3, this interprets the buffer has having tightly packed XYZ coordinate tuples. * @return the bounding volume, with axes lengths consistent with the conventions described in the * <code>Box</code> class overview. * @throws IllegalArgumentException if the buffer is null or empty, or if the stride is less than * three. */ public static Box computeBoundingBox(FloatBuffer buffer, int stride) { if (buffer == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.error(msg); throw new IllegalArgumentException(msg); } if (stride < 3) { String msg = Logging.getMessage("generic.StrideIsInvalid", stride); Logging.error(msg); throw new IllegalArgumentException(msg); } Vec4[] axes = WWMath.computePrincipalAxes(buffer, stride); if (axes == null) { String msg = Logging.getMessage("generic.BufferIsEmpty"); Logging.error(msg); throw new IllegalArgumentException(msg); } Vec4 r = axes[0]; Vec4 s = axes[1]; Vec4 t = axes[2]; // Find the extremes along each axis. double minDotR = Double.MAX_VALUE; double maxDotR = -minDotR; double minDotS = Double.MAX_VALUE; double maxDotS = -minDotS; double minDotT = Double.MAX_VALUE; double maxDotT = -minDotT; for (int i = buffer.position(); i <= buffer.limit() - stride; i += stride) { double x = buffer.get(i); double y = buffer.get(i + 1); double z = buffer.get(i + 2); double pdr = x * r.x + y * r.y + z * r.z; if (pdr < minDotR) minDotR = pdr; if (pdr > maxDotR) maxDotR = pdr; double pds = x * s.x + y * s.y + z * s.z; if (pds < minDotS) minDotS = pds; if (pds > maxDotS) maxDotS = pds; double pdt = x * t.x + y * t.y + z * t.z; if (pdt < minDotT) minDotT = pdt; if (pdt > maxDotT) maxDotT = pdt; } if (maxDotR == minDotR) maxDotR = minDotR + 1; if (maxDotS == minDotS) maxDotS = minDotS + 1; if (maxDotT == minDotT) maxDotT = minDotT + 1; return new Box(axes, minDotR, maxDotR, minDotS, maxDotS, minDotT, maxDotT); }
public AppFrame() { super(true, true, false); // Create list of positions along the control line. List<Position> positions = Arrays.asList( Position.fromDegrees(49.0457, -122.8115, 100), Position.fromDegrees(49.0539, -122.8091, 110), Position.fromDegrees(49.0621, -122.7937, 120), Position.fromDegrees(49.0681, -122.8044, 130), Position.fromDegrees(49.0682, -122.7730, 140), Position.fromDegrees(49.0482, -122.7764, 150), Position.fromDegrees(49.0498, -122.7466, 140), Position.fromDegrees(49.0389, -122.7453, 130), Position.fromDegrees(49.0321, -122.7759, 120), Position.fromDegrees(49.0394, -122.7689, 110), Position.fromDegrees(49.0629, -122.7666, 100)); // We will generate four paths parallel to the control path. Allocate lists to store the // positions of these // paths. List<Position> pathPositions1 = new ArrayList<Position>(); List<Position> pathPositions2 = new ArrayList<Position>(); List<Position> pathPositions3 = new ArrayList<Position>(); List<Position> pathPositions4 = new ArrayList<Position>(); Globe globe = getWwd().getModel().getGlobe(); // Generate two sets of lines parallel to the control line. The positions will be added to the // pathPosition lists. WWMath.generateParallelLines(positions, pathPositions1, pathPositions2, 50, globe); WWMath.generateParallelLines(positions, pathPositions3, pathPositions4, 100, globe); // Create Path objects from the position lists, and add them to a layer. RenderableLayer layer = new RenderableLayer(); this.addPath(layer, positions, "Control Path"); this.addPath(layer, pathPositions1, "Path 1"); this.addPath(layer, pathPositions2, "Path 2"); this.addPath(layer, pathPositions3, "Path 3"); this.addPath(layer, pathPositions4, "Path 4"); insertBeforePlacenames(getWwd(), layer); }
/** * Compute a <code>Box</code> that bounds a specified list of points. Principal axes are computed * for the points and used to form a <code>Box</code>. * * @param points the points for which to compute a bounding volume. * @return the bounding volume, with axes lengths consistent with the conventions described in the * overview. * @throws IllegalArgumentException if the point list is null or empty. */ public static Box computeBoundingBox(Iterable<? extends Vec4> points) { if (points == null) { String msg = Logging.getMessage("nullValue.PointListIsNull"); Logging.error(msg); throw new IllegalArgumentException(msg); } Vec4[] axes = WWMath.computePrincipalAxes(points); if (axes == null) { String msg = Logging.getMessage("generic.PointListIsEmpty"); Logging.error(msg); throw new IllegalArgumentException(msg); } Vec4 r = axes[0]; Vec4 s = axes[1]; Vec4 t = axes[2]; // Find the extremes along each axis. double minDotR = Double.MAX_VALUE; double maxDotR = -minDotR; double minDotS = Double.MAX_VALUE; double maxDotS = -minDotS; double minDotT = Double.MAX_VALUE; double maxDotT = -minDotT; for (Vec4 p : points) { if (p == null) continue; double pdr = p.dot3(r); if (pdr < minDotR) minDotR = pdr; if (pdr > maxDotR) maxDotR = pdr; double pds = p.dot3(s); if (pds < minDotS) minDotS = pds; if (pds > maxDotS) maxDotS = pds; double pdt = p.dot3(t); if (pdt < minDotT) minDotT = pdt; if (pdt > maxDotT) maxDotT = pdt; } if (maxDotR == minDotR) maxDotR = minDotR + 1; if (maxDotS == minDotS) maxDotS = minDotS + 1; if (maxDotT == minDotT) maxDotT = minDotT + 1; return new Box(axes, minDotR, maxDotR, minDotS, maxDotS, minDotT, maxDotT); }