设置世界风地图的缩放级别

时间:2011-05-11 19:53:17

标签: java worldwind

我正在尝试使用worldwind java设置图层,我想在地图上的特定地理位置渲染图标。我有那个工作,但我希望能够缩放到所有图标的位置。有一个简单的方法吗?我不确定从哪里开始..是否有现有的方法来放大一组点?

2 个答案:

答案 0 :(得分:9)

首先,你需要计算包含所有积分的扇区。 e.g。

Sector boundingSector = Sector.boundingSector(points);
//public static Sector boundingSector(Iterable<? extends LatLon> itrbl)

现在,这里是一些从ScankortDenmark示例中获取的代码来计算您需要在屏幕上显示整个扇区的缩放:

// From ScankortDenmark example
public static double computeZoomForExtent(Sector sector)
{
    Angle delta = sector.getDeltaLat();
    if (sector.getDeltaLon().compareTo(delta) > 0)
        delta = sector.getDeltaLon();
    double arcLength = delta.radians * Earth.WGS84_EQUATORIAL_RADIUS;
    double fieldOfView = Configuration.getDoubleValue(AVKey.FOV, 45.0);
    return arcLength / (2 * Math.tan(fieldOfView / 2.0));
}

答案 1 :(得分:1)

在某些情况下,这个答案确实有效。但是,更好的解决方案必须考虑到水平视场(视场)并不总是固定在45.0度。它还需要考虑垂直视场。甚至必须考虑如何结束聚类的位置。意思是,这些职位的分布是东西方向还是北方和南方。地球的用户视图(WorldWindow)是否真的比高度更瘦。在计算所需的缩放级别以查看所有位置时,会考虑所有这些因素。我创建了这个静态方法来解释上面列出的所有位置。作为旁注,如果计算地球的实际平均半径,您的位置倾向于聚集而不是采用Earth.WGS84_EQUATORIAL_RADIUS,则可以略微提高精度。但这几乎可以忽略不计,所以我把这部分留在这里。

/**
 * Calculates the altitude in meters needed to view all of the given points.
 * This method is safe for any window sizing configurations. If the
 * WorldWindor arg is null then a static max altitude value of 1,0667,999
 * meters is returned. if the WorldWindow is good but the list of Positions
 * is null or empty then the current zoom level of the WorldWindow is
 * returned. If the list of positions cannot all be seen on the globe
 * because some positions are on the other side of the globe then a static
 * max altitude value of 1,0667,999 meters is returned.
 *
 * @param positions
 *            - a list of positions wanted to view
 * @return the altitude in meters needed to view all of the given points.
 */
public static double getZoomAltitude(List<Position> positions, WorldWindow wwd) {
    double zoom = 10667999;
    if (wwd != null) {
        // Gets the current zoom as a fail safe to return
        BasicOrbitView orbitView = (BasicOrbitView) wwd.getView();
        zoom = orbitView.getZoom();

        // zoom is in meters and and is limited the max zoom out to 10,667,999 meters
        int MAX_ZOOM = 10667999;

        if (positions != null && !positions.isEmpty()) {
            Sector sector = Sector.boundingSector(positions);
            if (sector != null) {

                // This calculation takes into account the window sizing configuration of the map in order to accurately 
                // display the list of positions.
                double meanRadius = Earth.WGS84_EQUATORIAL_RADIUS;

                // Next we must calculate the zoom levels for both delta latitude viewing and delta longitude viewing.
                // generally, a group of positions that spread out more Longitudenal viewing (wider viewing width) 
                // holds a constant 45.0 degree field of view (FOV). The horizontal FOV can be changed so this input 
                // must handle dynamically as well. The latitudenal (positon group runs more East to West then North and South) 
                // position group have a dynamic FOV that changes depending on the users sizing of the map. These have 
                // to be handled any time the group of positions has a greater delta latitude than delta longitude. 
                // Also if the user has a skinny map this will effect the output calculation and must be handled. 
                // Here we take all the dynamic variables into account for both types of possibilities and choose 
                // the larger zoom level of them. 
                int deltaLon = new BigDecimal(sector.getDeltaLon().radians * meanRadius).intValue();
                int deltaLat = new BigDecimal(sector.getDeltaLat().radians * meanRadius).intValue();
                System.out.println("deltaLonAL Wider: " + deltaLon + "\tdeltaLatAL Taller: " + deltaLat);

                double horizontalFOV = orbitView.getFieldOfView().getDegrees();
                double verticalFOV = ViewUtil.computeVerticalFieldOfView(orbitView.getFieldOfView(),
                        orbitView.getViewport()).getDegrees();

                double lonZoomLevel = new BigDecimal((deltaLon / 2.0) / (Math.tan(horizontalFOV / 2.0))).intValue();
                double latZoomLevel = new BigDecimal((deltaLat / 2.0)
                        / (Math.tan(Math.toRadians(verticalFOV) / 2.0))).intValue();
                System.out
                        .println("LonZoomLevel Wider: " + lonZoomLevel + "\tLatZoomLevel Taller: " + latZoomLevel);

                double zoomLevel = Math.max(lonZoomLevel, latZoomLevel);
                System.out.println("zoomLevel meters: " + zoomLevel + "\tfeet: "
                        + new BigDecimal(zoomLevel * 3.2808));

                // zoom is the altitude measured in meters to view a given area calculated to fit the viewing
                // window edge to edge. A buffer is needed around the area for visual appeal. The bufferedZoom
                // is a calculated linear equation (y = 1.0338x + 96177 where R² = 1) It gives the same buffer
                // boundary around a group of position depending on the calculated zoom altitude.
                double bufferedZoom = 1.0338 * zoomLevel + 96177;
                zoom = new BigDecimal(bufferedZoom).intValue();

                if (zoom > MAX_ZOOM) {
                    zoom = MAX_ZOOM;
                    System.out.println("MAX_ZOOM applied");
                }
            }
        } else {
            System.out.println("getZoomAltitude method cannot calculate the zoom because the points passed in was null and the current zoom was returned.");
        }
    }
    return zoom;
}