【问题标题】:OpenLayers mobile screen and reppeating map with vector layersOpenLayers 移动屏幕和带有矢量图层的重复地图
【发布时间】:2014-07-22 14:39:40
【问题描述】:

我正在使用 Openlayers.mobile.js 库将 OSM 嵌入到 Android 应用程序中。

屏幕尺寸问题

我遇到的第一个问题是,当我缩放到 0 级时,例如纵向,而不是显示整个星球地图并在屏幕的额外顶部和底部填充黑色,看起来它做的相反: 垂直缩放到最大范围并剪切地图的额外水平边。

如果我设置 maxExtent(-180,-90,180,90) 地图与屏幕的相对位置相同,并且它不允许我移动地图,因此无法访问额外的两个边。

就像如果它正在考虑屏幕尺寸是相反的,但如果我在横向上这样做,我只会在屏幕上得到地图的中心部分。

我的理想愿望是将所有地图都显示在屏幕上,并用黑色填充所有额外的屏幕。在这两种情况下,横向和纵向。

重复问题

由于我无法正确修复地图的 maxExtent,因此在水平平移时它会开始重复。我使用动态绘制多边形的矢量图层。当用户移动地图时,有时它会将多边形的一些点移动到 x+360º,因此,当关闭多边形时,它会显示出奇怪的形状。 (它用 x 点和 x+360 点的混合来闭合多边形。

有没有办法告诉矢量图层我希望所有点都是最接近的点,然后他可以决定整个多边形应该在 x 还是 x+360? 有没有办法阻止地图重复或以与地图重复相同的方式重复矢量图层(允许在地图的两个位置(x 和 x+360º)显示相同的国家/多边形?

注意:当多边形位于两个地图之间时,点只会移动,如果不是,则移动整个多边形。我需要告诉构造函数 Polygon,多边形是通过邻近度而不是单个地图中的点来关闭的。因此,点 p1=(-179,0) 和 p2=(179,0) 应该关闭而不经过点 (0,0) 但经过点 (180,0)=(-180,0) .

一些代码

Mobile.js:

// initialize map when page ready
var map;

// Get rid of address bar on iphone/ipod
var fixSize = function() {
    window.scrollTo(0,0);
    document.body.style.height = '100%';
    if (!(/(iphone|ipod)/.test(navigator.userAgent.toLowerCase()))) {
        if (document.body.parentNode) {
            document.body.parentNode.style.height = '100%';
        }
    }
};
setTimeout(fixSize, 700);
setTimeout(fixSize, 1500);

    var init = function () {
    // create map
    map = new OpenLayers.Map({
        div: "map",
        theme: null,
        numZoomLevels: 18,
        controls: [
            new OpenLayers.Control.TouchNavigation({
                dragPanOptions: {
                    enableKinetic: true
                }
            })
        ],
        layers: [
            new OpenLayers.Layer.OSM("OpenStreetMap", null, {
                transitionEffect: 'resize'
            })
        ],
        center: new OpenLayers.LonLat(0, 0),
        zoom: 0
    });
};

index.html->周期绘制函数:

    //Stations      
    if(Math.abs(sc_altitude-sc_altitude_tmp)>sc_altitude_step){
        stations_area_layer.removeAllFeatures();
        for (var arrayIndex in station_areas){
            /*
            var radius = Rt*Math.sin(Math.acos(Rt/(Rt+sc_altitude-stations[arrayIndex].ellipsoid_elevation)));

            var circle = OpenLayers.Geometry.Polygon.createRegularPolygon(
                new OpenLayers.Geometry.Point(stations[arrayIndex].longitude, stations[arrayIndex].latitude).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),
                radius,
                30 
            );

            //circle.transform(new OpenLayers.Projection("EPSG:4258"), map.getProjectionObject());
            var station_feature = new OpenLayers.Feature.Vector(circle, null, station_area_style);
            stations_area_layer.addFeatures([station_feature]);
            */
            var areaPoints = [];
            for (var i in station_areas[arrayIndex].points) {
                var coord = station_areas[arrayIndex].points[i];
                var point = new OpenLayers.Geometry.Point(coord.longitude, coord.latitude);
                // transform from WGS 1984 to Spherical Mercator
                point.transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
                areaPoints.push(point);
            }               
            areaPoints.push(areaPoints[0]);

            var linearRing = new OpenLayers.Geometry.LinearRing(areaPoints);
            var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
            var polygonFeature = new OpenLayers.Feature.Vector(geometry, null, station_area_style);
            stations_area_layer.addFeatures([polygonFeature]);
        }

        sc_altitude_tmp = sc_altitude;
    }

index.html->head:

<head>
    <title>OpenLayers Mobile</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <link rel="stylesheet" href="theme/default/style.css" type="text/css">
    <link rel="stylesheet" href="theme/default/style.mobile.css" type="text/css">
<script type='text/javascript' src="interface.js"></script>
<!--<script src="http://www.openlayers.org/api/OpenLayers.js"></script>-->
<script src="OpenLayers.mobile.js"></script>
    <script src="mobile.js"></script>

<script type="text/javascript" src="proj4js/proj4.js"></script>
<script type="text/javascript" src="greatCircle.js"></script>
<script type="text/javascript" src="greatcirclemod.js"></script>
<SCRIPT type="text/javascript" src="proj4js/data/tmerc.js"></SCRIPT>
<SCRIPT type="text/javascript" src="proj4js/data/merc.js"></SCRIPT>
<SCRIPT type="text/javascript" src="proj4js/data/EPSG31466.js"></SCRIPT>
<SCRIPT type="text/javascript" src="proj4js/data/EPSG31467.js"></SCRIPT>
<SCRIPT type="text/javascript" src="proj4js/data/EPSG900913.js"></SCRIPT>
<!--<script type="text/javascript" src="javascript/counter_orthodrome.js"></script>-->
<style>
        html, body {
            margin  : 0;
            padding : 0;
            height  : 100%;
            width   : 100%;
        }
        @media only screen and (max-width: 600px) {
            html, body {
                height  : 117%;
            }
        }
        #map {
            width    : 100%;
            position : absolute;
            height   : 100%;
        }
        .olControlAttribution {
            position      : absolute;
            font-size     : 10px;
            bottom        : 0 !important;
            right         : 0 !important;
            background    : rgba(0,0,0,0.1);
            font-family   : Arial;
            padding       : 2px 4px;
            border-radius : 5px 0 0 0;
        }
        #title, #tags, #shortdesc {
            display: none;
        }
    </style>
</head>

【问题讨论】:

    标签: android openlayers openstreetmap


    【解决方案1】:

    由于没有答案,我将解释我的发现和解决方法:

    对于屏幕尺寸:

    地图在不使用地图 wrappingDateLine 时有不同的扩展。 该地图具有固定的最大缩放级别(来自图块提供商)。此缩放级别未考虑屏幕边界或像素密度,因为智能手机中的缩放级别 1 与平板电脑中的缩放 1 完全不同。没有简单的方法让地图始终适合任何设备的屏幕。

    使用 setMaxResolution 和 MinResolution 可能会改善这种行为。

    对于层的重复:

    现在我没有换行日期,但我认为我的解决方法适用于所有情况:

    我需要一种方法来区分多边形是否包含在某些极点内部以及哪个极点。对我来说幸运的是,我有一种方法可以使用为多边形生成点的同一库来区分它。

    有了这个区别,我可以创建两个不同的函数,它们将以不同的方式运行:

    对于封闭的多边形:

    想法是检测经度符号的变化,丢弃地图中间(0º)的符号变化,并在检测跳跃时交替填充两个点数组。此外,在每次检测到跳跃时,我们将通过选择经度 -180/180 和两个纬度之间的平均值(该点之前和之后)来添加部分多边形的限制点。

    我们最终得到了两个可用于构建多边形的数组。在下面的函数中,arrayIndex 对应一个“站”数组的索引,每个站包含一组点来创建一个多边形。

    function paintClosedArea(arrayIndex){
    var areaFirst = [];
    var areaSecond = [];
    var area_tmp_long = 0, area_tmp_lat = 0;
    var first = true;
    for (var i in station_areas[arrayIndex].points) {
        var coord = station_areas[arrayIndex].points[i];
        var point = new OpenLayers.Geometry.Point(
                            coord.longitude, 
                            coord.latitude
            ).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
    
        if((i!=0) && ((coord.longitude*area_tmp_long)<0) && (Math.abs(coord.longitude)>90.0) && (area_tmp_long+coord.longitude<90.0)){
            var avg_lat = (coord.latitude+area_tmp_lat)/2;
            if(coord.longitude > 0)
                var new_lon = -179.999999;
            else
                var new_lon = 179.999999;
            if(first){
                areaFirst.push(new OpenLayers.Geometry.Point(new_lon, avg_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
                areaSecond.push(new OpenLayers.Geometry.Point(-new_lon, avg_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
                first=false;
            }else{
                areaFirst.push(new OpenLayers.Geometry.Point(-new_lon, avg_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
                areaSecond.push(new OpenLayers.Geometry.Point(+new_lon, avg_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
                first=true;
            }
        }
        area_tmp_lat = coord.latitude;
        area_tmp_long = coord.longitude;
    
        if(first){
            areaFirst.push(point);
        }else{
            areaSecond.push(point);
        }                   
    }               
    if(areaFirst.length>0){
        //areaFirst.push(areaFirst[0]);
        var linearRing = new OpenLayers.Geometry.LinearRing(areaFirst);
        var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
        var polygonFeature = new OpenLayers.Feature.Vector(geometry, null, station_area_style);
        stations_area_layer.addFeatures([polygonFeature]);
    }
    if(areaSecond.length>0){
        //areaSecond.push(areaSecond[0]);
        var linearRing = new OpenLayers.Geometry.LinearRing(areaSecond);
        var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
        var polygonFeature = new OpenLayers.Feature.Vector(geometry, null, station_area_style);
        stations_area_layer.addFeatures([polygonFeature]);
    }
    }
    

    对于开放的多边形,即内部包含一个极点的多边形,我们将只生成一个点数组(一个多边形),但在这种情况下,当我们检测到日期线的跳跃时,我们添加4分:两个极限-180,180,如果包含北极,两个角-180,90 180,90,如果包含南极,则-180,-90 180,-90。

    通过给这些额外的 4 个点,多边形将被封闭填充孔极,如果不是,结果不会包围极并且多边形会自行切割。

    在下面的函数中,arrayIndex和之前一样,如果多边形包含北极则type为1,如果多边形包含南极则type为2:

    function paintOpenArea(arrayIndex,type){
    var areaFirst = [];
    var areaSecond = [];
    var area_tmp_long = 0, area_tmp_lat = 0;
    var first = true;
    for (var i in station_areas[arrayIndex].points) {
        var coord = station_areas[arrayIndex].points[i];
        var point = new OpenLayers.Geometry.Point(
                            coord.longitude, 
                            coord.latitude
            ).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
    
        if((i!=0) && ((coord.longitude*area_tmp_long)<0) && (Math.abs(coord.longitude)>90.0) && (area_tmp_long+coord.longitude<90.0)){
            var avg_lat = (coord.latitude+area_tmp_lat)/2;
            if(coord.longitude > 0)
                var new_lon = -179.999999;
            else
                var new_lon = 179.999999;
            if(type == 1)
                var new_lat = 90.0;
            else
                var new_lat = -90.0;
    
            areaFirst.push(new OpenLayers.Geometry.Point(new_lon, avg_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
            areaFirst.push(new OpenLayers.Geometry.Point(new_lon, new_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
            areaFirst.push(new OpenLayers.Geometry.Point(-new_lon, new_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
            areaFirst.push(new OpenLayers.Geometry.Point(-new_lon, avg_lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()));
    
        }
        area_tmp_lat = coord.latitude;
        area_tmp_long = coord.longitude;
    
        areaFirst.push(point);                  
    }               
    if(areaFirst.length>0){
        //areaFirst.push(areaFirst[0]);
        var linearRing = new OpenLayers.Geometry.LinearRing(areaFirst);
        var geometry = new OpenLayers.Geometry.Polygon([linearRing]);
        var polygonFeature = new OpenLayers.Feature.Vector(geometry, null, station_area_style);
        stations_area_layer.addFeatures([polygonFeature]);
    }
    }
    

    循环调用前面两个函数的函数是:

    function drawStationsAreas(){
    if(Math.abs(sc_altitude-sc_altitude_tmp)>sc_altitude_step){
        stations_area_layer.removeAllFeatures();
        for (var arrayIndex in station_areas){
            if(station_areas[arrayIndex].type==0)
                paintClosedArea(arrayIndex);
            else
                paintOpenArea(arrayIndex,station_areas[arrayIndex].type);
    
        }
    
        sc_altitude_tmp = sc_altitude;
    }
    }
    

    我们必须意识到这些功能并不完美,并且输入的点集不是从极端之一开始非常重要(不会检测到日期线的跳跃)。

    如果有人不同意某些陈述或对这些功能有意见或建议,请不要犹豫,发表评论。

    【讨论】:

      【解决方案2】:

      谢谢你。在 OL 5 中,您可能不需要分割封闭的多边形,您只需将一些点的经度调整为 > 180 或

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-02-13
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2015-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多