Android OpenLayers移动屏幕和矢量图层重复地图

Android OpenLayers移动屏幕和矢量图层重复地图,android,openlayers,openstreetmap,Android,Openlayers,Openstreetmap,我正在使用Openlayers.mobile.js库在Android应用程序中嵌入OSM 屏幕尺寸问题 我遇到的第一个问题是,当我缩放到0级时,例如在纵向,而不是显示整个行星地图并用黑色填充屏幕的额外顶部和底部,它看起来像是做了相反的事情:垂直缩放到最大程度并剪切地图的额外水平边 如果我设置maxExtent(-180,-90180,90),则贴图与屏幕具有相同的相对位置,并且不允许我移动贴图,因此无法访问额外的两条边 这就像是,如果它考虑屏幕尺寸是相反的,但如果我在横向中这样做,我只会得到屏幕

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

屏幕尺寸问题

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

如果我设置maxExtent(-180,-90180,90),则贴图与屏幕具有相同的相对位置,并且不允许我移动贴图,因此无法访问额外的两条边

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

我的理想愿望是把所有的地图都放在屏幕上,用黑色填充所有额外的屏幕。在这两种情况下,风景和肖像

重复问题

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

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

注意:当多边形位于两个贴图之间时,点只是移动的,如果不是移动的整个多边形的话。我需要告诉构造器多边形是通过接近度而不是通过单个贴图中的点来闭合的。因此,点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>

OpenLayers Mobile
html,正文{
保证金:0;
填充:0;
身高:100%;
宽度:100%;
}
@仅介质屏幕和(最大宽度:600px){
html,正文{
身高:117%;
}
}
#地图{
宽度:100%;
位置:绝对位置;
身高:100%;
}
.Olcontrolattribute{
位置:绝对位置;
字体大小:10px;
底部:0!重要;
右:0!重要;
背景:rgba(0,0,0,0.1);
字体系列:Arial;
填充物:2px4px;
边界半径:5px0;
}
#标题、#标签、#简短描述{
显示:无;
}

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

对于屏幕尺寸:

使用和不使用map 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]);
}
}
我们必须意识到,这些函数并不完美,输入点集不以某个极端开始非常重要(不会检测到日期线的跳变)


如果有人不同意其中一些陈述或对这些函数有意见或建议,请毫不犹豫地对答案进行评论。

谢谢。在OL 5中,您可能不需要拆分闭合多边形,您只需将某些点的经度调整为>180或<-180即可。这样,它可以绘制正确的多边形s、 但是,这种方法不适用于开放多边形,因此仍然需要使用额外的分段技巧

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