Openlayers 多面、多线、多点与单面、单线、单点的转换

发布于:2022-12-29 ⋅ 阅读:(368) ⋅ 点赞:(0)

Openlayers 多面、多线、多点与单面、单线、单点的转换

OpenLayers 教程

项目中偶然遇到个需求,因为安卓端数据类型问题,想把多个面图形要素转为一个多面的图形要素,提供给安卓端使用。因为数据存在数据库,所以想通过 postgis 的函数,直接转换就行。经过尝试,没找到合适函数,后来想到 Openlayers 中应该有转换方法,于是使用 openlayers 做了个转换的工具类,这里记录一下。

转换过程大概是,首先创建多面图形要素对象(此时几何图形为空),然后创建多个面状图形要素对象,最后遍历面图形对象,将几何图形(Polygon)添加到多面图形要素对象中。

注意:示例中的转换方法点线面通用!

2022年10月24日 修改在线示例,增加转换工具。

Openlayers 多面、多线、多点与单面、单线、单点的转换

<html lang="en">
<head>
    <meta charSet="utf-8">
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <link rel="stylesheet" href="http://openlayers.vip/examples/css/ol.css" type="text/css">
    <style>
        /* 注意:这里必须给高度,否则地图初始化之后不显示;一般是计算得到高度,然后才初始化地图 */
        .map {
            height: 400px;
            width: 100%;
            float: left;
        }

        #labelPopup {
            background-color: white;
        }
    </style>
    <!--注意:openlayers 原版的比较慢,这里引起自己服务器版-->
    <script src="http://openlayers.vip/examples/resources/ol.js"></script>
    <script src="./tiandituLayers.js"></script>
    <title>OpenLayers example</title>
</head>
<body>
<h2>OpenLayers feature multi transfer</h2>
<!--地图容器,需要指定 id -->
<div id="map" class="map"></div>

<script type="text/javascript">
    var map = new ol.Map({
        // 地图容器
        target: 'map',
        // 地图图层,比如底图、矢量图等
        layers: [
            getIMG_CLayer(),
            getIBO_CLayer(),
            getCIA_CLayer(),
        ],
        // 地图视野
        view: new ol.View({
            projection: "EPSG:4326",
            // 定位
            center: [115.67724700667199, 37.73879478106912],
            // 缩放
            zoom: 6,
            maxZoom: 18,
            minZoom: 1,
        })
    });

    var defaultStyle = new ol.style.Style({
        //边框样式
        stroke: new ol.style.Stroke({
            color: 'red',
            width: 1,
        }),
        //填充样式
        fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.3)',
        }),
    })
    // 初始化图层
    var layer = initVectorLayer();
    // 点线面数组
    var features = [];
    var featureMultiPolygon;

    addFeatures();

    // 添加面数据
    function addFeatures() {

        features.push(getFeatureByWKT("POLYGON((116.25730023609182 39.99408085954892,116.255712368355 39.99236424577939,116.25476823078176 39.9906905473541,116.255712368355 39.98815854204404,116.25704274402639 39.98742898119199,116.25802979694387 39.98687108171689,116.2591885112383 39.9846394838165,116.26227841602346 39.983051616079685,116.26382336841604 39.981292086965915,116.26562581287405 39.981034594900486,116.26695618854544 39.980777102835056,116.26875863300344 39.981034594900486,116.27021775470755 39.981549579031345,116.27163396106741 39.98043378008115,116.2724064372637 39.97991879595029,116.27408013568899 39.98017628801572,116.27146229969046 39.98395283830869,116.2727497600176 39.988759356863376,116.27064690814993 39.98966057909238,116.26978860126516 39.98966057909238,116.26935944782278 39.990046817190525,116.25730023609182 39.99408085954892))"));
        features.push(getFeatureByWKT("POLYGON((116.26172051654837 39.99940236223447,116.26071200595877 39.997299510366794,116.25976786838552 39.996033507711765,116.25852332340261 39.9950679124664,116.25770793186209 39.994552928335544,116.25730023609182 39.99408085954892,116.25787451043203 39.99388875354188,116.25837480282617 39.99372139594384,116.25905858212158 39.99349265838594,116.26843906021938 39.99035470485856,116.26920253859541 39.990219819672,116.269309826956 39.990300285942446,116.26939029322645 39.99052022708167,116.26948685275099 39.99062215102423,116.27001793013594 39.99066506636847,116.27045244799635 39.99062215102423,116.27074749098799 39.990327108032595,116.27071530447981 39.98989795459021,116.27068311797163 39.989796030647646,116.27064690814993 39.98966057909238,116.27148241625807 39.98952244532813,116.27230317221662 39.98925958884467,116.27360672579785 39.989527809746185,116.27420754061718 39.991566288597504,116.2744435750105 39.99315415633432,116.2743362866499 39.99448453200571,116.27375692950268 39.99564324630014,116.27307028399487 39.99611531508676,116.27289862261792 39.99712382567636,116.2694010220625 39.99697362197153,116.26875729189892 39.996372807152184,116.2671694241621 39.996072399742516,116.26650423632641 39.996608841545495,116.26422972308178 39.996351349480065,116.26382202731152 39.997123825676354,116.26285643206616 39.996630299217614,116.26259894000073 39.99763880980721,116.26270622836132 39.998132336265954,116.26242727862378 39.999097931511315,116.26172051654837 39.99940236223447))"));
        features.push(getFeatureByWKT("POLYGON((116.25694227111876 39.97520951368282,116.25694227111876 39.97469452955196,116.25765037429869 39.974372664470174,116.25784349334776 39.97364310361812,116.25964593780577 39.97293500043819,116.25953864944518 39.972377100963094,116.26082610977232 39.97093943693111,116.26271438491881 39.97074631788204,116.2633795727545 39.97173337079952,116.2639374722296 39.972312727946736,116.26346540344298 39.97246293165157,116.2644953717047 39.97278479673336,116.2653965939337 39.97422246076534,116.26668405426085 39.97420100309322,116.2674136151129 39.97351435758541,116.26799297226012 39.97349289991329,116.26825046432555 39.97398642637203,116.26825046432555 39.97450141050289,116.26711320770323 39.97555283643673,116.26646947753966 39.976368227977254,116.26614761245787 39.977054873485066,116.26436662567198 39.97825650312374,116.26322936904967 39.979307929057576,116.26269292724669 39.97920064069698,116.26254272354186 39.978556910533406,116.26376581085265 39.977333823222615,116.2642807949835 39.97643260099361,116.2639374722296 39.97647551633785,116.26346540344298 39.976561347026326,116.26301479232848 39.97651843168209,116.26234960449278 39.97589615919063,116.2610192288214 39.97475890256832,116.25822973144591 39.97516659833858,116.25694227111876 39.97520951368282))"));

        featureMultiPolygon = getFeatureByWKT("MULTIPOLYGON(((116.25730023609182 39.99408085954892,116.255712368355 39.99236424577939,116.25476823078176 39.9906905473541,116.255712368355 39.98815854204404,116.25704274402639 39.98742898119199,116.25802979694387 39.98687108171689,116.2591885112383 39.9846394838165,116.26227841602346 39.983051616079685,116.26382336841604 39.981292086965915,116.26562581287405 39.981034594900486,116.26695618854544 39.980777102835056,116.26875863300344 39.981034594900486,116.27021775470755 39.981549579031345,116.27163396106741 39.98043378008115,116.2724064372637 39.97991879595029,116.27408013568899 39.98017628801572,116.27146229969046 39.98395283830869,116.2727497600176 39.988759356863376,116.27064690814993 39.98966057909238,116.26978860126516 39.98966057909238,116.26935944782278 39.990046817190525,116.25730023609182 39.99408085954892)),((116.26172051654837 39.99940236223447,116.26071200595877 39.997299510366794,116.25976786838552 39.996033507711765,116.25852332340261 39.9950679124664,116.25770793186209 39.994552928335544,116.25730023609182 39.99408085954892,116.25787451043203 39.99388875354188,116.25837480282617 39.99372139594384,116.25905858212158 39.99349265838594,116.26843906021938 39.99035470485856,116.26920253859541 39.990219819672,116.269309826956 39.990300285942446,116.26939029322645 39.99052022708167,116.26948685275099 39.99062215102423,116.27001793013594 39.99066506636847,116.27045244799635 39.99062215102423,116.27074749098799 39.990327108032595,116.27071530447981 39.98989795459021,116.27068311797163 39.989796030647646,116.27064690814993 39.98966057909238,116.27148241625807 39.98952244532813,116.27230317221662 39.98925958884467,116.27360672579785 39.989527809746185,116.27420754061718 39.991566288597504,116.2744435750105 39.99315415633432,116.2743362866499 39.99448453200571,116.27375692950268 39.99564324630014,116.27307028399487 39.99611531508676,116.27289862261792 39.99712382567636,116.2694010220625 39.99697362197153,116.26875729189892 39.996372807152184,116.2671694241621 39.996072399742516,116.26650423632641 39.996608841545495,116.26422972308178 39.996351349480065,116.26382202731152 39.997123825676354,116.26285643206616 39.996630299217614,116.26259894000073 39.99763880980721,116.26270622836132 39.998132336265954,116.26242727862378 39.999097931511315,116.26172051654837 39.99940236223447)),((116.25694227111876 39.97520951368282,116.25694227111876 39.97469452955196,116.25765037429869 39.974372664470174,116.25784349334776 39.97364310361812,116.25964593780577 39.97293500043819,116.25953864944518 39.972377100963094,116.26082610977232 39.97093943693111,116.26271438491881 39.97074631788204,116.2633795727545 39.97173337079952,116.2639374722296 39.972312727946736,116.26346540344298 39.97246293165157,116.2644953717047 39.97278479673336,116.2653965939337 39.97422246076534,116.26668405426085 39.97420100309322,116.2674136151129 39.97351435758541,116.26799297226012 39.97349289991329,116.26825046432555 39.97398642637203,116.26825046432555 39.97450141050289,116.26711320770323 39.97555283643673,116.26646947753966 39.976368227977254,116.26614761245787 39.977054873485066,116.26436662567198 39.97825650312374,116.26322936904967 39.979307929057576,116.26269292724669 39.97920064069698,116.26254272354186 39.978556910533406,116.26376581085265 39.977333823222615,116.2642807949835 39.97643260099361,116.2639374722296 39.97647551633785,116.26346540344298 39.976561347026326,116.26301479232848 39.97651843168209,116.26234960449278 39.97589615919063,116.2610192288214 39.97475890256832,116.25822973144591 39.97516659833858,116.25694227111876 39.97520951368282)))");
    }

    /**
     * @todo 矢量图层
     * @returns {VectorLayer}
     * @constructor
     */
    function initVectorLayer() {
        //实例化一个矢量图层Vector作为绘制层
        let source = new ol.source.Vector();
        //创建一个图层
        let customVectorLayer = new ol.layer.Vector({
            source: source,
            zIndex: 2,
            //设置样式
            style: defaultStyle,
        });
        //将绘制层添加到地图容器中
        map.addLayer(customVectorLayer);

        return customVectorLayer;
    }

    /**
     * @todo wkt格式数据转化成图形对象
     * @param {string} wkt   "POINT(112.7197265625,39.18164062499999)" 格式数据
     * @param {string|Projection} sourceCode 源投影坐标系
     * @param {string|Projection} targetCode 目标投影坐标系
     * @returns {Feature}
     */
    function getFeatureByWKT(wkt, sourceCode, targetCode) {
        try {
            let view = map.getView();
            if (!wkt) {
                return null;
            }
            let format = new ol.format.WKT();

            let feature;

            feature = format.readFeature(wkt, {
                featureProjection: targetCode || view.getProjection(),
                dataProjection: sourceCode || view.getProjection(),
            });

            return feature;
        } catch (e) {
            console.log(e);
            return null;
        }
    }

    /**
     * @Todo 将feature   转化成wkt格式
     * 大地坐标转地理坐标,可以先new feature 然后转为wkt(设置转换  'EPSG:4326' 'EPSG:3857'),在转回feature即可
     * @method getWKTByFeatures
     * @param feature  参数为feature对象
     * @param code  坐标系
     * @returns str  返回wkt数据
     */
    function getWKTByFeature(feature, sourceCode, targetCode) {
        try {
            let view = map.getView();
            if (!feature) {
                return null;
            }
            let format = new ol.format.WKT();

            if (feature instanceof Array) {
                return format.writeFeatures(feature, {
                    //传入feature的坐标系
                    featureProjection: sourceCode || view.getProjection(),
                    //返回数据的坐标系
                    dataProjection: targetCode || view.getProjection()
                });
            } else {
                return format.writeFeature(feature, {
                    //传入feature的坐标系
                    featureProjection: sourceCode || view.getProjection(),
                    //返回数据的坐标系
                    dataProjection: targetCode || view.getProjection()
                });
            }
        } catch (e) {
            console.log(e);
            return null
        }
    }

    // 定位
    function moveTo(layerTemp) {
        layerTemp && map.getView().fit(layerTemp.getSource().getExtent(), {
            duration: 1,//动画的持续时间,
            callback: null,
        });
    }

    // 定义图形要素类型
    const POLYGON = 'Polygon';
    const MULTIPOLYGON = 'MultiPolygon';
    const LINESTRING = 'LineString';
    const MULTILINESTRING = 'MultiLineString';
    const POINT = 'Point';
    const MULTIPOINT = 'MultiPoint';

    /**
     * 将多个面(面或者多秒)合并为多面
     * @param features
     * @returns {MultiPolygon}
     * @constructor
     */
    function GeometryToMulti(features, geometryType) {

        if (!features || !features.length || features.length <= 0) {
            return;
        }

        let multiGeometry;

        if (POLYGON.toLowerCase() == geometryType.toLowerCase()) {
            multiGeometry = new ol.geom.MultiPolygon([]);
        } else if (LINESTRING.toLowerCase() == geometryType.toLowerCase()) {
            multiGeometry = new ol.geom.MultiLineString([]);
        } else if (POINT.toLowerCase() == geometryType.toLowerCase()) {
            multiGeometry = new ol.geom.MultiPoint([]);
        }

        let appendFunc = function (multi, geometries) {
            for (let i = 0; i < geometries.length; i++) {
                switch (type) {
                    case MULTIPOLYGON:
                        multi.appendPolygon(geometries[i]);
                        break;
                    case MULTILINESTRING:
                        multi.appendLinearRing(geometries[i]);
                        break;
                    case MULTIPOINT:
                        multi.appendPoint(geometries[i]);
                        break;
                }
            }
        }

        for (let i = 0; i < features.length; i++) {

            let type = features[i].getGeometry().getType();
            let temp = features[i].getGeometry();

            switch (type) {
                case MULTIPOLYGON:
                    appendFunc(multiGeometry, temp.getPolygons());
                    break;
                case MULTILINESTRING:
                    appendFunc(multiGeometry, temp.getLineStrings());
                    break;
                case MULTIPOINT:
                    appendFunc(multiGeometry, temp.getPoints());
                    break;
                case POLYGON:
                    multiGeometry.appendPolygon(features[i].getGeometry());
                    break;
                case LINESTRING:
                    multiGeometry.appendLineString(features[i].getGeometry());
                    break;
                case POINT:
                    multiGeometry.appendPoint(features[i].getGeometry());
                    break;
            }
        }

        return new ol.Feature(multiGeometry);
    }

    /**
     * 将多面拆分为多个面
     * @param feature
     * @returns {Polygon}
     * @constructor
     */
    function MultiToGeometry(feature) {

        if (!feature || !(feature instanceof ol.Feature)) {
            return;
        }

        let temp = feature.getGeometry();

        let type = feature.getGeometry().getType();

        let tempArr;
        if (MULTIPOLYGON == type) {
            tempArr = temp.getPolygons();
        } else if (MULTILINESTRING == type) {
            tempArr = temp.getLineStrings();
        } else if (MULTIPOINT == type) {
            tempArr = temp.getPoints();
        }

        let features;
        if (tempArr && tempArr.length > 0) {
            features = [];
            for (let i = 0; i < tempArr.length; i++) {
                features.push(new ol.Feature(tempArr[i]));
            }
        }
        return features;
    }

    // 面转为多面
    function polygonToMulti() {
        closeFeature();
        setTimeout(function () {
            let featureMulti = GeometryToMulti(features, POLYGON);
            layer.getSource().addFeatures([featureMulti]);
            console.log(getWKTByFeature(featureMulti));
            moveTo(layer);
        }, 350)
    }

    // 多面转为面
    function multiToPolygon() {
        closeFeature();
        setTimeout(function () {
            let featureMulti = MultiToGeometry(featureMultiPolygon);
            layer.getSource().addFeatures(featureMulti);
            moveTo(layer);
            console.log(getWKTByFeature(featureMulti));
        }, 350)
    }

    // 清空
    function closeFeature() {
        layer.getSource().clear();
    }

</script>
<button id="GeometryToMulti" onClick="polygonToMulti()">多个面图形要素转多面</button>
<button id="MultiToGeometry" onClick="multiToPolygon()">多面转多个面图形要素</button>
<button id="closeFeature" onClick="closeFeature()">清空</button>
</body>
</html>

在线示例

Openlayers 多面、多线、多点与单面、单线、单点的转换:Openlayers feature multi transfer

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到