MapBox-Gl多边形航线规划,无人机测绘功能

使用mapbox-gl实现无人机测绘功能中的无人机航线生成


自定义画线等功能 接上回mapbox-gl-draw` 自定义按钮画线,画面,计算面积,计算长度


绘制多边形等功能不做赘述


注释由AI生成,将就看

甲、 安装插件与准备

@mapbox/mapbox-gl
@mapbox/mapbox-gl-draw
uuid
@turf/turf

mapbox-gl多边形绘制类型
ts 复制代码
  export interface FeaturesMeta {
    type: string;
    geometry:  GeometryMeta;
    properties: PropertiesMeta | any;
    id?:  string;
  }

乙、 根据绘制的多边形进行缓冲区计算

提供缓冲区距离为单位

1) 将Draw数据转换成@turf/turf数据

turfAPI = polygon

2) 根据提供的缓冲区距离绘制多边形(平行扩建)

turfAPI = buffer

ts 复制代码
/**
 * 函数"usePolygonParallelExpansion"以多边形和缓冲距离作为输入,使用 Turf.js 创建缓冲多边形,为缓冲多边形分配唯一 ID,并返回缓冲多边形。
 * @param {FeaturesMeta} polygon - `polygon` 参数表示要并行扩展的多边形几何体。它应采用可以转换为 Turf.js 多边形对象的格式。
 * @param {number} buffer - `buffer` 参数是一个数字,表示您希望在 `usePolygonParallelExpansion`
 * 函数中扩展给定多边形的距离(以米为单位)。此距离将用于在多边形周围创建缓冲区。
 * @returns 函数"usePolygonParallelExpansion"返回通过将输入多边形扩展指定的缓冲距离(以米为单位)创建的缓冲多边形特征。
 */
export const usePolygonParallelExpansion = (polygon: FeaturesMeta, buffer: number) => {
    const turfPolygon = turf.polygon([polygon.geometry.coordinates[0]]);
    const bufferedPolygon = turf.buffer(turfPolygon, buffer, { units: 'meters' });
    bufferedPolygon.id = uuidv4()
    return bufferedPolygon;
}

丙、计算多边形最大边界,中心位置,以及最大纬度

可使用自定义函数,也可使用truf自带函数bbox

ts 复制代码
  /**
     * 函数"calculatePolygonBounds"计算由纬度和经度数组定义的多边形的边界框和中心。
     * @param {any[]} latlngs - `calculatePolygonBounds` 函数中的 `latlngs`
     * 参数是一个纬度和经度坐标数组。数组中的每个元素代表多边形上的一个点。坐标可以采用不同的格式,可以是数组 `[longitude, latitude]`,也可以是对象 `{lat}`。
     * @returns 函数 `calculatePolygonBounds` 返回一个具有以下属性的对象:
     * - `center`:一个具有 `lat` 和 `lng` 的对象,表示多边形的中心点
     * - `latlngs`:一个表示多边形四个角的对象数组
     * - `northLat`:输入纬度中的最大纬度值
     */
    const calculatePolygonBounds = (latlngs: any[]) => {
        const lats = latlngs.map(latlng => latlng[1] || latlng.lat);
        const lngs = latlngs.map(latlng => latlng[0] || latlng.lng);
        const maxLat = Math.max(...lats);
        const minLat = Math.min(...lats);
        const maxLng = Math.max(...lngs);
        const minLng = Math.min(...lngs);

        return {
            center: { lat: (maxLat + minLat) / 2, lng: (maxLng + minLng) / 2 },
            latlngs: [
            { lat: maxLat, lng: minLng },
            { lat: maxLat, lng: maxLng },
            { lat: minLat, lng: maxLng },
            { lat: minLat, lng: minLng }
            ],
            northLat: maxLat
        };
    };

丁、设置旋转的多边形(航线旋转时用到)

ts 复制代码
/**
 * 在 TypeScript 中,`rotatePolygon` 函数围绕指定中心点按给定角度旋转多边形。
 * @param {LatLng[] | Position[]} latlngs - `rotatePolygon` 函数中的 `latlngs` 参数是 `LatLng` 对象或 `Position`
 * 对象的数组。
 * @param  - `rotatePolygon` 函数采用以下参数:
 * @param {number} rotate - `rotatePolygon` 函数中的 `rotate` 参数表示多边形的旋转角度。此角度以度为单位指定,决定了多边形围绕其中心点的旋转量。
 * @param {boolean} [isFinally=false] - `rotatePolygon` 函数中的 `isFinally` 参数是一个布尔标志,指示最终输出是否应采用特定格式。如果
 * `isFinally` 设置为 `true`,则输出将是一个经度和纬度值数组 `[lng, lat]`。如果`
 * @returns `rotatePolygon` 函数根据输入的 `latlngs` 数组或 `Position` 数组、`center` 点、旋转角度 `rotate` 和布尔标志
 * `isFinally` 返回旋转坐标数组。该函数通过围绕指定的中心点旋转每个点来计算新坐标,然后如果 `isFinally` 为
 */
    const rotatePolygon = (latlngs: LatLng[] | Position[], { center }: { center: LatLng }, rotate: number,  isFinally: boolean = false) => {
        const res = [];
        const gis2pxCenter: Point = latlng2Px(center);
        for (let i = 0; i < latlngs.length; i++) {
            const gis2px = latlng2Px(latlngs[i]);
            const _transform = transform(gis2px.x, gis2px.y, gis2pxCenter.x, gis2pxCenter.y, rotate);
            let _item = px2Latlng(_transform);
            if (isFinally) {
                _item = [_item.lng, _item.lat];
            }
            res.push(_item);
        }
        return res;
    };
1)latlng2Px

mapbox-gl初始化map自带函数
map.project

2) px2Latlng

mapbox-gl初始化map自带函数
map.unproject

3) 旋转时需要坐标页面xy转换
ts 复制代码
/**
 * TypeScript 中的"transform"函数根据给定的旋转、平移和缩放参数对点执行二维变换。
 * @param {number} x - `x` 参数表示要转换的点的初始 x 坐标。
 * @param {number} y - `transform` 函数中的 `y` 参数表示要转换的点的初始 y 坐标。
 * @param {number} tx - `transform` 函数中的 `tx` 参数表示平移点的 x 坐标。它是应用变换(旋转和缩放)的点的 x 坐标。
 * @param {number} ty - `transform` 函数中的 `ty` 参数表示沿 y 轴的平移。它是点的 y 坐标垂直平移的量。
 * @param {number} deg - `transform` 函数中的 `deg` 参数表示旋转的角度(以度为单位)。
 * @param {number} [sx=1] - `transform` 函数中的 `sx` 参数表示沿 x 轴的缩放因子。它用于缩放被变换点的 x 坐标。默认情况下,如果没有为 `sx`
 * 提供值,则将其设置为 1,表示不沿 x 轴应用缩放
 * @param {number} [sy=1] - `transform` 函数中的 `sy` 参数表示 y 方向的缩放因子。它用于沿 y 轴缩放正在变换的对象。默认情况下,如果没有为 `sy`
 * 提供值,则将其设置为 1,表示在 y 方向上不应用缩放
 * @returns `transform` 函数在对输入位置 `(x, y)` 应用变换后,返回新位置 `[x', y']`。变换涉及围绕点 `(tx, ty)` 旋转 `deg` 度以及按 `sx`
 * 和 `sy` 缩放。
 */
    const transform = (x: number, y: number, tx: number, ty: number, deg: number, sx: number = 1, sy: number = 1): Position => {
        const rad = (Math.PI / 180) * deg;
        const cosRad = Math.cos(rad);
        const sinRad = Math.sin(rad);
        const dx = x - tx;
        const dy = y - ty;

        return [
            sx * (dx * cosRad - dy * sinRad) + tx,
            sy * (dx * sinRad + dy * cosRad) + ty,
        ];
    };

戍、计算纬线count纬线数量,step纬度差

turfAPI
distancedistance
pointpoint

ts 复制代码
/**
 * 函数"calculateLatLines"根据指定的间距计算给定边界内所需的纬线数量。
 * @param bounds - `bounds` 参数是调用 `calculatePolygonBounds` 函数的结果,该函数可能计算多边形的边界框并返回包含边界框角的经纬度坐标的对象。
 * @param {number} space - `calculateLatLines` 函数中的 `space`
 * 参数表示地图上纬线之间的理想间距。此值用于根据指定的间距计算给定边界框内需要多少条纬线。
 * @returns 函数 `calculateLatLines` 返回一个具有两个属性的对象:
 * 1. `count`:根据指定的间距,覆盖给定边界的西北点和西南点之间的距离所需的纬线数量。
 * 2. `step`:每条纬线之间的纬度差,通过将总纬度差除以纬度线数量计算得出。
 */
    const calculateLatLines = (bounds: ReturnType<typeof calculatePolygonBounds>, space: number) => {
        const nw: LatLng = bounds.latlngs[0];
        const sw: LatLng = bounds.latlngs[3];
        const distance = turf.distance(turf.point([nw.lng, nw.lat ]), turf.point([sw.lng, sw.lat]), { units: 'meters' });
        const latLineCount = Math.ceil(distance / space);
        const latDiff =  nw.lat - sw.lat;
        return {
            count: latLineCount,
            step: latDiff / latLineCount,
        };
    };

己、计算纬线与多边形交接点

1) 函数计算给定范围内的包装索引
ts 复制代码
/**
   * `wrapIndex` 函数计算给定范围内的包装索引。
   * @param {number} i - 参数`i`表示索引值,而参数`l`表示数组或列表的长度。
   * @param {number} l - `wrapIndex` 函数中的参数 `l` 表示您正在处理的数组或列表的长度。它用于确定数组索引的有效范围。
   */
    const wrapIndex = (i: number, l: number): number => ((i % l) + l) % l;
2) 计算多边形交接点
ts 复制代码
/**
 * 该函数计算线段与水平线在指定 y 坐标处的交点。
 * @param {Position} p1 - 第一个点的坐标为 [x1, y1]
 * @param {Position} p2 - 您似乎正要提供有关 `calculateIntersectionPoint` 函数中 `p2` 参数的一些信息。我可以如何进一步帮助您?
 * @param {number} y - `calculateIntersectionPoint` 函数中的 `y` 参数表示要找到两个给定点 `p1` 和 `p2` 之间的交点的 y
 * 坐标值。该函数根据提供的 y 坐标和以下坐标计算交点的 x 坐标:
 * @returns 函数"calculateIntersectionPoint"返回一个包含两个数字"[number, number]"的数组(表示交点),如果不满足某些条件,则返回"false"。
 */
    const calculateIntersectionPoint = (p1: Position, p2: Position, y: number): [number, number] | false => {
        const deltaY = p1[1] - p2[1];
        if (deltaY === 0) return false; // 检查分母是否为0,避免除以0

        const deltaX = p1[0] - p2[0];
        const x = (y - p1[1]) * deltaX / deltaY + p1[0];

        // 检查x是否在p1[0]和p2[0]之间
        if ((x > p1[0] && x > p2[0]) || (x < p1[0] && x < p2[0])) return false;

        return [x, y];
    };

庚、过程情况

不去除最大边界

不去除缓冲边界


相关推荐
hong_zc22 分钟前
初始 html
前端·html
小小吱27 分钟前
HTML动画
前端·html
糊涂涂是个小盆友1 小时前
前端 - 使用uniapp+vue搭建前端项目(app端)
前端·vue.js·uni-app
浮华似水1 小时前
Javascirpt时区——脱坑指南
前端
王二端茶倒水1 小时前
大龄程序员兼职跑外卖第五周之亲身感悟
前端·后端·程序员
_oP_i1 小时前
Web 与 Unity 之间的交互
前端·unity·交互
钢铁小狗侠1 小时前
前端(1)——快速入门HTML
前端·html
凹凸曼打不赢小怪兽2 小时前
react 受控组件和非受控组件
前端·javascript·react.js
狂奔solar2 小时前
分享个好玩的,在k8s上部署web版macos
前端·macos·kubernetes
qiyi.sky2 小时前
JavaWeb——Web入门(8/9)- Tomcat:基本使用(下载与安装、目录结构介绍、启动与关闭、可能出现的问题及解决方案、总结)
java·前端·笔记·学习·tomcat