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

一、 前言

利用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>中引入,因为谷歌浏览器的同源策略。
这里写图片描述

底图的范围大小 以及栅格的分辨率的设置,即:
这里写图片描述

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

这里写图片描述

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值