From e50790c3e9efff5064ca8d288e18113632aa7ea6 Mon Sep 17 00:00:00 2001 From: zhaipx Date: Tue, 16 Apr 2024 16:22:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E8=B7=9D=E7=A6=BB?= =?UTF-8?q?=E3=80=81=E6=96=B9=E4=BD=8D=E8=A7=92=E8=AE=A1=E7=AE=97=E3=80=81?= =?UTF-8?q?=E9=9D=A2=E7=A7=AF=E6=B5=8B=E9=87=8F=E4=BA=A4=E4=BA=92=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E7=BB=98=E5=88=B6=E6=8A=98=E7=BA=BF=E3=80=81?= =?UTF-8?q?=E5=A4=9A=E8=BE=B9=E5=BD=A2=E6=97=B6=E5=8F=AF=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/map/BottomBar.vue | 4 +- src/components/map/SceneViewer.vue | 4 +- src/components/toolbar.vue | 16 +++++++ src/utils/map/draw/drawPolygon.ts | 45 ++++++++++++------ src/utils/map/draw/drawPolyline.ts | 53 ++++++++++++--------- src/utils/map/geocomputation.ts | 2 +- src/utils/map/geometry/baseGeometry.ts | 7 +-- src/utils/map/geometry/textLabel.ts | 64 ++++++++++++++++++++++++++ 8 files changed, 149 insertions(+), 46 deletions(-) create mode 100644 src/components/toolbar.vue create mode 100644 src/utils/map/geometry/textLabel.ts diff --git a/src/components/map/BottomBar.vue b/src/components/map/BottomBar.vue index 0d96607..d66961e 100644 --- a/src/components/map/BottomBar.vue +++ b/src/components/map/BottomBar.vue @@ -5,10 +5,9 @@ --> diff --git a/src/components/map/SceneViewer.vue b/src/components/map/SceneViewer.vue index 57c5164..b60fdcb 100644 --- a/src/components/map/SceneViewer.vue +++ b/src/components/map/SceneViewer.vue @@ -69,9 +69,9 @@ onMounted(() => { window.viewer = viewer inputGeoJson(viewer) //绘制多边形 - // const drawPolyline = new CreatePolyline(viewer) + // const drawPolyline = new CreatePolyline(viewer,true,{}) // drawPolyline.start() - const drawPolygon = new DrawPolygon(viewer) + const drawPolygon = new DrawPolygon(viewer,true) drawPolygon.start() }) diff --git a/src/components/toolbar.vue b/src/components/toolbar.vue new file mode 100644 index 0000000..30040a3 --- /dev/null +++ b/src/components/toolbar.vue @@ -0,0 +1,16 @@ + + + + + + diff --git a/src/utils/map/draw/drawPolygon.ts b/src/utils/map/draw/drawPolygon.ts index 91f3a89..d9febe4 100644 --- a/src/utils/map/draw/drawPolygon.ts +++ b/src/utils/map/draw/drawPolygon.ts @@ -6,19 +6,20 @@ * @Description: 绘制多边形 */ import { - Viewer, - ScreenSpaceEventHandler, + CallbackProperty, Cartesian3, Color, - ScreenSpaceEventType, Entity, - CallbackProperty, PolylineDashMaterialProperty, + Rectangle, + ScreenSpaceEventHandler, + ScreenSpaceEventType, + Viewer, } 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' +import {cartesian2ToCartesian3} from '@/utils/map/coordinate' +import {PolygonEntity} from '../geometry/polygonEntity' +import {getPolygonArea} from "@/utils/map/geocomputation.ts"; +import {TextLabel} from "@/utils/map/geometry/textLabel.ts"; export class DrawPolygon { viewer: Viewer @@ -28,9 +29,11 @@ export class DrawPolygon { trackingLine: Entity | null trackingLinePositions: Cartesian3[] = [] bMove: boolean = false + bMeasure = false bLongClick: boolean = false - constructor(viewer: Viewer) { + constructor(viewer: Viewer, isMeasure: boolean=false) { this.viewer = viewer + this.bMeasure = isMeasure this.handler = new ScreenSpaceEventHandler(viewer.scene.canvas) this.polygon = null this.trackingLine = null @@ -130,17 +133,22 @@ export class DrawPolygon { } } } + //左双击回调事件 - private leftDoubleClickCallBack = ( - event: ScreenSpaceEventHandler.PositionedEvent, - ) => { + private leftDoubleClickCallBack = (event: ScreenSpaceEventHandler.PositionedEvent) => { if (!this.polygon) return - console.log('**************************** double click') this.bMove = false //移除多余的点 this.polygon.removePoint(-1) this.polygon.removePoint(-1) + if(this.bMeasure){ + //计算面积 + let area = getPolygonArea(this.positions) + //添加label + new TextLabel(this.viewer,this.getCenter(),`面积: ${(area/1000000).toFixed(2)}k㎡`) + } } + //创建追踪线 createTrackingLine(positions: Cartesian3[]) { return new Entity({ @@ -157,4 +165,15 @@ export class DrawPolygon { }, }) } + + // 获取多边形的外接矩形 + public getRectangle(): Rectangle { + return Rectangle.fromCartesianArray(this.positions) + } + + // 获取几何中心 + public getCenter(): Cartesian3 { + let rec = this.getRectangle() + return Cartesian3.fromRadians((rec.east + rec.west) / 2, (rec.south + rec.north) / 2) + } } diff --git a/src/utils/map/draw/drawPolyline.ts b/src/utils/map/draw/drawPolyline.ts index c61d76f..9f25dbd 100644 --- a/src/utils/map/draw/drawPolyline.ts +++ b/src/utils/map/draw/drawPolyline.ts @@ -20,6 +20,9 @@ import { cartesian2ToCartesian3 } from '@/utils/map/coordinate' import { PolylineEntity } from '../geometry/polylineEntity' import { PointEntity } from '@/utils/map/geometry/pointEntity' import EditGeometry from '@/utils/map/draw/editGeometry' +import {getDistance} from "@/utils/map/geocomputation.ts"; +import {Angle} from "@/utils/map/angle.ts"; +import {TextLabel} from "@/utils/map/geometry/textLabel.ts"; type EntityOptions = { id?: string name?: string @@ -44,6 +47,8 @@ export default class CreatePolyline { moveSelectedPoint: PointEntity | null = null positions: Cartesian3[] = [] bMove: boolean = false + bMeasure: boolean | undefined = false //是否处于测距模式 + totalDistance: number = 0 bLongClick: boolean = false clickTimeout: any // layer: CustomDataSource @@ -54,13 +59,14 @@ export default class CreatePolyline { width: 2, color: Color.GREEN, } - constructor(viewer: Viewer, options?: EntityOptions) { + constructor(viewer: Viewer, bMeasure: boolean=false,options?: EntityOptions) { this.viewer = viewer + this.bMeasure = bMeasure; this.handler = new ScreenSpaceEventHandler(this.viewer.scene.canvas) this.polyline = null this.trackingLine = null this.dashLine = null - + this.totalDistance = 0 this.controlPoints = [] this.defaultStyle = { ...this.defaultStyle, ...options } } @@ -90,21 +96,14 @@ export default class CreatePolyline { public end() { this.handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK) } + //左单击回调事件 - private leftClickCallBack = ( - event: ScreenSpaceEventHandler.PositionedEvent, - ) => { + private leftClickCallBack = (event: ScreenSpaceEventHandler.PositionedEvent) => { const pickedObject = this.viewer.scene.pick(event.position) - // console.log(pickedObject) if (pickedObject) { //点击同一位置,返回 - if ( - pickedObject.id.id === - this.polyline?.controlPointsID[this.positions.length - 1] - ) { + if (pickedObject.id.id === this.polyline?.controlPointsID[this.positions.length - 1]) return - // console.log('********click the same point') - } } const cartesian3 = cartesian2ToCartesian3(this.viewer, event.position) if (cartesian3 != undefined) { @@ -117,8 +116,19 @@ export default class CreatePolyline { this.polyline.addPoint(cartesian3) this.trackingLinePositions[0] = cartesian3 this.bMove = true - this.viewer.scene.requestRender() //刷新 + // 计算2点距离 + if(this.positions.length>=2 && this.bMeasure){ + let distance = getDistance(this.positions[this.positions.length-1],this.positions[this.positions.length-2]) + this.totalDistance += distance + // 计算2点方位角 + let azimuth = Angle.getAzimuth(this.positions[this.positions.length-2],this.positions[this.positions.length-1]) + // 计算2点的中间点 + let midPoint = Cartesian3.midpoint(this.positions[this.positions.length-1],this.positions[this.positions.length-2],new Cartesian3()) + // 添加label + let labelText = `距离: ${distance.toFixed(2)}km, 方位角: ${azimuth}°` + new TextLabel(this.viewer, midPoint,labelText) + } } } // 移动回调事件 @@ -140,13 +150,8 @@ export default class CreatePolyline { } } // 左双击回调事件 - private leftDoubleClickCallBack = ( - event: ScreenSpaceEventHandler.PositionedEvent, - ) => { - // 清除可能已经设置的单击定时器 - // clearTimeout(this.clickTimeout) + private leftDoubleClickCallBack = (event: ScreenSpaceEventHandler.PositionedEvent,) => { if (!this.polyline) return - console.log('**************************** double click') this.bMove = false const cartesian3 = cartesian2ToCartesian3(this.viewer, event.position) if (cartesian3 != undefined) { @@ -156,9 +161,12 @@ export default class CreatePolyline { } } + if(this.bMeasure){ + // 添加总距离label + new TextLabel(this.viewer,this.positions[this.positions.length-1], + `总距离: ${this.totalDistance.toFixed(2)}km`) + } this.clearEvent() - console.log('end:' + this.positions.length.toString()) - console.log(this.positions) //结束绘制进入编辑模式 this.polyline.removeControlPoints() const editTool = new EditGeometry(this.viewer, this.polyline.geometry!) @@ -173,7 +181,8 @@ export default class CreatePolyline { this.viewer.entities.remove(this.controlPoints.pop() as Entity) } } - clearEvent() { + + private clearEvent() { this.handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK) this.handler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE) this.handler.removeInputAction(ScreenSpaceEventType.LEFT_DOUBLE_CLICK) diff --git a/src/utils/map/geocomputation.ts b/src/utils/map/geocomputation.ts index 674d083..9134727 100644 --- a/src/utils/map/geocomputation.ts +++ b/src/utils/map/geocomputation.ts @@ -88,7 +88,7 @@ function isOnLineSegment( /** - * 计算距离,单位米 + * 计算距离,单位千米 * @param p1 起点 * @param p2 终点 */ diff --git a/src/utils/map/geometry/baseGeometry.ts b/src/utils/map/geometry/baseGeometry.ts index 58fb8ab..2099c6c 100644 --- a/src/utils/map/geometry/baseGeometry.ts +++ b/src/utils/map/geometry/baseGeometry.ts @@ -38,13 +38,10 @@ export abstract class BaseGeometry extends CustomDataSource { * 新增一个节点,默认插入在尾部, * @param pos 点坐标 * @param index 插入的位置,0起步 + * @param bAddControlPoint * @bAddControlPoint 是否添加控制点 */ - public addPoint( - pos: Cartesian3, - index: number = -1, - bAddControlPoint: boolean = true, - ) { + public addPoint(pos: Cartesian3, index: number = -1, bAddControlPoint: boolean = true,) { if (index === -1) { //插入尾部 this.positions.push(pos) diff --git a/src/utils/map/geometry/textLabel.ts b/src/utils/map/geometry/textLabel.ts new file mode 100644 index 0000000..0fc91bb --- /dev/null +++ b/src/utils/map/geometry/textLabel.ts @@ -0,0 +1,64 @@ +import {Cartesian3, Entity, Color, Viewer, Cartesian2, HorizontalOrigin, VerticalOrigin, HeightReference} from "cesium"; + +/** + 文件描述:文本标注 + 创建时间:2024/4/16 11:44 + 创建人:Zhaipeixiu + */ +export type textLabelOptions = { + showBackground?: boolean, //显示背景 + backgroundColor?: Color, //背景色 + backgroundPadding?: any, //padding值 + fillColor: Color, + horizontalOrigin?: any, //水平对齐方式 + verticalOrigin?: any, //竖直对齐方式 + outlineColor?: any, + outlineWidth?: any +} + +export class TextLabel{ + _viewer: Viewer|undefined = undefined + _defaultStyle: textLabelOptions = { + showBackground: true, //显示背景 + backgroundColor: Color.BLACK, //背景色 + backgroundPadding: new Cartesian2(10, 10), //padding值 + fillColor: Color.WHITE, + outlineColor: Color.WHITESMOKE, + outlineWidth: 1.0, + horizontalOrigin: HorizontalOrigin.CENTER,//对齐方式 + verticalOrigin: VerticalOrigin.CENTER, + } + _cesiumLabel: Entity|undefined = undefined + + // 构造函数,新建label并显示 + constructor(viewer: Viewer, position: Cartesian3, text: string, options?: textLabelOptions) { + this._viewer = viewer + this._defaultStyle = {...this._defaultStyle, ...options} + + this._cesiumLabel = new Entity({ + position: position, + name: 'default', + label: { + text: text, + scale: .6, + pixelOffset: new Cartesian2(20, -20), + showBackground: this._defaultStyle.showBackground, //显示背景 + backgroundColor: this._defaultStyle.backgroundColor, //背景色 + backgroundPadding: this._defaultStyle.backgroundPadding, //padding值 + fillColor: this._defaultStyle.fillColor, + outlineColor: this._defaultStyle.outlineColor, + outlineWidth: this._defaultStyle.outlineWidth, + horizontalOrigin: this._defaultStyle.horizontalOrigin, //对齐方式 + verticalOrigin: this._defaultStyle.verticalOrigin, + heightReference: HeightReference.CLAMP_TO_GROUND + } + }) + this._viewer.entities.add(this._cesiumLabel) + } + + //移除label + public remove(){ + if(this._cesiumLabel !== undefined && this._viewer!==null) + this._viewer.entities.remove(this._cesiumLabel) + } +}