/// /// /// import { area, distance, Feature, featureCollection, lineString, LineString, multiPolygon, point, Point, polygon, Polygon, } from "@turf/turf"; import BaseDraw from "./../BaseDraw"; import PolygonRender from "./IRender"; import IHPaaS from "../../../../../modules/hpaas-core/IHPaaS"; import PolygonRenderL7 from "./renderL7"; import PolygonRenderDeckGL from "./renderDeckGL"; import ToolsCenter from "../../ToolsCenter"; import { PolygonFeatureType } from "../../data/PolygonStore"; let completePolygonCount = 0; export interface mouseEventType { lnglat: { lng: number; lat: number; }; feature: Feature; } class PolygonDraw extends BaseDraw { // 当形成 polygon 的时候,当前正在画的 polygon 数据 private drawingPolygon?: Feature; // 正在画的feature,不一定是polygon private drawingFeature?: Feature; private render: PolygonRender; private drawingPoints: { lng: number; lat: number; }[] = []; private drawingPointsTotalArea = 0; private moveingPoint = { lng: 0, lat: 0, }; private isDrawing = false; private type: "byroad" | "line" | "quickline" = "quickline"; private lastAddPointTime = new Date().getTime(); private drivingInstance?: AMap.Driving; // 是否自动吸附基础路段上的点 private pinToBaseUnit = true; // 是否自动吸附到其他的区域上 private pinToOtherArea = false; inited = false; hpaas: IHPaaS; public toolsCenter: ToolsCenter; constructor(toolsCenter: ToolsCenter, options: { type?: "byroad" | "line" | "quickline" } = {}) { super(); this.toolsCenter = toolsCenter; this.hpaas = toolsCenter.hpaas; if (options.type) { this.type = options.type; } if (this.hpaas.type == "L7") { this.render = new PolygonRenderL7(this); } else { this.render = new PolygonRenderDeckGL(this); } if (this.type == "byroad") { this._initDrive(); } if (!this.inited) { this.inited = true; this.render?.initLayer(); this._bindEvent(); } } _initDrive() { if (window.AMap) { this.drivingInstance = new AMap.Driving({ // map: this.hpaas.mapInstance.amapInstance, policy: AMap.DrivingPolicy.LEAST_TIME, }); } } _bindEvent() { this.render.bindEvent({ mousemove: this._mousemoveEventHandler, click: this._mouseclickEventHandler, contextmenu: this.contextmenuEventHandler, }); // this.hpaas.scene.on("mousemove", this._mousemoveEventHandler); // this.hpaas.scene.on("click", this._mouseclickEventHandler); // this.hpaas.scene.on("contextmenu", this.contextmenuEventHandler); // this.bgLayer?.on("mousedown", this.polygonMouseDownHandler); // this.hpaas.scene.on("mouseup", this.polygonMouseUpHandler); } contextmenuEventHandler = (e: any) => { if (this.isDrawing) { // this.isDrawing = false; this._drawPointsToCompletePolygon(); this.renderData(); } }; _mouseclickEventHandler = (e: mouseEventType) => { if (this.isDrawing && e) { // console.log(e, draggingPointModel); if (this.type == "line" || this.type == "quickline") { // 折线的时候,点击代表结束 const lng = e.lnglat.lng; const lat = e.lnglat.lat; this.drawingPoints.push({ lng, lat }); // if (this.drawingPoints.length > 3) { // this._drawPointsToCompletePolygon(); // } this.renderData(); } else if (this.type == "byroad") { const lng = e.lnglat.lng; const lat = e.lnglat.lat; const lastPoint = this.drawingPoints[this.drawingPoints.length - 1]; if (lastPoint) { this.drivingInstance && this.drivingInstance.search( new AMap.LngLat(lastPoint.lng, lastPoint.lat), new AMap.LngLat(lng, lat), (status, result) => { if (status == "complete") { const res = result as AMap.Driving.SearchResultBase; const steps = res.routes[0].steps; let temps: AMap.LngLat[] = []; for (let i = 0; i < steps.length; i++) { const element = steps[i]; temps = temps.concat(element.path); } for (let m = 0; m < temps.length; m++) { const p = temps[m]; this.drawingPoints.push({ lng: p.getLng(), lat: p.getLat() }); } this.renderData(); } } ); } else { const lng = e.lnglat.lng; const lat = e.lnglat.lat; this.drawingPoints.push({ lng, lat }); this.renderData(); } } // this.pointLayer.setData(this.points); } }; _mousemoveEventHandler = (e: mouseEventType) => { if (this.isDrawing) { const lng = e.lnglat.lng; const lat = e.lnglat.lat; if (this.type == "quickline") { const nowTime = new Date().getTime(); if (nowTime - this.lastAddPointTime > 100 && this.drawingPoints.length > 1) { const lastPoint = this.drawingPoints[this.drawingPoints.length - 1]; const _distance = distance([lng, lat], [lastPoint.lng, lastPoint.lat], { units: "kilometers", }); if (_distance > 0.001) { console.log("add point"); this.drawingPoints.push({ lng, lat }); this.lastAddPointTime = nowTime; } } } this.renderData(); if (this.drawingPoints.length == 0) { this.render.popup?.html( `
点击开始绘制
${ this.type == "quickline" ? "然后移动🖱自动添加点" : "点击继续添加点" }
右击停止绘制
` ); this.render.popup?.pos({ lng, lat }); this.render.popup?.show(); } else { this.render.popup?.html( `
总面积:${this.drawingPointsTotalArea.toFixed( 2 )}平方千米
右击停止绘制
` ); this.render.popup?.pos({ lng, lat }); this.render.popup?.show(); } // this.popup && this.hpaas.scene.addPopup(this.popup); } }; _calcDistanceByAddPoint(lng: number, lat: number) { const lastPoint = this.drawingPoints[this.drawingPoints.length - 1]; const _distance = distance([lng, lat], [lastPoint.lng, lastPoint.lat], { units: "kilometers", }); } _drawPointsToCompletePolygon() { if (!this.drawingPolygon) return; this.drawingPolygon.id = "complete_" + completePolygonCount++; const multipolygon = multiPolygon([this.drawingPolygon.geometry.coordinates]); this.toolsCenter.drawLayer.addData([multipolygon as PolygonFeatureType]); this.emit("complete_feature", multipolygon); // this.completePolygons.push(multiPolygon([this.drawingPolygon.geometry.coordinates])); this.drawingPolygon = undefined; this.drawingFeature = undefined; this.drawingPoints = []; this.drawingPointsTotalArea = 0; } updateDrawingFeature() { const drawPoints = Array.from(this.drawingPoints); if (this.moveingPoint.lng) { drawPoints.push(this.moveingPoint); } if (drawPoints.length == 1) { const _point = drawPoints[0]; this.drawingFeature = point([_point.lng, _point.lat]) as Feature; } else if (drawPoints.length == 2) { const startPoint = drawPoints[0]; const endPoint = drawPoints[1]; this.drawingFeature = lineString([ [startPoint.lng, startPoint.lat], [endPoint.lng, endPoint.lat], ]) as Feature; } else if (drawPoints.length > 2) { if (drawPoints.length > 0) { drawPoints.push(drawPoints[0]); } this.drawingFeature = polygon([ drawPoints.map((p) => { return [p.lng, p.lat]; }), ]) as Feature; this.drawingPolygon = this.drawingFeature as Feature; this.drawingPointsTotalArea = area(this.drawingPolygon) / 1000000; } } renderData() { this.updateDrawingFeature(); if (this.drawingFeature?.geometry.type == "Point") { const polygonCollection = featureCollection([]); polygonCollection.features = polygonCollection.features.concat(this.completePolygons); this.render.render(polygonCollection, this.drawingPoints); this.render.popup.hide(); } else if (this.drawingFeature?.geometry.type == "LineString") { const polygonCollection = featureCollection([]); polygonCollection.features = polygonCollection.features.concat(this.completePolygons); this.render.render(polygonCollection, this.drawingPoints); this.render.popup.show(); } else if (this.drawingFeature?.geometry.type == "Polygon") { const polygonCollection = featureCollection([multiPolygon([this.drawingFeature.geometry.coordinates])]); polygonCollection.features = polygonCollection.features.concat(this.completePolygons); this.render.render(polygonCollection, this.drawingPoints); this.render.popup.show(); } else { const polygonCollection = featureCollection([]); polygonCollection.features = polygonCollection.features.concat(this.completePolygons); this.render.render(polygonCollection, this.drawingPoints); this.render.popup.hide(); } } begin() { this.isDrawing = true; } end() { this._drawPointsToCompletePolygon(); this.isDrawing = false; this.render.popup.hide(); } clear() { this.isDrawing = false; this.completePolygons = []; this.drawingPoints = []; this.drawingPolygon = undefined; this.drawingFeature = undefined; this.drawingPointsTotalArea = 0; this.render.popup.hide(); this.renderData(); } } export default PolygonDraw;