龙空技术网

通过openlayers加载dwg格式的CAD图并与互联网地图叠加

vjmap 335

前言:

目前兄弟们对“tiledmap格子坐标算法”都比较着重,看官们都需要学习一些“tiledmap格子坐标算法”的相关知识。那么小编在网摘上汇集了一些关于“tiledmap格子坐标算法””的相关知识,希望朋友们能喜欢,同学们快快来了解一下吧!

Openlayers介绍

Openlayers是一个基于Javacript开发,免费、开源的前端地图开发库,使用它,可以很容易的开发出WebGIS系统。目前Openlayers支持地图瓦片、矢量数据等众多地图数据格式,支持比较完整的地图交互操作。目前OpenLayers已经成为一个拥有众多开发者和帮助社区的成熟、流行的框架,在国内外的GIS相关行业中得到了广泛的应用。

openlayers 官网地址

openlayers 源码地址

Openlayers中加载CAD栅格瓦片

// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据let svc = new vjmap.Service(env.serviceUrl, env.accessToken)// 打开地图let mapId = "sys_zp";let res = await svc.openMap({    mapid: mapId, // 地图ID    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开    style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式})if (res.error) {    // 如果打开出错    message.error(res.error)}// 获取地图范围let mapBounds = vjmap.GeoBounds.fromString(res.bounds);//自定义投影参数let cadProjection = new ol.proj.Projection({    // extent用于确定缩放级别    extent: mapBounds.toArray(),    units: 'm'});// 设置每级的分辨率let resolutions= [];for(let i = 0; i < 25; i++) {    resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)))}// 增加自定义的cad的坐标系ol.proj.addProjection(cadProjection);// 创建openlayer的地图对象let map = new ol.Map({    target: 'map', // div的id    view: new ol.View({        center: mapBounds.center().toArray(),  // 地图中心点        projection: cadProjection, // 刚自定义的cad的坐标系        resolutions:resolutions, // 分辨率        zoom: 2// 初始缩放级别    })});// 增加一个瓦片图层let layer = new ol.layer.Tile({    // 增加一个瓦片数据源    source: new ol.source.TileImage({        url: svc.rasterTileUrl() // 唯杰地图服务提供的cad的栅格瓦片服务地址    })});// 在地图中增加上面的瓦片图层map.addLayer(layer);
Openlayers中加载CAD矢量瓦片
// 增加一个矢量瓦片图层let layer = new ol.layer.VectorTile({    // 增加一个瓦片数据源    source: new ol.source.VectorTile({        projection: cadProjection,        format: new ol.format.MVT(),        url: svc.vectorTileUrl() // 唯杰地图服务提供的cad的矢量瓦片服务地址    }),    style: createVjMapVectorStyle(ol.style.Style, ol.style.Fill, ol.style.Stroke, ol.style.Circle)});// 在地图中增加上面的瓦片图层map.addLayer(layer);
Openlayers中选择高亮CAD实体
const highlight_ent = async co => {    vectorSource.clear();    let res = await svc.pointQueryFeature({        x: co[0],        y: co[1],        zoom: map.getView().getZoom(),        fields: ""    }, pt => {        // 查询到的每个点进行坐标处理回调        return mapPrj.fromMercator(pt);// 转成cad的坐标    })    if (res && res.result && res.result.length > 0) {        let features = [];        for (let ent of res.result) {            if (ent.geom && ent.geom.geometries) {                let clr = vjmap.entColorToHtmlColor(ent.color);                for (let g = 0; g < ent.geom.geometries.length; g++) {                    features.push({                        type: "Feature",                        properties: {                            objectid: ent.objectid + "_" + g,                            color: clr,                            alpha: ent.alpha / 255,                            lineWidth: 1,                            name: ent.name,                            isline: ent.isline,                            layerindex: ent.layerindex                        },                        geometry: ent.geom.geometries[g]                    })                }                // 选择提示                let content = `feature: ${ent.objectid}; layer: ${cadLayers[ent.layerindex].name}; type: ${ent.name}`                message.info({ content, key: "info", duration: 3});            }        }        geojsonObject.features = features;        if (geojsonObject.features.length > 0) {            vectorSource.addFeatures( new ol.format.GeoJSON().readFeatures(geojsonObject, {dataProjection: cadProjection}))        }    }};
Openlayers中上传打开CAD的DWG图形
// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据let svc = new vjmap.Service(env.serviceUrl, env.accessToken)// 上传dwg文件const uploadDwgFile = async file => {    message.info("正在上传图形,请稍候", 2);    let res = await svc.uploadMap(file); // 上传地图    // 输入图id    let mapid = prompt("请输入图名称ID", res.mapid);    res.mapid = mapid;    res.mapopenway = vjmap.MapOpenWay.GeomRender; // 几何渲染,内存渲染用vjmap.MapOpenWay.Memory    res.isVector = false; // 使用栅格瓦片    res.style = vjmap.openMapDarkStyle(); // 深色样式,浅色用openMapDarkStyle    message.info("正在打开图形,请稍候,第一次打开时根据图的大小可能需要几十秒至几分钟不等", 5);    let data = await svc.openMap(res); // 打开地图    if (data.error) {        message.error(data.error)        return;    }    openMap(data);}
Openlayers中切换CAD图层
// 切换图层const switchLayer = async layers => {    let res = await svc.cmdSwitchLayers(layers); // 调用唯杰服务切换图层,返回图层id {layerid: "xxxx"}    let source = layer.getSource();    // 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址    source.setUrl(svc.rasterTileUrl());    // 刷新    source.refresh();}
Openlayers中切换CAD图形
const switchToMapId = async (mapId)=> {    let res = await svc.openMap({        mapid: mapId, // 地图ID        mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开        style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式    })    if (res.error) {        // 如果打开出错        message.error(res.error)        return;    }// 获取地图范围    let mapBounds = vjmap.GeoBounds.fromString(res.bounds);//自定义投影参数    let cadProjection = new ol.proj.Projection({        // extent用于确定缩放级别        extent: mapBounds.toArray(),        units: 'm'    });// 设置每级的分辨率    let resolutions= [];    for(let i = 0; i < 25; i++) {        resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)))    }// 增加自定义的cad的坐标系    ol.proj.addProjection(cadProjection);// 重新创建openlayer的地图对象    map = new ol.Map({        target: createNewMapDivId(), // div的id        view: new ol.View({            center: mapBounds.center().toArray(),  // 地图中心点            projection: cadProjection, // 刚自定义的cad的坐标系            resolutions:resolutions, // 分辨率            zoom: 2 // 初始缩放级别        })    });// 增加一个瓦片图层    let layer = new ol.layer.Tile({        // 增加一个瓦片数据源        source: new ol.source.TileImage({            url: svc.rasterTileUrl() // 唯杰地图服务提供的cad的栅格瓦片服务地址        })    });// 在地图中增加上面的瓦片图层    map.addLayer(layer);    map.on('click', (e) => message.info({content: `您点击的坐标为: ${JSON.stringify(e.coordinate)}`, key: "info", duration: 3}));}
Openlayers中深色浅色切换主题
let curIsDarkTheme = true;const switchToDarkTheme = async () => {    if (curIsDarkTheme) return;    curIsDarkTheme = true;    document.body.style.background = "#022B4F"; // 背景色改为深色    await updateStyle(curIsDarkTheme)}const switchToLightTheme = async () => {    if (!curIsDarkTheme) return;    curIsDarkTheme = false;    document.body.style.backgroundImage = "linear-gradient(rgba(255, 255, 255, 1), rgba(233,255,255, 1), rgba(233,255,255, 1))"    await updateStyle(curIsDarkTheme)}const updateStyle = async (isDarkTheme) => {    style.backcolor = isDarkTheme ? 0 : 0xFFFFFF;//深色为黑色,浅色为白色    let res = await svc.cmdUpdateStyle(style);    let source = layer.getSource();    // 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址    source.setUrl(svc.rasterTileUrl());    // 刷新    source.refresh();}
Openlayers中自定义CAD地图样式

通过修改CAD地图后台样式数据自定义地图

// 更改样式const expressionList = [] ;// 表达式数组const updateStyle = async (style) => {    let res = await svc.cmdUpdateStyle({        name: "customStyle2",        backcolor: 0,        expression: expressionList.join("\n"),        ...style    });    let source = layer.getSource();    // 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址    source.setUrl(svc.rasterTileUrl());    // 刷新    source.refresh();}// 表达式语法和变量请参考// 服务端条件查询和表达式查询  服务端渲染表达式语法  修改颜色  红color.r, 绿color.g, 蓝color.b, 透明度color.a,如果输入了级别的话,表示此级别及以上的设置const modifyColor = (color, zoom) => {    let result = "";    let z = Number.isInteger(zoom) ? `[${zoom + 1}]` : '';    if ("r" in color) result += `gOutColorRed${z}:=${color.r};`;    if ("g" in color) result += `gOutColorGreen${z}:=${color.g};`;    if ("b" in color) result += `gOutColorBlue${z}:=${color.b};`;    if ("a" in color) result += `gOutColorAlpha${z}:=${color.a};`;    return result;}
Openlayers中对CAD图处理组合

对多个cad图进行图层开关裁剪旋转缩放处理后合并成一个新的cad图

// 组合成新的图,将sys_world图进行一定的处理后,再与sys_hello进行合成,生成新的地图文件名let rsp = await svc.composeNewMap([    {        mapid: "sys_world", // 地图id        // 下面的参数可以根据实际需要来设置,可以对图层,范围,坐标转换来进行处理        layers: ["经纬度标注","COUNTRY"], // 要显示的图层名称列表        //clipbounds: [10201.981489534268, 9040.030491346213, 26501.267379,  4445.465999], // 要显示的范围        //fourParameter: [0,0,1,0] // 对地图进行四参数转换计算    },    {        mapid: "sys_hello"    }])if (!rsp.status) {    message.error(rsp.error)}// 返回结果为/*{    "fileid": "pec9c5f73f1d",    "mapdependencies": "sys_world||sys_hello",    "mapfrom": "sys_world&&v1&&&&0&&&&&&&&&&00A0&&10||sys_hello&&v1&&&&0&&&&&&&&&&&&2",    "status": true} */
Openlayers中查询图中所有文字并绘制边框
// 实体类型ID和名称映射const { entTypeIdMap } = await svc.getConstData();const getTypeNameById = name => {    for(let id in entTypeIdMap) {        if (entTypeIdMap[id] == name) {            return id        }    }}const queryTextAndDrawBounds = async () => {    let queryTextEntTypeId = getTypeNameById("AcDbText"); // 单行文字    let queryMTextEntTypeId = getTypeNameById("AcDbMText"); // 多行文字    let queryAttDefEntTypeId = getTypeNameById("AcDbAttributeDefinition"); // 属性定义文字    let queryAttEntTypeId = getTypeNameById("AcDbAttribute"); // 属性文字    let query = await svc.conditionQueryFeature({        condition: `name='${queryTextEntTypeId}' or name='${queryMTextEntTypeId}' or name='${queryAttDefEntTypeId}' or name='${queryAttEntTypeId}'`, // 只需要写sql语句where后面的条件内容,字段内容请参考文档"服务端条件查询和表达式查询"        fields: "",        limit: 100000 //设置很大,相当于把所有的圆都查出来。不传的话,默认只能取100条    }, pt => {        // 查询到的每个点进行坐标处理回调        return mapPrj.fromMercator(pt);// 转成cad的坐标    })    if (query.error) {        message.error(query.error)    } else {        message.info(`查询到符合的记数条数:${query.recordCount}`)        if (query.recordCount > 0) {            let features = [];            for(var i = 0; i < query.recordCount; i++) {                let bounds = vjmap.getEnvelopBounds(query.result[i].envelop, mapPrj);                let clr = vjmap.entColorToHtmlColor(query.result[i].color); // 实体颜色转html颜色(                features.push({                    type: "Feature",                    properties: {                        name: "objectid:" + query.result[i].objectid,                        color: clr                    },                    geometry: {                        'type': 'Polygon',                        'coordinates': [                            bounds.toPointArray(),                        ],                    }                })            }            if (!vectorSource) {                // 如果之前没有高亮矢量图层                addHighLightLayer();            }            vectorSource.clear();            let geojsonObject = {                'type': 'FeatureCollection',                'features': features            }            // 修改矢量数据源数据            vectorSource.addFeatures( new ol.format.GeoJSON().readFeatures(geojsonObject, {dataProjection: cadProjection}))        }    }}
Openlayers中图形绘制
const source = new ol.source.Vector({wrapX: false});const vector = new ol.layer.Vector({    source: source,});map.addLayer(vector);let draw; // global so we can remove it laterfunction addInteraction(value) {    map.removeInteraction(draw);    if (value !== 'None') {        draw = new ol.interaction.Draw({            source: source,            type: value,        });        map.addInteraction(draw);    }}addInteraction('Point');
Openlayers中CAD图叠加互联网地图[CAD为底图]
// 增加高德地图底图let gdlayer;const addGaodeMap = async (isRoadway) => {    const tileUrl = svc.webMapUrl({        tileCrs: "gcj02",        tileUrl:  isRoadway ? [                "{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"            ] :            /* 如果用影像 */            [                "{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}",                "{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"            ],        tileSize: 256,        tileRetina: 1,        tileMaxZoom: 18,        tileShards: "1,2,3,4",        tileToken: "",        tileFlipY: false,        mapbounds: res.bounds,        srs: "EPSG:4527",// 可通过前两位获取 vjmap.transform.getEpsgParam(vjmap.transform.EpsgCrsTypes.CGCS2000, 39).epsg        // 因为sys_cad2000这个图只有6位,没有带系。需要在坐标转换前平移下带系          fourParameterBefore: "39000000,0,1,0"    })    // 增加一个瓦片图层    gdlayer = new ol.layer.Tile({        // 增加一个瓦片数据源        source: new ol.source.TileImage({            url: tileUrl        })    });    gdlayer.setZIndex(-1);// 在地图中增加上面的瓦片图层    map.addLayer(gdlayer);    // cad坐标与高德坐标相互转换示例    let webCo = await cad2webCoordinate(center, false); // cad转高德    let cadCo = await web2cadCoordinate(webCo, false); // 高德转cad    console.log(center, webCo, cadCo)}
Openlayers中互联网地图自动叠加CAD图[互联网图为底图]
let cadEpsg = "EPSG:4544";// cad图的espg代号// 增加cad的wms图层let wmsUrl = svc.wmsTileUrl({    mapid: mapId, // 地图id    layers: layer, // 图层名称    bbox: '', // bbox这里不需要    srs: "EPSG:3857", //    crs: cadEpsg})function getQueryStringArgs(url) {    let theRequest = {};    let idx = url.indexOf("?");    if (idx != -1) {        let str = url.substr(idx + 1);        let strs = str.split("&");        for (let i = 0; i < strs.length; i++) {            let items = strs[i].split("=");            theRequest[items[0]] = items[1];        }    }    return theRequest;}let mapBounds = vjmap.GeoBounds.fromString(res.bounds);// cad图坐标转web wgs84坐标const cadToWebCoordinate = async point => {    let co = await svc.cmdTransform(cadEpsg, "EPSG:4326", point);    return co[0]}// cad转wgs84经纬度let boundsMin = await cadToWebCoordinate(mapBounds.min);let boundsMax = await cadToWebCoordinate(mapBounds.max);// wgs84经纬度转墨卡托boundsMin = vjmap.Projection.lngLat2Mercator(boundsMin);boundsMax = vjmap.Projection.lngLat2Mercator(boundsMax);// 在openlayer中增加wms图层map.addLayer(new ol.layer.Tile({    // 范围    extent: [boundsMin[0], boundsMin[1], boundsMax[0], boundsMax[1]],    source: new ol.source.TileWMS({        url: wmsUrl.substr(0, wmsUrl.indexOf("?")),        params: {...getQueryStringArgs(wmsUrl),'TILED': true}    }),}))
Openlayers中互联网地图公共点叠加CAD图[互联网图为底图]
// cad上面的点坐标let cadPoints = [    vjmap.geoPoint([587464448.8435847, 3104003685.208651,]),    vjmap.geoPoint([587761927.7224838, 3104005967.655292]),    vjmap.geoPoint([587463688.0280377, 3103796743.3798513]),    vjmap.geoPoint([587760406.0913897, 3103793700.1176634])];// 在互联网图上面拾取的与上面的点一一对应的坐标(wgs84坐标)let webPoints = [    vjmap.geoPoint([116.48476281710168, 39.96200739703454]),    vjmap.geoPoint([116.48746772021137, 39.96022062215167]),    vjmap.geoPoint([116.48585059441585, 39.9588451134361]),    vjmap.geoPoint([116.48317418949145, 39.960515760972356])]// 通过坐标参数求出四参数let epsg3857Points = webPoints.map(w => vjmap.geoPoint(vjmap.Projection.lngLat2Mercator(w)));let param = vjmap.coordTransfromGetFourParamter(epsg3857Points, cadPoints , false); // 这里考虑旋转let fourparam = [param.dx, param.dy, param.scale, param.rotate]// wms图层地址const getCadWmsUrl = (transparent) => {    let wmsUrl = svc.wmsTileUrl({        mapid: mapId, // 地图id        layers: layer, // 图层名称        bbox: '', // bbox这里不需要        fourParameter: fourparam,        transparent: transparent,        backgroundColor: 'rgba(240, 255, 255)' // 不透明时有效    })    return wmsUrl}let mapBounds = vjmap.GeoBounds.fromString(res.bounds);let cadPrj = new vjmap.GeoProjection(mapBounds);// cad图坐标转3857坐标const cadToWebCoordinate = point => {    // 再调用四参数反算求出web的坐标    return vjmap.coordTransfromByInvFourParamter(vjmap.geoPoint(point), param)}// 3857转cad图坐标const webToCadCoordinate = point => {    return vjmap.coordTransfromByFourParamter(vjmap.geoPoint(point), param)}let wmsLayer;const addWmsLayer = async (transparent)=> {    removeWmsLayer();    let wmsUrl = getCadWmsUrl(transparent);    wmsLayer = new ol.layer.Tile({        // 范围        extent: bounds.toArray(),        source: new ol.source.TileWMS({            url: wmsUrl.substr(0, wmsUrl.indexOf("?")),            params: {...getQueryStringArgs(wmsUrl),'TILED': true}        }),    });    // 在openlayer中增加wms图层    map.addLayer(wmsLayer);}
最后

可点击 在线体验上面功能

如果需要用openlayers来加载CAD图进行开发,请参考示例

如果需要用leaflet来加载CAD图进行开发,请参考示例

如果需要用maptalks来加载CAD图进行开发,请参考示例

如何基于vue3来开发openlayers应用,可查看此开源代码

如何基于vue2来开发openlayers应用,可查看此开源代码

标签: #tiledmap格子坐标算法