diff --git a/src/components/map/BottomBar.vue b/src/components/map/BottomBar.vue index 7d1aa18..0684f78 100644 --- a/src/components/map/BottomBar.vue +++ b/src/components/map/BottomBar.vue @@ -5,36 +5,40 @@ --> diff --git a/src/utils/DataIO.ts b/src/utils/DataIO.ts index 08d49b6..ffcecee 100644 --- a/src/utils/DataIO.ts +++ b/src/utils/DataIO.ts @@ -1,5 +1,5 @@ /* * @Author: zhaipx * @Date: {2024/4/11} - * @Description: + * @Description: */ diff --git a/src/utils/map/angle.ts b/src/utils/map/angle.ts index 3e6e8cb..f651cd6 100644 --- a/src/utils/map/angle.ts +++ b/src/utils/map/angle.ts @@ -1,57 +1,67 @@ -import {getAzimuth} from "@/utils/map/geocomputation.ts"; -import {Cartesian3} from "cesium"; +import { getAzimuth } from '@/utils/map/geocomputation.ts' +import { Cartesian3 } from 'cesium' class Angle { - constructor() {} + constructor() {} - /** - * 十进制经纬度转度分秒,精确至毫秒 - * @param decimal_var 十进制经纬度 - * @constructor - */ - static DecimalDegree2DMS(decimal_var: number|string){ - if(!decimal_var.toString().includes('.')) - return decimal_var.toString() + '°0\'0\'\'' - let decimalStr = decimal_var.toString().split('.') - let degreeStr = decimalStr[0] - if (decimalStr[1]){ - let minutes = Number(decimalStr[1]) / Math.pow(10,decimalStr[1].length) * 60 - if(!minutes.toString().includes('.')) - return degreeStr + '°'+ minutes.toString() +'\'0\'\'' - let minuteSecondsStr = minutes.toString().split('.') - if (minuteSecondsStr[1]){ - let secondStr = Number(minuteSecondsStr[1]) / Math.pow(10,minuteSecondsStr[1].length) * 60 - return degreeStr + '°'+ minuteSecondsStr[0] +'\'' + secondStr.toFixed(3) + '\'\'' - } - } - return '' + /** + * 十进制经纬度转度分秒,精确至毫秒 + * @param decimal_var 十进制经纬度 + * @constructor + */ + static DecimalDegree2DMS(decimal_var: number | string) { + if (!decimal_var.toString().includes('.')) + return decimal_var.toString() + "°0'0''" + let decimalStr = decimal_var.toString().split('.') + let degreeStr = decimalStr[0] + if (decimalStr[1]) { + let minutes = + (Number(decimalStr[1]) / Math.pow(10, decimalStr[1].length)) * 60 + if (!minutes.toString().includes('.')) + return degreeStr + '°' + minutes.toString() + "'0''" + let minuteSecondsStr = minutes.toString().split('.') + if (minuteSecondsStr[1]) { + let secondStr = + (Number(minuteSecondsStr[1]) / + Math.pow(10, minuteSecondsStr[1].length)) * + 60 + return ( + degreeStr + + '°' + + minuteSecondsStr[0] + + "'" + + secondStr.toFixed(3) + + "''" + ) + } } + return '' + } - /** - * 计算方位角,单位度 - * @param p1 起点 - * @param p2 终点 - * @param digits 保留小数位数,默认保留1位小数 - */ - static getAzimuth(p1: Cartesian3, p2: Cartesian3, digits=1){ - return getAzimuth(p1, p2, digits) - } - - /** - * 十进制度转弧度 - * @param degree 十进制度 - */ - static degree2rad(degree: number): number { - return Math.PI/180 * degree - } - /** - * 弧度转十进制度 - * @param rad 弧度 - */ - static rad2degree(rad: number): number { - return 180/Math.PI * rad - } + /** + * 计算方位角,单位度 + * @param p1 起点 + * @param p2 终点 + * @param digits 保留小数位数,默认保留1位小数 + */ + static getAzimuth(p1: Cartesian3, p2: Cartesian3, digits = 1) { + return getAzimuth(p1, p2, digits) + } + /** + * 十进制度转弧度 + * @param degree 十进制度 + */ + static degree2rad(degree: number): number { + return (Math.PI / 180) * degree + } + /** + * 弧度转十进制度 + * @param rad 弧度 + */ + static rad2degree(rad: number): number { + return (180 / Math.PI) * rad + } } export { Angle } diff --git a/src/utils/map/draw/drawPolygon.ts b/src/utils/map/draw/drawPolygon.ts new file mode 100644 index 0000000..91f3a89 --- /dev/null +++ b/src/utils/map/draw/drawPolygon.ts @@ -0,0 +1,160 @@ +/* + * @Author: cbwu 504-wuchengbo@htsdfp.com + * @Date: 2024-04-11 13:53:40 + * @LastEditors: cbwu + * @LastEditTime: 2024-04-12 15:18:40 + * @Description: 绘制多边形 + */ +import { + Viewer, + ScreenSpaceEventHandler, + Cartesian3, + Color, + ScreenSpaceEventType, + Entity, + CallbackProperty, + PolylineDashMaterialProperty, +} from 'cesium' +import { cartesian2ToCartesian3 } from '@/utils/map/coordinate' +import { PolygonEntity } from '../geometry/polygonEntity' +import { PointEntity } from '@/utils/map/geometry/pointEntity' +import EditGeometry from '@/utils/map/draw/editGeometry' + +export class DrawPolygon { + viewer: Viewer + handler: ScreenSpaceEventHandler + polygon: PolygonEntity | null + positions: Cartesian3[] = [] + trackingLine: Entity | null + trackingLinePositions: Cartesian3[] = [] + bMove: boolean = false + bLongClick: boolean = false + constructor(viewer: Viewer) { + this.viewer = viewer + this.handler = new ScreenSpaceEventHandler(viewer.scene.canvas) + this.polygon = null + this.trackingLine = null + } + public start() { + // 左单击加点 + this.handler.setInputAction( + this.leftClickCallBack, + ScreenSpaceEventType.LEFT_CLICK, + ) + // 移动动态绘制 + this.handler.setInputAction( + this.moveCallBack, + ScreenSpaceEventType.MOUSE_MOVE, + ) + // 左双击结束 + this.handler.setInputAction( + this.leftDoubleClickCallBack, + ScreenSpaceEventType.LEFT_DOUBLE_CLICK, + ) + } + //左单击回调事件 + private leftClickCallBack = ( + event: ScreenSpaceEventHandler.PositionedEvent, + ) => { + const pickedObject = this.viewer.scene.pick(event.position) + // console.log(pickedObject) + if (pickedObject) { + //点击同一位置,返回 + if ( + pickedObject.id.id === + this.polygon?.controlPointsID[this.positions.length - 1] + ) { + console.log('********click the same point') + return + } + } + console.log('****************leftClick!') + const cartesian3 = cartesian2ToCartesian3(this.viewer, event.position) + if (cartesian3 != undefined) { + if (this.positions.length <= 2) { + this.positions.push(cartesian3) + this.trackingLinePositions.push(cartesian3) + } else { + this.polygon!.modifyPoint(cartesian3, -1) + this.polygon!.showControlPoint(-1, true) + //多创建一个点,用于鼠标移动实时变化 + this.polygon!.addPoint(cartesian3, -1) + this.polygon!.showControlPoint(-1, false) + + this.trackingLinePositions[2] = cartesian3 + } + this.bMove = true + this.viewer.scene.requestRender() //刷新 + } + } + //移动回调事件 + private moveCallBack = (event: ScreenSpaceEventHandler.MotionEvent) => { + if (this.bMove) { + const cartesian3 = cartesian2ToCartesian3(this.viewer, event.endPosition) + if (cartesian3 != undefined) { + if (this.positions.length === 1) { + //更新追踪线坐标 + this.trackingLinePositions[1] = cartesian3 + // this.positions[1] = cartesian3 + if (!this.trackingLine) { + //创建追踪线对象 + this.trackingLine = this.createTrackingLine( + this.trackingLinePositions, + ) + this.viewer.entities.add(this.trackingLine) + } + } + if (this.positions.length === 2) { + //移除追踪直线 + if (this.trackingLine) { + this.viewer.entities.remove(this.trackingLine) + } + this.positions.push(cartesian3) + console.log( + '*********PositionsLength:' + this.positions.length.toString(), + ) + //创建多边形 + if (!this.polygon) { + this.polygon = new PolygonEntity(this.positions) + this.viewer.dataSources.add(this.polygon) + // 实时移动不显示控制点 + this.polygon.showControlPoint(-1, false) + } + } + //实时改变多边形 + if (this.positions.length >= 3) { + this.polygon!.modifyPoint(cartesian3, -1) + } + + this.viewer.scene.requestRender() //刷新 + } + } + } + //左双击回调事件 + private leftDoubleClickCallBack = ( + event: ScreenSpaceEventHandler.PositionedEvent, + ) => { + if (!this.polygon) return + console.log('**************************** double click') + this.bMove = false + //移除多余的点 + this.polygon.removePoint(-1) + this.polygon.removePoint(-1) + } + //创建追踪线 + createTrackingLine(positions: Cartesian3[]) { + return new Entity({ + polyline: { + positions: new CallbackProperty(() => { + return positions + }, false), + width: 2, + material: new PolylineDashMaterialProperty({ + color: Color.GREEN, + dashLength: 15, //短划线长度 + }), + clampToGround: true, + }, + }) + } +} diff --git a/src/utils/map/draw/drawPolyline.ts b/src/utils/map/draw/drawPolyline.ts index 743522a..df931e7 100644 --- a/src/utils/map/draw/drawPolyline.ts +++ b/src/utils/map/draw/drawPolyline.ts @@ -2,7 +2,7 @@ * @Author: cbwu 504-wuchengbo@htsdfp.com * @Date: 2024-03-27 08:43:44 * @LastEditors: cbwu - * @LastEditTime: 2024-04-02 13:33:25 + * @LastEditTime: 2024-04-12 09:06:27 * @Description: 绘制Polyline类 */ import { @@ -178,7 +178,7 @@ export default class CreatePolyline { this.handler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE) this.handler.removeInputAction(ScreenSpaceEventType.LEFT_DOUBLE_CLICK) } - + //创建追踪线 createTrackingLine(positions: Cartesian3[]) { return new Entity({ polyline: { diff --git a/src/utils/map/drawer.ts b/src/utils/map/drawer.ts index 8015732..9a73f82 100644 --- a/src/utils/map/drawer.ts +++ b/src/utils/map/drawer.ts @@ -2,7 +2,7 @@ * @Author: cbwu 504-wuchengbo@htsdfp.com * @Date: 2024-03-15 08:43:26 * @LastEditors: cbwu - * @LastEditTime: 2024-03-26 14:20:32 + * @LastEditTime: 2024-04-12 10:30:36 * @FilePath: \GCSMap\src\utils\drawer.ts * @Description: 矢量要素绘制工具类 */ diff --git a/src/utils/map/geocomputation.ts b/src/utils/map/geocomputation.ts index f0719b8..0777547 100644 --- a/src/utils/map/geocomputation.ts +++ b/src/utils/map/geocomputation.ts @@ -5,7 +5,14 @@ * @LastEditTime: 2024-04-01 14:05:43 * @Description: 地理计算 */ -import {Cartesian3, Cartographic, EllipsoidGeodesic, Math as Cesium_Math, Matrix4, Transforms} from 'cesium' +import { + Cartesian3, + Cartographic, + EllipsoidGeodesic, + Math as Cesium_Math, + Matrix4, + Transforms, +} from 'cesium' /** * 计算空间中一点到一条直线的最短距离的交点(在不考虑地球曲率的情况下) * @param lineStart 直线的起点:[longitude1, latitude1, height1] @@ -84,20 +91,18 @@ function isOnLineSegment( */ } - /** * 计算距离,单位米 * @param p1 起点 * @param p2 终点 */ -function getDistance(p1:Cartesian3, p2: Cartesian3): number -{ - let point1cartographic = Cartographic.fromCartesian(p1); - let point2cartographic = Cartographic.fromCartesian(p2); +function getDistance(p1: Cartesian3, p2: Cartesian3): number { + let point1cartographic = Cartographic.fromCartesian(p1) + let point2cartographic = Cartographic.fromCartesian(p2) /**根据经纬度计算出距离**/ let geodesic = new EllipsoidGeodesic() geodesic.setEndPoints(point1cartographic, point2cartographic) - return geodesic.surfaceDistance/1000 + return geodesic.surfaceDistance / 1000 } /** @@ -106,20 +111,30 @@ function getDistance(p1:Cartesian3, p2: Cartesian3): number * @param p2 终点 * @param digits 保留小数位数,默认为保留1位小数 */ -function getAzimuth(p1:Cartesian3, p2: Cartesian3, digits=1): string -{ +function getAzimuth(p1: Cartesian3, p2: Cartesian3, digits = 1): string { // 建立局部坐标系:北为y,东为x,p1为原点 const localMatrix = Transforms.eastNorthUpToFixedFrame(p1) //求世界坐标到局部坐标的变换矩阵 const worldToLocalMatrix = Matrix4.inverse(localMatrix, new Matrix4()) //p1在局部坐标系的位置,即局部坐标原点 - const localPosition1 = Matrix4.multiplyByPoint(worldToLocalMatrix, p1, new Cartesian3()) + const localPosition1 = Matrix4.multiplyByPoint( + worldToLocalMatrix, + p1, + new Cartesian3(), + ) //p2在局部坐标系的位置 - const localPosition2 = Matrix4.multiplyByPoint(worldToLocalMatrix, p2, new Cartesian3()) + const localPosition2 = Matrix4.multiplyByPoint( + worldToLocalMatrix, + p2, + new Cartesian3(), + ) //弧度 - const angle = Math.atan2(localPosition2.x - localPosition1.x, localPosition2.y - localPosition1.y) + const angle = Math.atan2( + localPosition2.x - localPosition1.x, + localPosition2.y - localPosition1.y, + ) //转为角度 - let theta = angle * (180 / Math.PI); + let theta = angle * (180 / Math.PI) theta = theta < 0 ? theta + 360 : theta return theta.toFixed(digits) } @@ -139,4 +154,10 @@ function getPolygonArea(vertexs: Cartesian3[]) { return Math.abs(area) } -export { getClosestPoint, isOnLineSegment, getDistance, getAzimuth, getPolygonArea } +export { + getClosestPoint, + isOnLineSegment, + getDistance, + getAzimuth, + getPolygonArea, +} diff --git a/src/utils/map/geometry/baseGeometry.ts b/src/utils/map/geometry/baseGeometry.ts index 3a1804b..5aab807 100644 --- a/src/utils/map/geometry/baseGeometry.ts +++ b/src/utils/map/geometry/baseGeometry.ts @@ -2,7 +2,7 @@ * @Author: cbwu 504-wuchengbo@htsdfp.com * @Date: 2024-03-28 16:22:58 * @LastEditors: cbwu - * @LastEditTime: 2024-04-02 14:09:15 + * @LastEditTime: 2024-04-12 14:57:49 * @Description: 几何类抽象基类 */ import { @@ -37,16 +37,21 @@ export abstract class BaseGeometry extends CustomDataSource { * 新增一个节点,默认插入在尾部, * @param pos 点坐标 * @param index 插入的位置,0起步 + * @bAddControlPoint 是否添加控制点 */ - public addPoint(pos: Cartesian3, index: number = -1) { + public addPoint( + pos: Cartesian3, + index: number = -1, + bAddControlPoint: boolean = true, + ) { if (index === -1) { //插入尾部 this.positions.push(pos) - // console.log(this.positions.length) - this.createPoint(pos, this.positions.length - 1) + if (bAddControlPoint) + this.createControlPoint(pos, this.positions.length - 1) } else if (index >= 0 && index < this.positions.length) { this.positions.splice(index, 0, pos) - this.createPoint(pos, index) + if (bAddControlPoint) this.createControlPoint(pos, index) } else { return } @@ -62,11 +67,11 @@ export abstract class BaseGeometry extends CustomDataSource { this.positions.pop() } else if (index >= 0 && index < this.positions.length) { this.positions.splice(index, 1) - this.entities.removeById(this.controlPointsID[index]) - this.controlPointsID.splice(index, 1) } else { return } + //移除控制点 + this.removeControlPoint(index) } /** * 修改某点的坐标 @@ -74,12 +79,17 @@ export abstract class BaseGeometry extends CustomDataSource { * @param index 修改点的位置 */ public modifyPoint(pos: Cartesian3, index: number) { + if (index === -1) { + index = this.positions.length - 1 + } if (index >= 0 && index < this.positions.length) { this.positions.splice(index, 1, pos) - //修改控制点坐标 - const point = this.entities.getById(this.controlPointsID[index]) - if (point) { - point.position = new ConstantPositionProperty(pos) + if (this.controlPointsID[index]) { + //修改控制点坐标 + const point = this.entities.getById(this.controlPointsID[index]) + if (point) { + point.position = new ConstantPositionProperty(pos) + } } } } @@ -88,7 +98,7 @@ export abstract class BaseGeometry extends CustomDataSource { * @param pos 点的坐标 * @param index 插入的位置,0起步 */ - createPoint(pos: Cartesian3, index: number) { + public createControlPoint(pos: Cartesian3, index: number) { // if (this.geometry) { const point = new PointEntity(pos) point.parent = this.geometry! @@ -97,6 +107,17 @@ export abstract class BaseGeometry extends CustomDataSource { this.controlPointsID.splice(index, 0, point.id) // } } + /** + * 移除控制点 + * @param index 控制点下标号 + */ + public removeControlPoint(index: number) { + if (index === -1) index = this.controlPointsID.length - 1 + if (this.controlPointsID[index]) { + this.entities.removeById(this.controlPointsID[index]) + this.controlPointsID.splice(index, 1) + } + } /** * 清空所有控制点 */ @@ -106,4 +127,16 @@ export abstract class BaseGeometry extends CustomDataSource { }) this.controlPointsID = [] } + /** + * 设置控制点是否显示 + * @param index 控制点下标号 + * @param bShow 是否显示 + */ + showControlPoint(index: number, bShow: boolean) { + if (index === -1) index = this.controlPointsID.length - 1 + if (this.controlPointsID[index]) { + const point = this.entities.getById(this.controlPointsID[index]) + if (point) point.show = bShow + } + } } diff --git a/src/utils/map/geometry/pointEntity.ts b/src/utils/map/geometry/pointEntity.ts index ec8878b..de0a02e 100644 --- a/src/utils/map/geometry/pointEntity.ts +++ b/src/utils/map/geometry/pointEntity.ts @@ -2,7 +2,7 @@ * @Author: cbwu 504-wuchengbo@htsdfp.com * @Date: 2024-03-28 16:35:33 * @LastEditors: cbwu - * @LastEditTime: 2024-03-30 22:06:23 + * @LastEditTime: 2024-04-12 15:43:49 * @Description: 封装的点几何类 */ import { @@ -39,8 +39,9 @@ class PointEntity extends Entity { id: 'Point' + String(PointEntity.ID), name: 'Point' + String(PointEntity.ID + 1), show: true, - pixelSize: 10, - color: Color.GREEN, + pixelSize: 8, + color: Color.WHITE, + outlineColor: Color.GREEN, outlineWidth: 0, } constructor(position: Cartesian3, options?: EntityOptions) { diff --git a/src/utils/map/geometry/polygonEntity.ts b/src/utils/map/geometry/polygonEntity.ts index 87f94fa..4a29c73 100644 --- a/src/utils/map/geometry/polygonEntity.ts +++ b/src/utils/map/geometry/polygonEntity.ts @@ -2,7 +2,7 @@ * @Author: cbwu 504-wuchengbo@htsdfp.com * @Date: 2024-04-11 09:26:56 * @LastEditors: cbwu - * @LastEditTime: 2024-04-11 13:26:25 + * @LastEditTime: 2024-04-12 15:34:45 * @Description: 封装的Polygon对象 */ import { @@ -10,8 +10,7 @@ import { Cartesian3, Color, CallbackProperty, - Property, - PolygonGraphics, + PolygonHierarchy, } from 'cesium' import { BaseGeometry } from './baseGeometry' import { type EntityOptions } from './pointEntity' @@ -28,20 +27,30 @@ export class PolygonEntity extends BaseGeometry { fillColor: Color.RED.withAlpha(0.5), fill: true, } - constructor(ptArr: Cartesian3[] | Property, options?: EntityOptions) { + constructor(ptArr: Cartesian3[], options?: EntityOptions) { super() + this.positions = ptArr this.options = { ...this.options, ...options } this.geometry = new Entity({ show: this.options.show, name: this.options.name, polygon: { - hierarchy: ptArr, + hierarchy: new CallbackProperty(() => { + return new PolygonHierarchy(this.positions) + }, false), material: this.options.fillColor, //填充颜色 fill: this.options.fill, //是否填充 - outlineWidth: this.options.width, //线宽 + outline: true, + // outlineWidth: this.options.width, //线宽 outlineColor: this.options.color, //线颜色 }, }) + this.entities.add(this.geometry) + // 添加控制点 + ptArr.forEach((pt, index) => { + this.createControlPoint(pt, index) + }) + PolygonEntity.ID++ } } diff --git a/src/utils/map/geometry/polylineEntity.ts b/src/utils/map/geometry/polylineEntity.ts index 026ea28..bb07f25 100644 --- a/src/utils/map/geometry/polylineEntity.ts +++ b/src/utils/map/geometry/polylineEntity.ts @@ -2,7 +2,7 @@ * @Author: cbwu 504-wuchengbo@htsdfp.com * @Date: 2024-03-28 16:49:02 * @LastEditors: cbwu - * @LastEditTime: 2024-04-01 17:04:55 + * @LastEditTime: 2024-04-12 14:27:12 * @Description: 封装的Polyline类 */ import { Entity, Cartesian3, Color, CallbackProperty } from 'cesium' @@ -40,7 +40,7 @@ export class PolylineEntity extends BaseGeometry { this.entities.add(this.geometry) // 添加控制点 ptArr.forEach((pt, index) => { - this.createPoint(pt, index) + this.createControlPoint(pt, index) }) PolylineEntity.ID++