⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ellipsoidalglobe.java

📁 world wind java sdk 源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
     *     * @param verticalExaggeration the vertical exaggeration to apply to the globe's elevations when computing the     *                             cylinder.     * @param sector               the sector to return the bounding cylinder for.     *     * @return The minimal bounding cylinder in Cartesian coordinates.     * @throws IllegalArgumentException if <code>sector</code> is null     */    public Cylinder computeBoundingCylinder(double verticalExaggeration, Sector sector)    {        if (sector == null)        {            String msg = Logging.getMessage("nullValue.SectorIsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        double[] minAndMaxElevations = this.getMinAndMaxElevations(sector);        return this.computeBoundingCylinder(verticalExaggeration, sector,            minAndMaxElevations[0], minAndMaxElevations[1]);    }    /**     * Returns a cylinder that minimally surrounds the specified minimum and maximum elevations in the sector at a     * specified vertical exaggeration.     *     * @param verticalExaggeration the vertical exaggeration to apply to the minimum and maximum elevations when     *                             computing the cylinder.     * @param sector               the sector to return the bounding cylinder for.     * @param minElevation         the minimum elevation of the bounding cylinder.     * @param maxElevation         the maximum elevation of the bounding cylinder.     *     * @return The minimal bounding cylinder in Cartesian coordinates.     * @throws IllegalArgumentException if <code>sector</code> is null     */    public Cylinder computeBoundingCylinder(double verticalExaggeration, Sector sector,                                            double minElevation, double maxElevation)    {        if (sector == null)        {            String msg = Logging.getMessage("nullValue.SectorIsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        // Compute the exaggerated minimum and maximum heights.        double minHeight = minElevation * verticalExaggeration;        double maxHeight = maxElevation * verticalExaggeration;        // If the sector spans both poles in latitude, or spans greater than 180 degrees in longitude, we cannot use the        // sector's Cartesian quadrilateral to compute a bounding cylinde. This is because the quadrilateral is either        // smaller than the geometry defined by the sector (when deltaLon >= 180), or the quadrilateral degenerates to        // two points (when deltaLat >= 180). So we compute a bounging cylinder that spans the equator and covers the        // sector's latitude range. In some cases this cylinder may be too large, but we're typically not interested        // in culling these cylinders since the sector will span most of the globe.        if (sector.getDeltaLatDegrees() >= 180d || sector.getDeltaLonDegrees() >= 180d)        {            return this.computeBoundsFromSectorLatitudeRange(sector, minHeight, maxHeight);        }        // Otherwise, create a standard bounding cylinder that minimally surrounds the specified sector and elevations.        else        {            return this.computeBoundsFromSectorQuadrilateral(sector, minHeight, maxHeight);        }    }    public SectorGeometryList tessellate(DrawContext dc)    {        if (this.tessellator == null)        {            this.tessellator = (Tessellator) WorldWind.createConfigurationComponent(AVKey.TESSELLATOR_CLASS_NAME);        }        return this.tessellator.tessellate(dc);    }    /**     * Determines whether a point is above a given elevation     *     * @param point the <code>Vec4</code> point to test.     * @param elevation the elevation to test for.     * @return true if the given point is above the given elevation.     */    public boolean isPointAboveElevation(Vec4 point, double elevation)    {        if (point == null)        {            String msg = Logging.getMessage("nullValue.PointIsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        return (point.x() * point.x()) / ((this.equatorialRadius + elevation) * (this.equatorialRadius + elevation))            + (point.y() * point.y()) / ((this.polarRadius + elevation) * (this.polarRadius + elevation))            + (point.z() * point.z()) / ((this.equatorialRadius + elevation) * (this.equatorialRadius + elevation))            - 1 > 0;    }    /**     * Returns a cylinder that minimally surrounds the specified height range in the sector.     *     * @param sector               the sector to return the bounding cylinder for.     * @param minHeight            the minimum height to include in the bounding cylinder.     * @param maxHeight            the maximum height to include in the bounding cylinder.     *     * @return The minimal bounding cylinder in Cartesian coordinates.     * @throws IllegalArgumentException if <code>sector</code> is null     */    protected Cylinder computeBoundsFromSectorQuadrilateral(Sector sector, double minHeight, double maxHeight)    {        if (sector == null)        {            String msg = Logging.getMessage("nullValue.SectorIsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        // Get three non-coincident points on the sector's quadrilateral. We choose the north or south pair that is        // closest to the equator, then choose a third point from the opposite pair. We use maxHeight as elevation        // because we want to bound the largest potential quadrilateral for the sector.        Vec4 p0, p1, p2;        if (Math.abs(sector.getMinLatitude().degrees) <= Math.abs(sector.getMaxLatitude().degrees))        {            p0 = this.computePointFromPosition(sector.getMinLatitude(), sector.getMaxLongitude(), maxHeight); // SE            p1 = this.computePointFromPosition(sector.getMinLatitude(), sector.getMinLongitude(), maxHeight); // SW            p2 = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMinLongitude(), maxHeight); // NW        }        else        {            p0 = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMinLongitude(), maxHeight); // NW            p1 = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMaxLongitude(), maxHeight); // NE            p2 = this.computePointFromPosition(sector.getMinLatitude(), sector.getMinLongitude(), maxHeight); // SW        }                // Compute the center, axis, and radius of the circle that circumscribes the three points.        // This circle is guaranteed to circumscribe all four points of the sector's Cartesian quadrilateral.        Vec4[] centerOut = new Vec4[1];        Vec4[] axisOut = new Vec4[1];        double[] radiusOut = new double[1];        if (!this.computeCircleThroughPoints(p0, p1, p2, centerOut, axisOut, radiusOut))        {            // If the computation failed, then two of the points are coincident. Fall back to creating a bounding            // cylinder based on the vertices of the sector. This bounding cylinder won't be as tight a fit, but            // it will be correct.            return this.computeBoundsFromSectorVertices(sector, minHeight, maxHeight);        }        Vec4 centerPoint = centerOut[0];        Vec4 axis = axisOut[0];        double radius = radiusOut[0];        // Compute the sector's lowest projection along the cylinder axis. We test opposite corners of the sector        // using minHeight. One of these will be the lowest point in the sector.        Vec4 extremePoint = this.computePointFromPosition(sector.getMinLatitude(), sector.getMinLongitude(), minHeight);        double minProj = extremePoint.subtract3(centerPoint).dot3(axis);        extremePoint = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMaxLongitude(), minHeight);        minProj = Math.min(minProj, extremePoint.subtract3(centerPoint).dot3(axis));        // Compute the sector's highest projection along the cylinder axis. We only need to use the point at the        // sector's centroid with maxHeight. This point is guaranteed to be the highest point in the sector.        LatLon centroid = sector.getCentroid();        extremePoint = this.computePointFromPosition(centroid.getLatitude(), centroid.getLongitude(), maxHeight);        double maxProj = extremePoint.subtract3(centerPoint).dot3(axis);        Vec4 bottomCenterPoint = axis.multiply3(minProj).add3(centerPoint);        Vec4 topCenterPoint = axis.multiply3(maxProj).add3(centerPoint);        return new Cylinder(bottomCenterPoint, topCenterPoint, radius);    }    /**     * Compute the Cylinder that surrounds the equator, and has height defined by the sector's minumum and maximum     * latitudes (including maxHeight).     *     * @param sector               the sector to return the bounding cylinder for.     * @param minHeight            the minimum height to include in the bounding cylinder.     * @param maxHeight            the maximum height to include in the bounding cylinder.     *     * @return the minimal bounding cylinder in Cartesianl coordinates.     * @throws IllegalArgumentException if <code>sector</code> is null     */    @SuppressWarnings({"UnusedDeclaration"})    protected Cylinder computeBoundsFromSectorLatitudeRange(Sector sector, double minHeight, double maxHeight)    {        if (sector == null)        {            String msg = Logging.getMessage("nullValue.SectorIsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        Vec4 centerPoint = Vec4.ZERO;        Vec4 axis = Vec4.UNIT_Y;        double radius = this.getEquatorialRadius() + maxHeight;        // Compute the sector's lowest projection along the cylinder axis. This will be a point of minimum latitude        // with maxHeight.        Vec4 extremePoint = this.computePointFromPosition(sector.getMinLatitude(), sector.getMinLongitude(), maxHeight);        double minProj = extremePoint.subtract3(centerPoint).dot3(axis);        // Compute the sector's lowest highest along the cylinder axis. This will be a point of maximum latitude        // with maxHeight.        extremePoint = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMaxLongitude(), maxHeight);        double maxProj = extremePoint.subtract3(centerPoint).dot3(axis);        Vec4 bottomCenterPoint = axis.multiply3(minProj).add3(centerPoint);        Vec4 topCenterPoint = axis.multiply3(maxProj).add3(centerPoint);        return new Cylinder(bottomCenterPoint, topCenterPoint, radius);    }    /**     * Returns a cylinder that surrounds the specified height range in the zero-area sector. The returned cylinder     * won't be as tight a fit as <code>computeBoundsFromSectorQuadrilateral</code>.     *     * @param sector               the sector to return the bounding cylinder for.     * @param minHeight            the minimum height to include in the bounding cylinder.     * @param maxHeight            the maximum height to include in the bounding cylinder.     *     * @return The minimal bounding cylinder in Cartesian coordinates.     * @throws IllegalArgumentException if <code>sector</code> is null     */    protected Cylinder computeBoundsFromSectorVertices(Sector sector, double minHeight, double maxHeight)    {        if (sector == null)        {            String msg = Logging.getMessage("nullValue.SectorIsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        // Compute the top center point as the surface point with maxHeight at the sector's centroid.        LatLon centroid = sector.getCentroid();        Vec4 topCenterPoint = this.computePointFromPosition(centroid.getLatitude(), centroid.getLongitude(), maxHeight);        // Compute the axis as the surface normal at the sector's centroid.        Vec4 axis = this.computeSurfaceNormalAtPoint(topCenterPoint);        // Compute the four corner points of the sector with minHeight.        Vec4 southwest = this.computePointFromPosition(sector.getMinLatitude(), sector.getMinLongitude(), minHeight);        Vec4 southeast = this.computePointFromPosition(sector.getMinLatitude(), sector.getMaxLongitude(), minHeight);        Vec4 northeast = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMaxLongitude(), minHeight);        Vec4 northwest = this.computePointFromPosition(sector.getMaxLatitude(), sector.getMinLongitude(), minHeight);        // Compute the bottom center point as the lowest projection along the axis.        double minProj = southwest.subtract3(topCenterPoint).dot3(axis);        minProj = Math.min(minProj, southeast.subtract3(topCenterPoint).dot3(axis));        minProj = Math.min(minProj, northeast.subtract3(topCenterPoint).dot3(axis));        minProj = Math.min(minProj, northwest.subtract3(topCenterPoint).dot3(axis));        Vec4 bottomCenterPoint = axis.multiply3(minProj).add3(topCenterPoint);        // Compute the radius as the maximum distance from the top center point to any of the corner points.        double radius = topCenterPoint.distanceTo3(southwest);        radius = Math.max(radius, topCenterPoint.distanceTo3(southeast));        radius = Math.max(radius, topCenterPoint.distanceTo3(northeast));        radius = Math.max(radius, topCenterPoint.distanceTo3(northwest));        return new Cylinder(bottomCenterPoint, topCenterPoint, radius);    }    /**     * Computes the center, axis, and radius of the circle that circumscribes the specified points. If the points are     * oriented in a clockwise winding order, the circle's axis will point toward the viewer. Otherwise the axis     * will point away from the viewer. Values are returned in the first element of centerOut, axisOut, and radiusOut.     * The caller must provide a preallocted arrays of length one or greater for each of these values.     *     * @param p0        the first point.     * @param p1        the second point.     * @param p2        the third point.     * @param centerOut preallocated array to hold the circle's center.     * @param axisOut   preallocated array to hold the circle's axis.     * @param radiusOut preallocated array to hold the circle's radius.     *     * @return true if the computation was successful; false otherwise.     * @throws IllegalArgumentException if <code>p0</code>, <code>p1</code>, or <code>p2</code> is null     */    private boolean computeCircleThroughPoints(Vec4 p0, Vec4 p1, Vec4 p2, Vec4[] centerOut, Vec4[] axisOut,                                               double[] radiusOut)    {        if (p0 == null || p1 == null || p2 == null)        {            String msg = Logging.getMessage("nullValue.Vec4IsNull");            Logging.logger().severe(msg);            throw new IllegalArgumentException(msg);        }        Vec4 v0 = p1.subtract3(p0);        Vec4 v1 = p2.subtract3(p1);        Vec4 v2 = p2.subtract3(p0);        double d0 =  v0.dot3(v2);        double d1 = -v0.dot3(v1);        double d2 =  v1.dot3(v2);        double t0 = d1 + d2;        double t1 = d0 + d2;        double t2 = d0 + d1;        double e0 = d0 * t0;        double e1 = d1 * t1;        double e2 = d2 * t2;        double max_e = Math.max(Math.max(e0, e1), e2);        double min_e = Math.min(Math.min(e0, e1), e2);        double E = e0 + e1 + e2;        double tolerance = 1e-6;        if (Math.abs(E) <= tolerance * (max_e - min_e))            return false;        double radiusSquared = 0.5d * t0 * t1 * t2 / E;        // the three points are collinear -- no circle with finite radius is possible        if (radiusSquared < 0d)            return false;        double radius = Math.sqrt(radiusSquared);        Vec4 center = p0.multiply3(e0 / E);        center = center.add3(p1.multiply3(e1 / E));        center = center.add3(p2.multiply3(e2 / E));        Vec4 axis = v2.cross3(v0);        axis = axis.normalize3();        if (centerOut != null)            centerOut[0] = center;        if (axisOut != null)            axisOut[0] = axis;        if (radiusOut != null)            radiusOut[0] = radius;        return true;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -