可以在地图上绘制点,线,面,并且根据绘制的点线面绘制缓冲区。
1.用cesium的handle进行点线面绘制。
2.用turf.buffer函数对绘制的点线面进行缓冲区分析。
3.在地图上绘制缓冲区。
import {
buffer, point, lineString, polygon,
} from '@turf/turf';
import bus from '../../eventBus';
interface Position {
lon: number;
lat: number;
alt: number;
}
const { Cesium, }: any = window;
export default class Buffer {
viewer: any;
drawLayer:any;
handler: any;
radius = 1000;
constructor (viewer: any | unknown, options = { basePath: '', }) {
this.viewer = viewer;
this.drawLayer = new Cesium.CustomDataSource('measureLayer');
this.viewer.dataSources.add(this.drawLayer);
}
/**
* 坐标转换 84转笛卡尔
* @param {Position} position 位置
* @param {number} alt 高度
* @returns {any} 笛卡尔坐标
*/
transformWGS84ToCartesian = (position: Position, alt = 0): any => (position ?
Cesium.Cartesian3.fromDegrees(
position.lon,
position.lat,
alt || position.alt,
Cesium.Ellipsoid.WGS84
) :
Cesium.Cartesian3.ZERO)
/**
* 坐标数组转换 笛卡尔转84
* @param {Array} WSG84Arr {lon,lat,alt} 地理坐标数组
* @param {Number} alt 拔高
* @return {Array} Cartesian3 三维位置坐标数组
*/
transformWGS84ArrayToCartesianArray (WSG84Arr: number[], alt: number): any[] {
return WSG84Arr ?
WSG84Arr.map((item: any) => this.transformWGS84ToCartesian(item, alt)) :
[];
}
/**
* 坐标转换 笛卡尔转84
* @param {Object} cartesian 三维位置坐标
* @return {Object} {lon,lat,alt} 地理坐标
*/
transformCartesianToWGS84 = (cartesian: any | undefined): any => {
const ellipsoid = Cesium.Ellipsoid.WGS84;
const cartographic = ellipsoid.cartesianToCartographic(cartesian);
return {
lon: Cesium.Math.toDegrees(cartographic.longitude),
lat: Cesium.Math.toDegrees(cartographic.latitude),
alt: cartographic.height,
};
}
/**
* 坐标数组转换 笛卡尔转86
* @param {Array} cartesianArr 三维位置坐标数组
* @return {Array} {lon,lat,alt} 地理坐标数组
*/
transformCartesianArrayToWGS84Array (cartesianArr: number[]): any {
if (this.viewer) {
return cartesianArr ?
cartesianArr.map((item: any) => this.transformCartesianToWGS84(item)) :
[];
}
}
/**
* 84坐标转弧度坐标
* @param {Object} position wgs84
* @return {Object} Cartographic 弧度坐标
*/
transformWGS84ToCartographic = (position: Position): any => (position ?
Cesium.Cartographic.fromDegrees(
position.lon || position.lon,
position.lat,
position.alt
) :
Cesium.Cartographic.ZERO)
/**
* 拾取位置点
* @param {Object} px 屏幕坐标
* @return {Object} Cartesian3 三维坐标
*/
getCatesian3FromPX (px: any | undefined): any {
if (this.viewer && px) {
const picks = this.viewer.scene.drillPick(px);
let cartesian = null;
let isOn3dtiles = false;
let isOnTerrain = false;
// drillPick
Object.keys(picks).forEach((i) => {
const pick = picks[i];
if (
pick && (pick.primitive instanceof (Cesium.Cesium3DTileFeature || Cesium.Cesium3DTileset || Cesium.Model))
) {
isOn3dtiles = true;
}
// 3dtilset
if (isOn3dtiles) {
this.viewer.scene.pick(px);
cartesian = this.viewer.scene.pickPosition(px);
if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
if (cartographic.height < 0) cartographic.height = 0;
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const { height, } = cartographic;
cartesian = this.transformWGS84ToCartesian({ lon, lat, alt: height, });
}
}
});
// 地形
const boolTerrain = this.viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
// Terrain
if (!isOn3dtiles && !boolTerrain) {
const ray = this.viewer.scene.camera.getPickRay(px);
if (!ray) return null;
cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
isOnTerrain = true;
}
// 地球
if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
cartesian = this.viewer.scene.camera.pickEllipsoid(px, this.viewer.scene.globe.ellipsoid);
}
if (cartesian) {
const position = this.transformCartesianToWGS84(cartesian);
if (position.alt < 0) {
cartesian = this.transformWGS84ToCartesian(position, 0.1);
}
return cartesian;
}
return false;
}
}
pointBuffer ():any {
if (this.viewer) {
if (this.handler) {
this.handler.destroy();
}
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction((movement: any) => {
const cartesian = this.getCatesian3FromPX(movement.position);
if (Cesium.defined(cartesian)) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const { height, } = cartographic;
this.addPoint([lon,
lat,
height,]);
this.initPointBuffer([lon,
lat,
height,],this.radius);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction((e: any) => {
// 鼠标左键双击清除
this.clear();
bus.emit('bufferState');
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
}
}
lineBuffer ():void {
this.viewer.scene.globe.depthTestAgainstTerrain = true;
if (this.viewer) {
let positions: any[] = [];
let linePoint: any[] = [];
const lineEntity: any = new Cesium.Entity();
if (this.handler) {
this.handler.destroy();
}
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction((movement: any) => {
const cartesian = this.getCatesian3FromPX(movement.position);
if (cartesian) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const { height, } = cartographic;
linePoint.push([lon,
lat,
height,]);
if (positions.length === 0) {
positions.push(cartesian.clone());
linePoint.push([lon,
lat,
height,]);
}
// 添加量测信息点
positions.push(cartesian);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
this.handler.setInputAction((movement: any) => {
const cartesian = this.getCatesian3FromPX(movement.endPosition);
if (cartesian && cartesian.x) {
if (positions.length >= 2) {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const { height, } = cartographic;
linePoint.pop();
linePoint.push([lon,
lat,
height,]);
positions.pop();
positions.push(cartesian);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// right
this.handler.setInputAction((movement: any) => {
if (positions.length > 0) {
this.initPolylineBuffer(linePoint, this.radius);
this.addPolyline(positions);
positions = [];
linePoint = [];
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
this.handler.setInputAction((e: any) => {
this.clear();
bus.emit('bufferState');
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
lineEntity.polyline = {
width: 5,
material: Cesium.Color.YELLOW.withAlpha(0.8),
clampToGround: true,
};
lineEntity.polyline.positions = new Cesium.CallbackProperty(() => positions, false);
this.drawLayer.entities.add(lineEntity);
}
}
polyBuffer ():void {
if (this.viewer) {
this.viewer.scene.globe.depthTestAgainstTerrain = true;
let positions: any = [];
let polyPoint: any = [];
const polygonHie = new Cesium.PolygonHierarchy();
const polygonEntity: any = new Cesium.Entity();
if (this.handler) {
this.handler.destroy();
}
this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
this.handler.setInputAction((movement: any) => {
const cartesian = this.getCatesian3FromPX(movement.position);
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
if (cartesian) {
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const { height, } = cartographic;
if (positions.length === 0) {
polygonHie.positions.push(cartesian.clone());
positions.push(cartesian.clone());
polyPoint.push([lon,
lat,
height,]);
}
positions.push(cartesian.clone());
polygonHie.positions.push(cartesian.clone());
polyPoint.push([lon,
lat,
height,]);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// mouse_move
this.handler.setInputAction((movement: any) => {
const cartesian = this.getCatesian3FromPX(movement.endPosition);
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const lon = Cesium.Math.toDegrees(cartographic.longitude);
const lat = Cesium.Math.toDegrees(cartographic.latitude);
const { height, } = cartographic;
if (positions.length >= 2) {
if (cartesian) {
positions.pop();
positions.push(cartesian);
polygonHie.positions.pop();
polygonHie.positions.push(cartesian);
polyPoint.pop();
polyPoint.push([lon,
lat,
height,]);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// left结束绘制
this.handler.setInputAction((movement: any) => {
if (positions.length > 2) {
positions.push(positions[0]);
polyPoint.push(polyPoint[0]);
console.log(polyPoint);
this.addPolygon(positions);
this.initPolygonBuffer(polyPoint,this.radius);
positions = [];
polyPoint = [];
polygonHie.positions = [];
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
this.handler.setInputAction((e: any) => {
this.clear();
bus.emit('bufferState');
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
polygonEntity.polyline = {
width: 3,
material: Cesium.Color.YELLOW.withAlpha(0.8),
clampToGround: true,
};
polygonEntity.polyline.positions = new Cesium.CallbackProperty(() => positions, false);
polygonEntity.polygon = {
hierarchy: new Cesium.CallbackProperty(() => polygonHie, false),
material: Cesium.Color.WHITE.withAlpha(0.1),
clampToGround: true,
};
this.drawLayer.entities.add(polygonEntity);
}
}
initPointBuffer (drawpoint:any, distance:number|undefined):void {
const pointF = point(drawpoint);
console.log(distance);
const buffered = buffer(pointF, distance, { units: 'meters', });
const { coordinates, } = buffered.geometry;
const points = coordinates[0];
const degreesArray = this.pointsToDegreesArray(points);
this.addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
}
// 初始化线缓冲
initPolylineBuffer (bufferLine:any, distance:number|undefined) {
let degreesArray = this.pointsToDegreesArray(bufferLine);
const polylineF = lineString(bufferLine);
const buffered = buffer(polylineF, distance, { units: 'meters', });
const { coordinates, } = buffered.geometry;
const points = coordinates[0];
degreesArray = this.pointsToDegreesArray(points);
this.addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
}
// 初始化面缓冲
initPolygonBuffer (bufferPolyogn:any, distance:number|undefined) {
let degreesArray = this.pointsToDegreesArray(bufferPolyogn);
const polygonF = polygon([bufferPolyogn,]);
const buffered = buffer(polygonF, distance, { units: 'meters', });
const { coordinates, } = buffered.geometry;
const points = coordinates[0];
degreesArray = this.pointsToDegreesArray(points);
this.addBufferPolyogn(Cesium.Cartesian3.fromDegreesArray(degreesArray));
}
// 添加点
addPoint (drawpoint:any):any {
this.drawLayer.entities.add({
position: Cesium.Cartesian3.fromDegrees(drawpoint[0], drawpoint[1], drawpoint[2]),
point: {
pixelSize: 10,
color: Cesium.Color.YELLOW,
outlineWidth: 3,
outlineColor: Cesium.Color.YELLOW.withAlpha(0.5),
clampToGround: true,
},
});
}
// 添加线
addPolyline (positions:any) :void {
this.drawLayer.entities.add({
polyline: {
positions,
width: 2,
material: Cesium.Color.YELLOW,
clampToGround: true,
},
});
}
// 添加缓冲面
addBufferPolyogn (positions:any) {
this.drawLayer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(positions),
material: Cesium.Color.RED.withAlpha(0.7),
classificationType: Cesium.ClassificationType.BOTH,
clampToGround: true,
},
});
}
// 添加面
addPolygon (positions:any) {
this.drawLayer.entities.add({
polygon: {
hierarchy: new Cesium.PolygonHierarchy(positions),
material: Cesium.Color.WHITE.withAlpha(0.1),
classificationType: Cesium.ClassificationType.BOTH,
clampToGround: true,
},
polyline: {
positions,
width: 2,
material: Cesium.Color.YELLOW.withAlpha(0.4),
clampToGround: true,
},
});
}
// 坐标点格式转换
pointsToDegreesArray (points:any):any {
const degreesArray: any[] = [];
points.map((item:any) => {
degreesArray.push(item[0]);
degreesArray.push(item[1]);
});
return degreesArray;
}
changeRadius (changeDis:number) :void {
this.radius = changeDis;
}
// 地图绘制要素清除
clear = (): void => {
this.drawLayer.entities.removeAll();
return this.handler && this.handler.destroy();
}
}
import BufferImpl from './BufferImpl';
const bufferImpl = new BufferImpl(this.viewer);