添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

总结起来就是两个需求:

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

由于从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>
    <title>厂区地图计算</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v3.20.1/css/ol.css" type="text/css">
    <script src="https://unpkg.com/[email protected]/dist/math.js"></script>
    <script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
</head>
<style>
</style>
    <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里输出,结果如下:

使用图上像素坐标转换的经纬度,在Google地图上标记旗杆的位置如下:

 经过多次计算和实地对比,精度差距大约在1米以内,比较符合实际需要。

我在企鹅家的课堂和CSDN学院都开通了《OpenLayers实例详解》课程,欢迎报名学习。搜索关键字OpenLayers就能看到。

WebGIS开发过程中会遇到这样一种情况:需要使用OpenLayers加载一个未校准的CAD导出的位图;并且还需要通过经纬度坐标数据在这个位图上做一些标记,还需要能通过在OpenLayers取得的图上要素的像素坐标获知实际的经纬度。总结起来就是两个需求:加载位图 经纬度坐标与像素坐标互转分析:由于从CAD导出的位图并不带有定位信息,所以需要通过仿射变换将图上的像素坐标转换到地理坐标...
可以参考Mxdraw云和mapbox结合的实例,按照以下步骤进行操作: 在Mapbox Studio中,创建一个新项目并选择Geoq浅色地样式。 将地发布到Mapbox中,并获取地ID和访问令牌。 在网页CAD中,使用Mapbox GL JS API连接到地服务,Geoq浅色地数据。 根据网页CAD的需要,调整地的缩放级别、中心点坐标、颜色和样式。 在web CAD界面中,添一个API用于数据,例如OpenLayers或Leaflet。 使用API连接到web GIS中的地服务接口,并将Geoq地数据到web CAD上。 调整Geoq地数据的显示参数,例如颜色和层顺序,以满足web CAD界面设计的要求。 通过遵循这些步骤,您可以在网页CAD和Mapbox结合中实现Geoq浅色地功能。
Database db = HostApplicationServices.WorkingDatabase; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; new TileLayer({ extent: [-13884991, 2870341, -7455066, 6338219], source: new TileArcGISRest({ url: 'https://sampleserver1.arcgisonline.com/Ar.
项目需求主要是实现井下的人员定位功能,通过项目方给的dwg格式地,以web的形式进行,进而在地上实时显示人员位置,点击查看人员信息,绘制人员历史轨迹,统计等主要功能。
很多的朋友遇到这么一个问题,自己手里的CAD纸是dwg格式的,想要导入Google earth内查看,但是Google earth只支持昆明路或者kmz格式的文件,那么应该怎么处理,把dwg格式的文件换成kml或者kmz格式的文件呢,下面已换成kml格式为例(换成kmz的方法相同),给大家介绍如何将dwg格式的文件换成kml格式的文件。 工具/原料 水经注万能地器  AotoC
OpenLayers 是一个用于在 Web 上展示地理信息的开源 JavaScript 库。它支持多种地理坐标系,包括 CGCS2000(China Geodetic Coordinate System 2000)。 要在 OpenLayers 中使用 CGCS2000 坐标系,你需要使用 Proj4js 库来进行坐标换。首先,确保你已经引入了 Proj4js 库和相应的 CGCS2000 坐标系定义文件。 下面是一个简单的示例代码,展示了如何在 OpenLayers 中使用 CGCS2000 坐标系: ```javascript // 定义 CGCS2000 坐标系 proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs"); // 创建地 var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() view: new ol.View({ center: ol.proj.fromLonLat([116.3975, 39.9085], 'EPSG:4490'), zoom: 10 在上述示例代码中,我们首先使用 `proj4.defs` 定义了 CGCS2000 坐标系(EPSG:4490)。然后在创建地时,使用 `ol.proj.fromLonLat` 方法将经纬度坐标换为 CGCS2000 坐标系的投影坐标。 请注意,以上代码仅展示了基本的使用方法,你可能需要根据具体需求进行适当的调整和扩展。希望对你有所帮助!
Openlayers源码实践系列:通过在ol.source.ImageCanvas中获取VectorContext对象高效率绘制海量要素(支持点、线、面) qq_34873359: 这代码能支持要素拾取吗? OpenLayers 5 使用turf.js渲染克里金插值计算的等值面 chuxiaoyu1981: turf.js用turf.min.js代替不可以吗? OpenLayers 5 使用turf.js渲染克里金插值计算的等值面 chuxiaoyu1981: turf.js文件找不到呢 OpenLayers 5 使用turf.js渲染克里金插值计算的等值面 FF_Chen: Uncaught TypeError: Cannot read property 'value' of undefined