Установка уровня масштабирования карты мира - PullRequest
5 голосов
/ 11 мая 2011

Я пытаюсь настроить слой, используя WorldWind Java, и я хочу, чтобы отображать значки на карте в определенном географическом положении. У меня это работает, но я хочу иметь возможность масштабировать туда, где находятся все иконки. Есть ли простой способ сделать это? Я не совсем уверен, с чего начать. Существуют ли способы увеличения группы точек?

Ответы [ 2 ]

9 голосов
/ 12 мая 2011

Сначала вам нужно вычислить Сектор, содержащий все ваши очки. например,

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 голос
/ 04 февраля 2016

182Мучный ответ работает при некоторых условиях.Однако лучшее решение должно учитывать, что горизонтальное поле зрения (поле зрения) не всегда фиксируется на 45,0 градусов.Также необходимо учитывать вертикальное поле зрения.Даже как позиции конца кластеризации должны быть приняты во внимание.Это означает, что позиции распределяются больше с востока на запад или с севера на юг.Является ли пользовательский вид глобуса (WorldWindow) на самом деле более тонким, чем высота.Все эти факторы учитываются при расчете необходимого уровня масштабирования для просмотра всех позиций.Я создал этот статический метод для учета всех перечисленных выше позиций.В качестве примечания, у вас может быть немного лучшая точность, если вы вычислите фактический средний радиус Земли, где ваши позиции имеют тенденцию к кластеризации, а не по взятой Земле. 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;
}
...