欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

独立坐标的栅格瓦片与矢量(geoJson)地图在Leaflet下加载

程序员文章站 2024-03-25 11:24:10
...

一、 前言

利用web加载栅格与矢量地图,大多是基于WGS84 ,或者 web墨卡托。但是在实际过程中,也存在非WGS 84的独立地理坐标,如:游戏地图、CAD作图….我查看了许多开源的地图map容器,leaflet (https://leafletjs.com/) 与 openLayers (http://openlayers.org/) 支持这种独立坐标,窗体的话可以利用sharpMap(https://github.com/SharpMap/SharpMap)。

二、准备工作

本案例要讲的是CAD作图后如何与栅格底图配准并展示在Leaflet。如果只是单纯的游戏地图,可以参考 https://leafletjs.com/examples/crs-simple/crs-simple.html

数据源:①.栅格底图(可以利用地图下载器)合并成一张大图用于配准,之后可以利用MapTiler转成瓦片或者用GDAL的gdal2tiles.py

  ②.独立坐标矢量图层从CAD出图后,利用ArcEngine 或者GDAL转成shp 格式。

三、步骤

3.1).首先在SharpMap窗体中对两个图层进行配准。
        ①可以通过ArcEngine提供的方法(网上查找)。
        ②还可以自己写仿射变换,然后重采样,具体利用的是Emgu.CV.CvInvoke.GetAffineTransform 方法,但是发现效果没有AE的好。

3.2)再利用gdal 将shp矢量转geoJson,将配准后的栅格大图转瓦片。

3.3)此时将两个在Leaflet上加载,其中投影需要利用L.CRS.Simple,加载geoJson 利用L.SvgScaleOverlay() (http://bl.ocks.org/Sumbera/7e8e57368175a1433791),栅格瓦片利用 L.tileLayer。

3.4)贴上 Leaflet 的代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>栅格and矢量</title>

    <link rel="stylesheet" href="http://www.sumbera.com/gist/js/leaflet/svg/scaled/leaflet.css" />

    <style>
        body {
            margin: 0px;
        }
        #map {
            position: absolute;
            height: 100%;
            width: 100%;

        }
    </style>
</head>
<body>

    <!-- Base libraries-->
    <script src="http://www.sumbera.com/gist/js/leaflet/svg/scaled/d3-3.5.5.min.js"></script>
    <script src="http://www.sumbera.com/gist/js/leaflet/svg/scaled/leaflet.js"></script>

    <script src="L.SvgScaleOverlay.js"></script> <!--http://bl.ocks.org/Sumbera/7e8e57368175a1433791 -->
    <script src="test.js" charset="utf-8"></script>  <!-- 该JS 是geoJson对象数组-->
    <div id="map">
    </div>
    <div id="tooltip" style="width:230px; height:100px;">
     </div>


    <script>


    var mapExtent = [533435.6179770336, 3120955.497304902, 535565.1120320936,3124568.6378654544];  //minX minY maxX maxY
    var mapMinZoom = 0;
    var mapMaxZoom = 4;
    var mapMaxResolution = 1.0605050075;  //你的图像的分辨率 (在tfw 文件中的第一行) (tfw 文件是tif 的地理格式文件)
    var mapMinResolution = Math.pow(2, mapMaxZoom) * mapMaxResolution;;
    var tileExtent = [533435.6179770336, 3120955.497304902, 535565.1120320936,3124568.6378654544];
    var crs = L.CRS.Simple;
    crs.transformation = new L.Transformation(1, -tileExtent[0], -1, tileExtent[3]);
    crs.scale = function(zoom) {
        return Math.pow(2, zoom) / mapMinResolution;
    };
    crs.zoom = function(scale) {
        return Math.log(scale * mapMinResolution) / Math.LN2;
    };
    var layer;
    var lmap = new L.Map('map', {
        maxZoom: 10,
        minZoom: mapMinZoom,
        crs: crs
    });
     lmap.fitBounds([
        crs.unproject(L.point(mapExtent[2], mapExtent[3])),
        crs.unproject(L.point(mapExtent[0], mapExtent[1]))
    ]);
 var layer;
    layer = L.tileLayer('tile/{z}/{x}/{y}.png', { 
        minZoom: mapMinZoom,
        maxZoom: 10,
        maxNativeZoom: mapMaxZoom,
        attribution: 'Rendered with <a href="https://leafletjs.com/">Leaflet</a>',
        noWrap: false,

        tms: false
    });
 lmap.addLayer(layer);

            var circles;

            var svgOverlay = L.SvgScaleOverlay();
            var radius = 2;

               lmap.on("click",function(e){
                console.log(e);

              });
            //------------------------------------------------------------
            var datas =[];
            for(var i = 0;i<myGeoJson.features.length;i++){ //myGeoJson是我geoJson对象的名字,我的geoJson是地形图
                 datas.push( myGeoJson.features[i].geometry.coordinates); // 
               }
            <!-- window.load = function(){ -->
               <!-- console.log( euCountries); -->
               <!-- for(var i = 0;i<euCountries.features.length;i++){ -->
                 <!-- datas.push( euCountries.features[i].geometry.coordinates); -->
               <!-- } -->

            <!-- } -->

            svgOverlay.onInitData = function () {
                if (!circles) {
                    var g = d3.select(this._g);
                    circles = g.selectAll("polyline")
                                    .data(datas)
                                    .enter().append('polyline');
                    // -- opacity based on grouping optimization in point data
                    circles.attr('stroke','blue');
                    circles.attr('stroke-width','1');
                    //circles.style("fill-opacity", 0.8);
                    circles.style("fill", "none");

                }


                circles.each(function (d) {
                    var elem = d3.select(this);
                    var points = [];
                    for(var i=0; i<d.length;i++){
                    try{
                        var point = lmap.project(L.latLng(new L.LatLng(d[i][1], d[i][0])))._subtract(lmap.getPixelOrigin());
                    var svgPoint =  svgOverlay._svg.createSVGPoint();
                    svgPoint.x = point.x; svgPoint.y = point.y;
                    elem[0][0].points.appendItem(svgPoint);

                    }catch(err){
                     console.log(err);

                    }
                    }
                })
            };

            svgOverlay.onScaleChange = function (scaleDiff) {
                if (scaleDiff > 0.5) {
                    var newRadius = radius * 1 / scaleDiff;
                    //newRadius  = crs.scale(scaleDiff);
                    var currentRadius = d3.select('polyline').attr("stroke-width");
                    if (currentRadius != newRadius) {
                        d3.selectAll("polyline").attr('stroke-width', newRadius);
                    }
                }

            }


            lmap.addLayer(svgOverlay);
            /***********************/




    </script>
</body>

</html>

其中 需要自行设置的是①.geoJson文件的加载。
                                     ②.栅格图像的范围大小与分辨率大小。
我的geoJson 文件用的是JS 加载方式 在<head>中引入,因为谷歌浏览器的同源策略。
独立坐标的栅格瓦片与矢量(geoJson)地图在Leaflet下加载

底图的范围大小 以及栅格的分辨率的设置,即:
独立坐标的栅格瓦片与矢量(geoJson)地图在Leaflet下加载

这些参数都可以在下图的tfw文件中计算而得,tfw不懂的请自行google。

独立坐标的栅格瓦片与矢量(geoJson)地图在Leaflet下加载