📄 ellipsoidalglobe.java
字号:
return inter; } public boolean intersects(Line line) { if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } return line.distanceTo(this.center) <= this.equatorialRadius; } public boolean intersects(Plane plane) { if (plane == null) { String msg = Logging.getMessage("nullValue.PlaneIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } double dq1 = plane.dot(this.center); return dq1 <= this.equatorialRadius; } public double getElevations(Sector sector, List<? extends LatLon> latlons, double targetResolution, double[] elevations) { return this.elevationModel != null ? this.elevationModel.getElevations(sector, latlons, targetResolution, elevations) : 0; } public double getElevation(Angle latitude, Angle longitude) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return this.elevationModel != null ? this.elevationModel.getElevation(latitude, longitude) : 0; } public Vec4 computePointFromPosition(Position position) { if (position == null) { String message = Logging.getMessage("nullValue.PositionIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return this.geodeticToCartesian(position.getLatitude(), position.getLongitude(), position.getElevation()); } public Vec4 computePointFromPosition(Angle latitude, Angle longitude, double metersElevation) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return this.geodeticToCartesian(latitude, longitude, metersElevation); } public Position computePositionFromPoint(Vec4 point) { if (point == null) { String message = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return this.cartesianToGeodetic(point); } /** * Returns the normal to the Globe at the specified position. * * @param latitude the latitude of the position. * @param longitude the longitude of the position. * * @return the Globe normal at the specified position. */ public Vec4 computeSurfaceNormalAtLocation(Angle latitude, Angle longitude) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } double cosLat = latitude.cos(); double cosLon = longitude.cos(); double sinLat = latitude.sin(); double sinLon = longitude.sin(); double eqSquared = this.equatorialRadius * this.equatorialRadius; double polSquared = this.polarRadius * this.polarRadius; double x = cosLat * sinLon / eqSquared; double y = (1.0 - this.es) * sinLat / polSquared; double z = cosLat * cosLon / eqSquared; return new Vec4(x, y, z).normalize3(); } /** * Returns the normal to the Globe at the specified cartiesian point. * * @param point the cartesian point. * * @return the Globe normal at the specified point. */ public Vec4 computeSurfaceNormalAtPoint(Vec4 point) { if (point == null) { String msg = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } double eqSquared = this.equatorialRadius * this.equatorialRadius; double polSquared = this.polarRadius * this.polarRadius; double x = (point.x - this.center.x) / eqSquared; double y = (point.y - this.center.y) / polSquared; double z = (point.z - this.center.z) / eqSquared; return new Vec4(x, y, z).normalize3(); } public Vec4 computeNorthPointingTangentAtLocation(Angle latitude, Angle longitude) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } // Latitude is treated clockwise as rotation about the X-axis. We flip the latitude value so that a positive // rotation produces a clockwise rotation (when facing the axis). latitude = latitude.multiply(-1.0); double cosLat = latitude.cos(); double sinLat = latitude.sin(); double cosLon = longitude.cos(); double sinLon = longitude.sin(); // The north-pointing tangent is derived by rotating the vector (0, 1, 0) about the Y-axis by longitude degrees, // then rotating it about the X-axis by -latitude degrees. This can be represented by a combining two rotation // matrices Rlat, and Rlon, then transforming the vector (0, 1, 0) by the combined transform: // // NorthTangent = (Rlon * Rlat) * (0, 1, 0) // // Since the input vector only has a Y coordinate, this computation can be simplified. The simplified // computation is shown here as NorthTangent = (x, y, z). // double x = sinLat * sinLon; //noinspection UnnecessaryLocalVariable double y = cosLat; double z = sinLat * cosLon; return new Vec4(x, y, z).normalize3(); } /** * Returns the cartesian transform Matrix that maps coordinates to the local coordinate system at * (latitude, longitude, metersElevation). They X axis will mapped to the vector tangent to the globe and pointing * East. The Y axis will mapped to the vector tangent to the Globe and pointing to the North Pole. The Z axis will * be mapped to the Globe normal at (latitude, longitude, metersElevation). The origin will be mapped to the * cartesian position of (latitude, longitude, metersElevation). * * @param latitude the latitude of the position. * @param longitude the longitude of the position. * @param metersElevation the number of meters above or below mean sea level. * * @return the cartesian transform Matrix that maps coordinates to the local coordinates at the specified position. */ public Matrix computeTransformToPosition(Angle latitude, Angle longitude, double metersElevation) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } Vec4 point = this.geodeticToCartesian(latitude, longitude, metersElevation); // Transform to the cartesian coordinates of (latitude, longitude, metersElevation). Matrix transform = Matrix.fromTranslation(point); // Rotate the coordinate system to match the longitude. // Longitude is treated as counter-clockwise rotation about the Y-axis. transform = transform.multiply(Matrix.fromRotationY(longitude)); // Rotate the coordinate systme to match the latitude. // Latitude is treated clockwise as rotation about the X-axis. We flip the latitude value so that a positive // rotation produces a clockwise rotation (when facing the axis). transform = transform.multiply(Matrix.fromRotationX(latitude.multiply(-1.0))); return transform; } /** * Returns the cartesian transform Matrix that maps coordinates to the local coordinate system at * (latitude, longitude, metersElevation). They X axis will mapped to the vector tangent to the globe and pointing * East. The Y axis will mapped to the vector tangent to the Globe and pointing to the North Pole. The Z axis will * be mapped to the Globe normal at (latitude, longitude, metersElevation). The origin will be mapped to the * cartesian position of (latitude, longitude, metersElevation). * * @param position the latitude, longitude, and number of meters above or below mean sea level. * * @return the cartesian transform Matrix that maps coordinates to the local coordinates at the specified position. */ public Matrix computeTransformToPosition(Position position) { if (position == null) { String message = Logging.getMessage("nullValue.PositionIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return this.computeTransformToPosition(position.getLatitude(), position.getLongitude(), position.getElevation()); } public Position getIntersectionPosition(Line line) { if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } Intersection[] intersections = this.intersect(line); if (intersections == null) return null; return this.computePositionFromPoint(intersections[0].getIntersectionPoint()); } /** * Maps a position to a flat world Cartesian coordinates. The Y axis points to the north pole. The Z axis points to * the intersection of the prime meridian and the equator, in the equatorial plane. The X axis completes a * right-handed coordinate system, and is 90 degrees east of the Z axis and also in the equatorial plane. Sea level * is at z = zero. * * @param latitude the latitude of the position. * @param longitude the longitude of the position. * @param metersElevation the number of meters above or below mean sea level. * * @return The Cartesian point corresponding to the input position. */ protected Vec4 geodeticToCartesian(Angle latitude, Angle longitude, double metersElevation) { if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatitudeOrLongitudeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } double cosLat = latitude.cos(); double sinLat = latitude.sin(); double cosLon = longitude.cos(); double sinLon = longitude.sin(); double rpm = // getRadius (in meters) of vertical in prime meridian this.equatorialRadius / Math.sqrt(1.0 - this.es * sinLat * sinLat); double x = (rpm + metersElevation) * cosLat * sinLon; double y = (rpm * (1.0 - this.es) + metersElevation) * sinLat; double z = (rpm + metersElevation) * cosLat * cosLon; return new Vec4(x, y, z); } protected Position cartesianToGeodetic(Vec4 cart) { if (cart == null) { String message = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } // according to // H. Vermeille, // Direct transformation from geocentric to geodetic ccordinates, // Journal of Geodesy (2002) 76:451-454 double ra2 = 1 / (this.equatorialRadius * equatorialRadius); double X = cart.z; //noinspection SuspiciousNameCombination double Y = cart.x; double Z = cart.y; double e2 = this.es; double e4 = e2 * e2; double XXpYY = X * X + Y * Y; double sqrtXXpYY = Math.sqrt(XXpYY); double p = XXpYY * ra2; double q = Z * Z * (1 - e2) * ra2; double r = 1 / 6.0 * (p + q - e4); double s = e4 * p * q / (4 * r * r * r); double t = Math.pow(1 + s + Math.sqrt(s * (2 + s)), 1 / 3.0); double u = r * (1 + t + 1 / t); double v = Math.sqrt(u * u + e4 * q); double w = e2 * (u + v - q) / (2 * v); double k = Math.sqrt(u + v + w * w) - w; double D = k * sqrtXXpYY / (k + e2); double lon = 2 * Math.atan2(Y, X + sqrtXXpYY); double sqrtDDpZZ = Math.sqrt(D * D + Z * Z); double lat = 2 * Math.atan2(Z, D + sqrtDDpZZ); double elevation = (k + e2 - 1) * sqrtDDpZZ / k; return Position.fromRadians(lat, lon, elevation); } /** * Returns a cylinder that minimally surrounds the sector at a specified vertical exaggeration.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -