ArcGIS Feature格式数据转GeoJSON

        在实际工作中,由于ArcGIS数据格式的一些限制,往往借助其他一些地图引擎进行Web系统开发时,会出现数据格式不一致的情况。典型的如,mapbox gl去渲染一些arcgis服务查出来的结果,这时候就需要对查出来的结果数据格式做一些转换,以满足实际需求。

const commonJs = {
    /**
     * 判断根据ArcGIS的Geometry,获取转换成GeoJSON应该被赋予的类型
     * @param {Object} geometry
     * @returns
     */
    getGeometryType(geometry) {
        let _geometryType = ''
        // 对于rings,只返回一个大类型Polygon,后续会根据rings的具体情况,再去设置细分类型
        if (geometry && geometry.rings) {
            _geometryType = 'Polygon'
        }
        if (geometry && geometry.paths) {
            _geometryType = geometry.paths && geometry.paths.length > 1 ? 'MultiLineString' : 'LineString'
        }
        if (geometry && geometry.points) {
            _geometryType = 'MultiPoint'
        }
        if (geometry && (Array.isArray(geometry) || (geometry.x && geometry.y))) {
            _geometryType = 'Point'
        }
        return _geometryType
    },

    /**
     * 判断图形顺时针、逆时针的方向
     * @param {*} coordArr
     [
      [[x,y],[x,y]], // 一个面
      [[x,y],[x,y]]  // 一个面
     ]
     * @returns
     * handType: 返回的顺序和数组地块的顺序一一对应,true:为顺时针,false:逆时针
     * trueCount:返回true的总数,用于判断是否多面
     */
    checkPolygonCoordsHand(coordArr) {
        let handType = []
        let trueCount = 0
        coordArr.forEach((cods) => {
            let type = 0
            // 多边形x坐标最大值的坐标点序号,这个点一定是多边形的凸点
            let maxIndex = 0
            let coords = cods.concat()
            // 坐标中头尾相同点坐标,相同的则去掉左后一个点
            if (coords[0][0] === coords[coords.length - 1][0] && coords[0][1] === coords[coords.length - 1][1]) {
                coords.splice(coords.length - 1, 1)
            }
            coords.forEach((cod, index2) => {
                // 取第一个出现的最大x坐标的序号
                if (cod[0] > coords[maxIndex][0]) {
                    maxIndex = index2
                }
            })
            if (maxIndex === 0) {
                // 最大的x坐标点等于多边形坐标点集数组的第一个点则取最后一个点为p1,下一个点为p3,本身为p2
                type = (coords[maxIndex][0] - coords[coords.length - 1][0]) * (coords[maxIndex + 1][1] - coords[maxIndex][1]) - (coords[maxIndex][1] - coords[coords.length - 1][1]) * (coords[maxIndex + 1][0] - coords[maxIndex][0])
            } else if (maxIndex < coords.length - 1) {
                // 最大的x坐标点等于多边形坐标点集数组的中间某个点则取前一个点为p1,下一个点为p3,本身为p2
                type = (coords[maxIndex][0] - coords[maxIndex - 1][0]) * (coords[maxIndex + 1][1] - coords[maxIndex][1]) - (coords[maxIndex][1] - coords[maxIndex - 1][1]) * (coords[maxIndex + 1][0] - coords[maxIndex][0])
            } else {
                // 最大的x坐标点等于多边形坐标点集数组的最后一个点则往前取第一个点为p1,下一个点为p3,本身为p2
                type = (coords[maxIndex][0] - coords[maxIndex - 1][0]) * (coords[0][1] - coords[maxIndex][1]) - (coords[maxIndex][1] - coords[maxIndex - 1][1]) * (coords[0][0] - coords[maxIndex][0])
            }
            // 大于 0,图形路径走向为逆时针;小于 0,图形路径走向为顺时针
            if (type < 0) {
                trueCount++
            }
            handType.push(type < 0)
        })
        return {
            trueCount: trueCount,
            handType: handType,
        }
    },

    /**
     * ArcGIS类型的Feature转GeoJSON
     * @param {*} features
     * @returns
     */
    convertAToGeojson(features) {
        let _geoJsonFeatures = []
        // 将返回的数据转化成GeoJSON格式
        if (features.length) {
            features.map((feature) => {
                let _geojsonFeature = {
                    type: 'Feature',
                    properties: feature.attributes ? feature.attributes : {},
                }
                if (feature.geometry) {
                    // 判断空间类型
                    let _geometryType = this.getGeometryType(feature.geometry)
                    let _handObj
                    // 对于Polygon类型的,进一步根据图形的顺、逆值,进行类型细分
                    if (_geometryType == 'Polygon') {
                        _handObj = this.checkPolygonCoordsHand(feature.geometry.rings)
                        // 如果顺、逆时针数组里,存在多个顺时针,即true的数量大于1,则表明多面
                        _geometryType = _handObj.trueCount > 1 ? 'MultiPolygon' : 'Polygon'
                    }
                    _geojsonFeature.geometry = {
                        type: _geometryType,
                        coordinates: [],
                    }
                    switch (_geometryType) {
                        case 'MultiPolygon':
                            let _rings = []
                            let startIndex = 0
                            let interval = 0
                            for (let i = 0, len = _handObj.handType.length; i < len; i++) {
                                if (i == 0 && _handObj.handType[i] == true) {
                                    startIndex = 0
                                    interval++
                                }
                                if (i >= 1 && _handObj.handType[i] == false) {
                                    interval++
                                }
                                // 截取true---下一个true之间的数组,[true, false, false, true] => [true, false, false)
                                if (i >= 1 && _handObj.handType[i] == true) {
                                    let tempArr = feature.geometry.rings.slice(startIndex, i)
                                    _rings.push(tempArr)
                                    startIndex = i
                                    interval = 0
                                }
                                // 在数组最后一位时,需要对其顺逆时针进行判断,true则截取当前值; false则截取起始位置直至最后
                                if (i == _handObj.handType.length - 1) {
                                    if (_handObj.handType[i] == true) {
                                        _rings.push(feature.geometry.rings.slice(i))
                                    } else {
                                        _rings.push(feature.geometry.rings.slice(startIndex))
                                    }
                                }
                            }
                            _geojsonFeature.geometry.coordinates = _rings
                            break
                        case 'Polygon':
                            _geojsonFeature.geometry.coordinates = feature.geometry.rings
                            break
                        case 'MultiLineString':
                            let _paths = []
                            feature.geometry.paths.map((path) => {
                                _paths.push(path)
                            })
                            _geojsonFeature.geometry.coordinates = _paths
                            break
                        case 'LineString':
                            _geojsonFeature.geometry.coordinates = feature.geometry.paths[0]
                            break
                        case 'MultiPoint':
                            _geojsonFeature.geometry.coordinates = feature.geometry.points
                            break
                        case 'Point':
                            _geojsonFeature.geometry.coordinates = [feature.geometry.x, feature.geometry.y]
                            break
                    }
                }
                _geoJsonFeatures.push(_geojsonFeature)
            })
        }
        return {
            type: 'FeatureCollection',
            features: _geoJsonFeatures,
        }
    }
}
export default commonJs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值