简体   繁体   English

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

[英]Setting the zoom level of worldwind map

I am trying to setup a layer using worldwind java and i want to render icons on the map at their specific geo locations. 我正在尝试使用worldwind java设置图层,我想在地图上的特定地理位置渲染图标。 I have that working but i want to be able to zoom to where all the icons are. 我有那个工作,但我希望能够缩放到所有图标的位置。 Is there an easy way to do that? 有一个简单的方法吗? Im not really sure where to start.. Are there existing methods for zooming in on a group of points? 我不确定从哪里开始..是否有现有的放大一组点的方法?

First you need to calculate the Sector containing all of your points. 首先,您需要计算包含所有点的扇区。 eg 例如

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

Now here's some code taken from ScankortDenmark example to calculate the zoom you need to fit the whole sector on screen: 现在这里是一些从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));
}

182Much's answer does work under under some conditions. 182在某些情况下,这个答案确实有效。 However, a better solution must take into account that the Horizontal FOV (Field of View) is not always fixed at 45.0 degrees. 但是,更好的解决方案必须考虑到水平视场(视场)并不总是固定在45.0度。 It also needs to take into account the Vertical FOV. 它还需要考虑垂直视场。 Even how the positions end of clustering has to be taken into account. 甚至必须考虑如何结束聚类的位置。 Meaning, do the positions spread out more East to West or North and South. 意思是,这些职位的分布是东西方向还是北方和南方。 Is the users view of the globe (WorldWindow) actually skinnier then the height. 地球的用户视图(WorldWindow)是否真的比高度更瘦。 All of these factors come into account when calculating the needed zoom level to view all positions. 在计算所需的缩放级别以查看所有位置时,会考虑所有这些因素。 I created this static method to account for all of the listed positions above. 我创建了这个静态方法来解释上面列出的所有位置。 As a side note, you can have slightly better precision if you calculate the actual mean radius of the Earth for where your positions tend to cluster instead of taken Earth.WGS84_EQUATORIAL_RADIUS. 作为旁注,如果计算地球的实际平均半径,您的位置倾向于聚集而不是采用Earth.WGS84_EQUATORIAL_RADIUS,则可以略微提高精度。 But this is almost negligible so I leave that part out here. 但这几乎可以忽略不计,所以我把这部分留在这里。

/**
 * 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM