📄 ebsrectangulartessellator.java
字号:
coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); Vec4 cellCenter = Vec4.mix3(.5, v1, v2); // Test cell center distance to vertical plane if (Math.abs(verticalPlane.distanceTo(cellCenter)) > maxCellRadius) continue; // Test cell center distance to horizontal plane if (Math.abs(horizontalPlane.distanceTo(cellCenter)) > elevationSpan) continue; // Prepare to test triangles - get other two vertices v0 & v3 Vec4 p; vIndex = 3 * indices[i]; Vec4 v0 = new Vec4( coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); vIndex = 3 * indices[i + 3]; Vec4 v3 = new Vec4( coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); // Test triangle 1 intersection w ray Triangle t = new Triangle(v0, v1, v2); if ((p = t.intersect(line)) != null) { list.add(new Intersection(p, false)); } // Test triangle 2 intersection w ray t = new Triangle(v1, v2, v3); if ((p = t.intersect(line)) != null) { list.add(new Intersection(p, false)); } } int numHits = list.size(); if (numHits == 0) return null; hits = new Intersection[numHits]; list.toArray(hits); final Vec4 origin = line.getOrigin(); Arrays.sort(hits, new Comparator<Intersection>() { public int compare(Intersection i1, Intersection i2) { if (i1 == null && i2 == null) return 0; if (i2 == null) return -1; if (i1 == null) return 1; Vec4 v1 = i1.getIntersectionPoint(); Vec4 v2 = i2.getIntersectionPoint(); double d1 = origin.distanceTo3(v1); double d2 = origin.distanceTo3(v2); return Double.compare(d1, d2); } }); return hits; } /** * Determines if and where a <code>RectTile</code> geometry intersects the globe ellipsoid at a given elevation. * The returned array of <code>Intersection</code> describes a list of individual segments - two * <code>Intersection</code> for each, corresponding to each geometry triangle that intersects the given elevation. * * @param tile the <Code>RectTile</code> which geometry is to be tested for intersection. * @param elevation the elevation for which intersection points are to be found. * @return an array of <code>Intersection</code> pairs or null if no intersection was found. */ private Intersection[] intersect(RectTile tile, double elevation) { if (tile.ri.vertices == null) return null; // Check whether the tile includes the intersection elevation - assume cylinder as Extent Cylinder cylinder = ((Cylinder)tile.getExtent()); if (!(globe.isPointAboveElevation(cylinder.getBottomCenter(), elevation) ^ globe.isPointAboveElevation(cylinder.getTopCenter(), elevation))) return null; Intersection[] hits; ArrayList<Intersection> list = new ArrayList<Intersection>(); int[] indices = new int[tile.ri.indices.limit()]; double[] coords = new double[tile.ri.vertices.limit()]; tile.ri.indices.rewind(); tile.ri.vertices.rewind(); tile.ri.indices.get(indices, 0, indices.length); tile.ri.vertices.get(coords, 0, coords.length); tile.ri.indices.rewind(); tile.ri.vertices.rewind(); int trianglesNum = tile.ri.indices.capacity() - 2; double centerX = tile.ri.referenceCenter.x; double centerY = tile.ri.referenceCenter.y; double centerZ = tile.ri.referenceCenter.z; // Loop through all tile cells - triangle pairs int startIndice = (density + 2) * 2 + 6; // skip firts skirt row and a couple degenerate cells int endIndice = trianglesNum - startIndice; // ignore last skirt row and a couple degenerate cells int k = -1; for (int i = startIndice; i < endIndice; i += 2) { // Skip skirts and degenerate triangle cells - based on indice sequence. k = k == density - 1 ? -4 : k + 1; // density x terrain cells interleaved with 4 skirt and degenerate cells. if (k < 0) continue; // Get the four cell corners int vIndex = 3 * indices[i]; Vec4 v0 = new Vec4( coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); vIndex = 3 * indices[i + 1]; Vec4 v1 = new Vec4( coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); vIndex = 3 * indices[i + 2]; Vec4 v2 = new Vec4( coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); vIndex = 3 * indices[i + 3]; Vec4 v3 = new Vec4( coords[vIndex++] + centerX, coords[vIndex++] + centerY, coords[vIndex] + centerZ); Intersection[] inter; // Test triangle 1 intersection if ((inter = globe.intersect(new Triangle(v0, v1, v2), elevation)) != null) { list.add(inter[0]); list.add(inter[1]); } // Test triangle 2 intersection if ((inter = globe.intersect(new Triangle(v1, v2, v3), elevation)) != null) { list.add(inter[0]); list.add(inter[1]); } } int numHits = list.size(); if (numHits == 0) return null; hits = new Intersection[numHits]; list.toArray(hits); return hits; } private Vec4 getSurfacePoint(RectTile tile, Angle latitude, Angle longitude, double metersOffset) { Vec4 result = this.getSurfacePoint(tile, latitude, longitude); if (metersOffset != 0 && result != null) result = applyOffset(this.globe, result, metersOffset); return result; } /** * Offsets <code>point</code> by <code>metersOffset</code> meters. * * @param globe the <code>Globe</code> from which to offset * @param point the <code>Vec4</code> to offset * @param metersOffset the magnitude of the offset * @return <code>point</code> offset along its surface normal as if it were on <code>globe</code> */ private static Vec4 applyOffset(Globe globe, Vec4 point, double metersOffset) { Vec4 normal = globe.computeSurfaceNormalAtPoint(point); point = Vec4.fromLine3(point, metersOffset, normal); return point; } private Vec4 getSurfacePoint(RectTile tile, Angle latitude, Angle longitude) { if (latitude == null || longitude == null) { String msg = Logging.getMessage("nullValue.LatLonIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (!tile.sector.contains(latitude, longitude)) { // not on this geometry return null; } if (tile.ri == null) return null; if (Math.abs(latitude.getDegrees()) > latitudeCutoffInDegrees) return getSurfacePointPolarRegion(tile,latitude,longitude); return getSurfacePointLateralSides(tile,latitude,longitude); } private Vec4 getSurfacePointLateralSides(RectTile tile, Angle latitude, Angle longitude) { // guaranteed that none of the input parameters are null double lat = latitude.getDegrees(); double lon = longitude.getDegrees(); double bottom = tile.sector.getMinLatitude().getDegrees(); double top = tile.sector.getMaxLatitude().getDegrees(); double left = tile.sector.getMinLongitude().getDegrees(); double right = tile.sector.getMaxLongitude().getDegrees(); double leftDecimal = (lon - left) / (right - left); double bottomDecimal = (lat - bottom) / (top - bottom); int row = (int) (bottomDecimal * (tile.density)); int column = (int) (leftDecimal * (tile.density)); double l = createPosition(column, leftDecimal, tile.ri.density); double h = createPosition(row, bottomDecimal, tile.ri.density); Vec4 result = interpolate(row, column, l, h, tile.ri); result = result.add3(tile.ri.referenceCenter); return result; } /** * Computes from a column (or row) number, and a given offset ranged [0,1] corresponding to the distance along the * edge of this sector, where between this column and the next column the corresponding position will fall, in the * range [0,1]. * * @param start the number of the column or row to the left, below or on this position * @param decimal the distance from the left or bottom of the current sector that this position falls * @param density the number of intervals along the sector's side * @return a decimal ranged [0,1] representing the position between two columns or rows, rather than between two * edges of the sector */ private static double createPosition(int start, double decimal, int density) { double l = ((double) start) / (double) density; double r = ((double) (start + 1)) / (double) density; return (decimal - l) / (r - l); } /** * Calculates a <code>Point</code> that sits at <code>xDec</code> offset from <code>column</code> to <code>column + * 1</code> and at <code>yDec</code> offset from <code>row</code> to <code>row + 1</code>. Accounts for the * diagonals. * * @param row represents the row which corresponds to a <code>yDec</code> value of 0 * @param column represents the column which corresponds to an <code>xDec</code> value of 0 * @param xDec constrained to [0,1] * @param yDec constrained to [0,1] * @param ri the render info holding the vertices, etc. * @return a <code>Point</code> geometrically within or on the boundary of the quadrilateral whose bottom left * corner is indexed by (<code>row</code>, <code>column</code>) */ private static Vec4 interpolate(int row, int column, double xDec, double yDec, RenderInfo ri) { row++; column++; int numVerticesPerEdge = ri.density + 3; int bottomLeft = row * numVerticesPerEdge + column; bottomLeft *= 3; int numVertsTimesThree = numVerticesPerEdge * 3; double[] a = new double[6]; ri.vertices.position(bottomLeft); ri.vertices.get(a); Vec4 bL = new Vec4(a[0], a[1], a[2]); Vec4 bR = new Vec4(a[3], a[4], a[5]);// Vec4 bL = new Vec4(ri.vertices.get(bottomLeft), ri.vertices.get(bottomLeft + 1), ri.vertices.get(// bottomLeft + 2));// Vec4 bR = new Vec4(ri.vertices.get(bottomLeft + 3), ri.vertices.get(bottomLeft + 4),// ri.vertices.get(bottomLeft + 5)); bottomLeft += numVertsTimesThree; ri.vertices.position(bottomLeft); ri.vertices.get(a); Vec4 tL = new Vec4(a[0], a[1], a[2]); Vec4 tR = new Vec4(a[3], a[4], a[5]);// Vec4 tL = new Vec4(ri.vertices.get(bottomLeft), ri.vertices.get(bottomLeft + 1), ri.vertices.get(// bottomLeft + 2));// Vec4 tR = new Vec4(ri.vertices.get(bottomLeft + 3), ri.vertices.get(bottomLeft + 4),// ri.vertices.get(bottomLeft + 5)); return interpolate(bL, bR, tR, tL, xDec, yDec); } /** * Calculates the point at (xDec, yDec) in the two triangles defined by {bL, bR, tL} and {bR, tR, tL}. If thought of * as a quadrilateral, the diagonal runs from tL to bR. Of course, this isn't a quad, it's two triangles. * * @param bL the bottom left corner * @param bR the bottom right c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -