WebGIS开发过程中会遇到这样一种情况:需要使用OpenLayers加载一个未校准的CAD导出的位图;并且还需要通过经纬度坐标数据在这个位图上做一些标记,还需要能通过在OpenLayers取得的图上要素的像素坐标获知实际的经纬度。

总结起来就是两个需求:

加载位图
经纬度坐标与像素坐标互转

分析:

由于从CAD导出的位图并不带有定位信息,所以需要通过仿射变换将图上的像素坐标转换到地理坐标。

即:(左边为某厂的卫星地图,右边为该厂的CAD导出位图,最终实现效果就是用OpenLayers加载位图,并实现坐标转换)

关于求解仿射变换的过程请见这里。主要的算法思想如下:

Arcgis中就带有了仿射变换的计算模块,OpenLayers没有仿射变换计算的能力,所以使用math.js这个数学库来进行实现。
代码:

算法在上面的截图已经有了,直接用相应的API实现就好:

        //定义仿射变换函数function affineTransform(point, from, to) {if (from.length != to.length) return;//根据参数构造仿射变换所需的矩阵            var X = [];var Y = [];var I = [];var U = [];var V = [];from.forEach((item, index) => {X.push(item[0]);Y.push(item[1]);I.push(1);U.push([to[index][0]])V.push([to[index][1]])})//开始最小二乘法的计算过程var XYIt = [X, Y, I];var resultINV = math.inv(math.multiply(XYIt, math.transpose(XYIt)))var resultMulti = math.multiply(resultINV, XYIt);var vec1 = math.multiply(resultMulti, U)var vec2 = math.multiply(resultMulti, V)//使用vec1和vec2计算转换后的坐标return [vec1[0][0] * point[0] + point[1] * vec1[1][0] + vec1[2][0], vec2[0][0] * point[0] + point[1] * vec2[1][0] + vec2[2][0]]}

CAD导出的位图直接使用ImageStatic加载,并自定义一个像素坐标系:

        //定义地图的像素坐标四至var extent = [0, 0, 4000, 2000];//定义地图的投影坐标系,像素坐标var projection = new ol.proj.Projection({code: 'factory-image',units: 'pixels',extent: extent});//初始化地图var map = new ol.Map({layers: [new ol.layer.Image({source: new ol.source.ImageStatic({url: './data/10-9.png',projection: projection,imageExtent: extent})})],target: 'map',view: new ol.View({projection: projection,center: ol.extent.getCenter(extent),zoom: 2,maxZoom: 8})});

概略分别获取图上厂区四角的坐标,图片像素坐标是用potoshop量取的,经纬度坐标是在google地图上拾取的:

        var upperLeft = [119.071450, 39.309006];var lowerLeft = [119.074536, 39.305893];var upperRight = [119.075858, 39.311641];var lowerRight = [119.078934, 39.308527];var upperLeftPixel = [959, 1897];var lowerLeftPixel = [959, 112];var upperRightPixel = [2924, 1897];var lowerRightPixel = [2924, 112];

包括使用旗杆坐标打点测试的完整代码:

<!DOCTYPE html>
<html><head><title>厂区地图计算</title><link rel="stylesheet" href="https://openlayers.org/en/v3.20.1/css/ol.css" type="text/css"><script src="https://unpkg.com/mathjs@6.2.3/dist/math.js"></script><script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script></head>
<style></style><body><div id="map" class="map"></div><script>//定义仿射变换函数function affineTransform(point, from, to) {if (from.length != to.length) return;var X = [];var Y = [];var I = [];var U = [];var V = [];from.forEach((item, index) => {X.push(item[0]);Y.push(item[1]);I.push(1);U.push([to[index][0]])V.push([to[index][1]])})var XYIt = [X, Y, I];var resultINV = math.inv(math.multiply(XYIt, math.transpose(XYIt)))var resultMulti = math.multiply(resultINV, XYIt);var vec1 = math.multiply(resultMulti, U)var vec2 = math.multiply(resultMulti, V)return [vec1[0][0] * point[0] + point[1] * vec1[1][0] + vec1[2][0], vec2[0][0] * point[0] + point[1] * vec2[1][0] + vec2[2][0]]}//Google坐标var upperLeft = [119.071450, 39.309006];var lowerLeft = [119.074536, 39.305893];var upperRight = [119.075858, 39.311641];var lowerRight = [119.078934, 39.308527];var upperLeftPixel = [959, 1897];var lowerLeftPixel = [959, 112];var upperRightPixel = [2924, 1897];var lowerRightPixel = [2924, 112];//定义地图的像素坐标四至var extent = [0, 0, 4000, 2000];//定义地图的投影坐标系,像素坐标var projection = new ol.proj.Projection({code: 'factory-image',units: 'pixels',extent: extent});//初始化地图var map = new ol.Map({layers: [new ol.layer.Image({source: new ol.source.ImageStatic({url: './data/10-9.png',projection: projection,imageExtent: extent})})],target: 'map',view: new ol.View({projection: projection,center: ol.extent.getCenter(extent),zoom: 2,maxZoom: 8})});//这里用旗杆的坐标演示坐标转换的使用var flagPole = [119.077710, 39.309195];var flagPolePixel = affineTransform(flagPole, [upperLeft, lowerLeft, upperRight, lowerRight], [upperLeftPixel, lowerLeftPixel, upperRightPixel, lowerRightPixel])var p=affineTransform(flagPolePixel, [upperLeftPixel, lowerLeftPixel, upperRightPixel, lowerRightPixel],[upperLeft, lowerLeft, upperRight, lowerRight])console.log(flagPole);console.log(p);var f = new ol.Feature(new ol.geom.Point(flagPolePixel));var vSource = new ol.source.Vector();var vLayer = new ol.layer.Vector({source: vSource})vSource.addFeature(f);f.setStyle(new ol.style.Style({image: new ol.style.Icon({src: './data/icon.png',anchor: [0.5, 1],scale: 0.3}),}))map.addLayer(vLayer);map.getView().fit(extent, map.getSize())map.render()</script>
</body></html>

这里使用旗杆的坐标进行了转换和逆转换,并在console里输出,结果如下:

更多请见:http://www.mark-to-win.com/tutorial/175096.html

通过 OpenLayers 加载CAD导出位图 和 math.js 构造的仿射变换实现地理坐标系到任意CAD图上像素坐标系的互转相关推荐

  1. vue openlayers 加载高德地图等 gcj02 的图层偏移问题

    vue openlayers 加载高德地图等 gcj02 的图层偏移问题 这个问题是在使用 openlayers 地图引擎加载高德地图或者是谷歌地图都会遇到的问题,所以说呢这篇博文稍微说一下解决办法. ...

  2. Vue+Openlayers加载Geoserver发布的TileWMS后更换shp数据源的流程

    场景 Vue中使用Openlayers加载Geoserver发布的TileWMS: Vue中使用Openlayers加载Geoserver发布的TileWMS_BADAO_LIUMANG_QIZHI的 ...

  3. Android中使用WebChromeClient显示Openlayers加载本地GeoJson文件显示地图(跨域问题解决)

    场景 Openlayers中加载GeoJson文件显示地图: Openlayers中加载GeoJson文件显示地图_BADAO_LIUMANG_QIZHI的博客-CSDN博客 上面加载显示GeoJso ...

  4. Vue中使用Openlayers加载Geoserver发布的TileWMS时单击获取shp文件的坐标信息

    场景 Vue中使用Openlayers加载Geoserver发布的TileWMS: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/ ...

  5. Vue中使用Openlayers加载Geoserver发布的TileWMS

    场景 Openlayers下载与加载geoserver的wms服务显示地图: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114 ...

  6. Vue中使用Openlayers加载Geoserver发布的ImageWMS

    场景 Openlayers下载与加载geoserver的wms服务显示地图: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114 ...

  7. Vue中使用Openlayers加载OSM(Open Street Map)显示街道地图

    场景 Openlayers下载与加载geoserver的wms服务显示地图: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114 ...

  8. WebGIS——Openlayers加载图层

    Openlayers加载图层 一.创建Html文件并在body中放入一个Div作为地图显示的容器 <body><div id="map" class=" ...

  9. OpenLayers 加载天地图模糊的问题 OpenLayers 地图缩放模糊

    openlayers 加载天地图模糊的问题,OpenLayers 地图缩放几次之后模糊 2021年12月20日 纠正模糊原因: 地图加载瓦片实质上还是图片,一般来说是256&256,将一个静态 ...

最新文章

  1. Unity SRP自定义渲染管线 -- 1.Custom Pipeline
  2. Google Go Programming In Eclipse
  3. ajax post 提交无法进入controller 请求200
  4. TimeQuest就一定要搞定——时序分析基本公式
  5. Hadoop学习笔记(五):MapReduce的类型与格式
  6. Linux:init 0~6
  7. 【Python】9×9数独计算器
  8. ajax前后端通信的头部消息之请求头与响应头
  9. 高质量单幅图片运动去模糊
  10. 【python】获取当前时间(年月日时分秒)
  11. 基于高通410c开发板,开发android端家庭控制中心APP(1)
  12. 关闭华为的触摸屏+查看自己电脑主板型号顺便推荐了个全能检测工具+进入华为的bios看看
  13. 怎么搭建自己的播客_如何开始自己的播客(逐步)
  14. [HNOI2017]影魔
  15. 区块链之区块结构-学习笔记
  16. Webix UI JavaScript 10.0.6 Crack
  17. [Weex 学习]Weex Debug模式
  18. python制表符是什么
  19. matlab误差分析报告,误差理论与数据处理实验报告
  20. 分发文件到服务器,Linux 把文件分发到不同服务器

热门文章

  1. HTML期末大学生网页设计作业——奇恩动漫HTML (1页面) HTML+CSS+JS网页设计期末课程大作业
  2. 【LeetCode】496. 下一个更大元素 I 【单调栈】
  3. error:2006D080:BIO routines:BIO_new_file:no such file
  4. 中间人攻击——ettercap的使用
  5. frameset的用法
  6. 公司成立三年即上市 网游速度获资本垂青
  7. 从Unity导出FBX到网页,实现一个模型多个动作动画
  8. Linux环境下连连看游戏代码,C++实现连连看游戏核心代码
  9. UICC 之 USIM 详解全系列——常用命令详解与实例说明
  10. 协程的原理及协程在高并发服务中的应用