turn.ts
/* eslint-disable no-unused-vars */
/**
* 距离(米)转换为经度 一米对应的经度与所在有关纬度
* @param meter 距离
* @param lat 所在纬度
* @returns {number}
*/
export const meter2Lng = (meter: number, lat: number): number => {
let pi = Math.PI;
let latInMeter = (Math.cos((lat * pi) / 180) * 6371 * 2 * pi) / 360;
return meter / latInMeter / 1000;
};
/**
* 距离(米)转换为纬度 一米对应的纬度为定值
* @param meter 距离多少米
* @returns {number}
*/
export const meter2Lat = (meter: number) => {
let pi = Math.PI;
let lngInMeter = (6371 * 2 * pi) / 360;
return meter / lngInMeter / 1000;
};
/**
* 判断该点是否是经纬度或者笛卡尔坐标
* @param point
*/
export const isDegreesOrCartesian = (point: any) => {
if (!point) {
throw "参数错误!";
}
if (
"number" === typeof point.x &&
"number" === typeof point.y &&
"number" === typeof point.z
) {
return true;
}
if ("number" === typeof point.lng && "number" === typeof point.lat) {
return true;
}
return false;
};
/**
* 笛卡尔坐标转WGS84
* @param Cartesian3 单个点或点数组
*/
export const Cartesian3ToWGS84 = ({ Cesium, viewer }: any, Cartesian3: any) => {
if (!Cesium || !viewer) {
return;
}
if (!Cartesian3 || !Cartesian3.x) {
throw "Error in parameters";
}
let _cartesian3 = new Cesium.Cartesian3(
Cartesian3.x,
Cartesian3.y,
Cartesian3.z
);
let _cartographic = Cesium.Cartographic.fromCartesian(_cartesian3);
let _lat = Cesium.Math.toDegrees(_cartographic.latitude);
let _lng = Cesium.Math.toDegrees(_cartographic.longitude);
let _alt = _cartographic.height;
return { lng: _lng, lat: _lat, alt: _alt };
};
/**
* 世界坐标系转屏幕坐标
* @param point
* @param viewer
*/
export const toWindowCoordinates = ({ Cesium, viewer }: any, point: any) => {
if (!Cesium || !viewer) {
return;
}
if (viewer && point && point.x && point.y && point.z) {
return Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, point);
} else if (viewer && point.lng && point.lat && point.alt) {
return Cesium.SceneTransforms.wgs84ToWindowCoordinates(
viewer.scene,
toCartesianFromDegrees({ Cesium, viewer }, point)
);
} else {
throw "参数错误!";
}
};
/**
* 笛卡尔坐标转世界坐标
* @param point
*/
export const toDegreesFromCartesian = ({ Cesium, viewer }: any, point: any) => {
if (!Cesium || !viewer) {
return;
}
if (point.x && point.y && point.z) {
let cartesian33 = new Cesium.Cartesian3(point.x, point.y, point.z);
let cartographic = Cesium.Cartographic.fromCartesian(cartesian33);
return {
lng: parseFloat(
Cesium.Math.toDegrees(cartographic.longitude).toFixed(10)
),
lat: parseFloat(Cesium.Math.toDegrees(cartographic.latitude).toFixed(10)),
alt: parseFloat(cartographic.height.toFixed(5)),
};
} else {
throw "参数错误!";
}
};
/**
* 世界坐标转笛卡尔坐标
* @param point
*/
export const toCartesianFromDegrees = ({ Cesium, viewer }: any, point: any) => {
if (!Cesium || !viewer) {
return;
}
if (point.lng && point.lat) {
return Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.alt || 0);
} else {
throw "参数错误!";
}
};
/**
* 转化成经纬度
* @param point
*/
export const toDegrees = ({ Cesium, viewer }: any, point: any) => {
if (!Cesium || !viewer) {
return;
}
if (isDegreesOrCartesian(point)) {
if (point.x && point.y && point.z) {
point = toDegreesFromCartesian({ Cesium, viewer }, point);
}
return point;
} else {
throw "参数错误!";
}
};
/**
* 转化成笛卡尔坐标
* @param point
*/
export const toCartesian = ({ Cesium, viewer }: any, point: any) => {
if (!Cesium || !viewer) {
return;
}
if (isDegreesOrCartesian(point)) {
if (point.lng && point.lat) {
point = toCartesianFromDegrees({ Cesium, viewer }, point);
}
return point;
} else {
throw "参数错误!";
}
};
/**
* 获取两点之间的距离
* @param p1
* @param p2
* @returns {*}
*/
export const getDistance = ({ Cesium, viewer }: any, p1: any, p2: any) => {
p1 = toCartesian({ Cesium, viewer }, p1);
p2 = toCartesian({ Cesium, viewer }, p2);
return Math.sqrt(
Math.pow(p1.x - p2.x, 2) +
Math.pow(p1.y - p2.y, 2) +
Math.pow(p1.z - p2.z, 2)
);
};
/**
* 点到线段的最短距离
* @param a 线段上一点
* @param b 线段上另一个点
* @param s 该点到ab的最短距离
* @returns {number}
*/
export const point2LineMinDistance = ({ Cesium, viewer }: any, a: any, b: any, s: any) => {
a = toCartesian({ Cesium, viewer }, a);
b = toCartesian({ Cesium, viewer }, b);
s = toCartesian({ Cesium, viewer }, s);
let ab = Math.sqrt(
Math.pow(a.x - b.x, 2.0) +
Math.pow(a.y - b.y, 2.0) +
Math.pow(a.z - b.z, 2.0)
);
let as = Math.sqrt(
Math.pow(a.x - s.x, 2.0) +
Math.pow(a.y - s.y, 2.0) +
Math.pow(a.z - s.z, 2.0)
);
let bs = Math.sqrt(
Math.pow(s.x - b.x, 2.0) +
Math.pow(s.y - b.y, 2.0) +
Math.pow(s.z - b.z, 2.0)
);
let cos_A =
(Math.pow(as, 2.0) + Math.pow(ab, 2.0) - Math.pow(bs, 2.0)) / (2 * ab * as);
let sin_A = Math.sqrt(1 - Math.pow(cos_A, 2.0));
let t =
((a.x - s.x) * (a.x - b.x) +
(a.y - s.y) * (a.y - b.y) +
(a.z - s.z) * (a.z - b.z)) /
(Math.pow(a.x - b.x, 2.0) +
Math.pow(a.y - b.y, 2.0) +
Math.pow(a.z - b.z, 2.0));
if (t < 0) {
return as;
} else if (t <= 1 && t >= 0) {
return as * sin_A;
} else if (t > 1) {
return bs;
}
};
/**
* 求三角形面积;返回-1为不能组成三角形;
* @param a
* @param b
* @param c
* @returns {*}
*/
export const countTriangleArea = ({ Cesium, viewer }: any, a: any, b: any, c: any) => {
a = toCartesian({ Cesium, viewer }, a);
b = toCartesian({ Cesium, viewer }, b);
c = toCartesian({ Cesium, viewer }, c);
let area = -1;
let side = []; //存储三条边的长度;
side[0] = Math.sqrt(
Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2) + Math.pow(a.z - b.z, 2)
);
side[1] = Math.sqrt(
Math.pow(a.x - c.x, 2) + Math.pow(a.y - c.y, 2) + Math.pow(a.z - c.z, 2)
);
side[2] = Math.sqrt(
Math.pow(c.x - b.x, 2) + Math.pow(c.y - b.y, 2) + Math.pow(c.z - b.z, 2)
);
//不能构成三角形;
if (
side[0] + side[1] <= side[2] ||
side[0] + side[2] <= side[1] ||
side[1] + side[2] <= side[0]
) {
return area;
}
//利用海伦公式。area =sqr(p*(p-a)(p-b)(p-c));
let p = (side[0] + side[1] + side[2]) / 2; //半周长;
area = Math.sqrt(p * (p - side[0]) * (p - side[1]) * (p - side[2]));
return area;
};
/**
* 获取多边形的中心(根据经纬度,不包括高程)
* @param path 数组 [{lng:123,lat:32},...]
* @returns {{lng: number, lat: number}}
*/
export const getPolygonCenterByDegree = (path: any) => {
if (!path || path.length < 3 || !path[0].lng) {
throw "Error in parameters";
}
let x = 0.0;
let y = 0.0;
for (let i = 0; i < path.length; i++) {
x = x + parseFloat(path[i].lng);
y = y + parseFloat(path[i].lat);
}
x = x / path.length;
y = y / path.length;
return {
lng: x,
lat: y,
};
};
/**
* 求多边形的面积
* @param arr
* @returns {*}
*/
export const countArea = ({ Cesium, viewer }: any, arr: any) => {
if (!arr || arr.length < 3) {
throw "参数错误!";
} else {
let area = 0;
for (let i = 0; i < arr.length; i++) {
let j = (i + 1) % arr.length;
let p1 = arr[i],
p2 = arr[j];
p1 = toCartesian({ Cesium, viewer }, p1);
p2 = toCartesian({ Cesium, viewer }, p2);
area += p1.x * p2.y;
area -= p1.y * p2.x;
}
area /= 2;
return Math.abs(area);
}
};
run.ts
import { meter2Lng, meter2Lat, toDegrees, toCartesian } from "@/assets/tools/turn/turn"
/**
* 拖拽坐标轴调整实体位置
* @param Cesium
* @param viewer
* @param activeModelEntity 要移动的实体
* @param arrowLength 坐标轴长度(米) 默认200
*/
let dragEntity: any = (Cesium: any, viewer: any, activeModelEntity: any, arrowLength: number) => {
let MoveEntity = (() => {
let leftDownFlag = false;//左键是否按下 作为可拖拽的依据
let pointDraged: any = null;//左键按下之后拾取到的东西
let viewer: any;
let Cesium: any;
let handler: any;
let activeModelEntity: any;//要拖动的实体
let arrowLength: number;//单位米
let lastMaterial: any;// 坐标轴原本的材质
let activePolyLineEntity: any;//选中的线实体
let activePolyLineMaterial: any;//坐标轴选中之后的材质
let lastEndPosition: any;//鼠标移动上次的位置
let ConstructMoveEntity = (options: any) => {
viewer = options.viewer;
Cesium = options.Cesium;
activeModelEntity = options.activeModelEntity;
arrowLength = options.arrowLength || 200;
handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
Init();
addOrUpdateAxis(null, null);
viewer.scene.globe.depthTestAgainstTerrain = true;//开启深度检测
activePolyLineMaterial = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.YELLOW)
}
let addOrUpdateAxis = (pickedId: any = null, activePolyLineMaterial: any = null) => {
if (activeModelEntity && arrowLength) {
let startPosition = activeModelEntity.position.getValue(viewer.clock.currentTime);
let p_p = toDegrees({ Cesium: Cesium, viewer: viewer }, startPosition)
// console.log(p_p) //打印位置
let endLng = toCartesian({ Cesium: Cesium, viewer: viewer }, { lng: p_p.lng + meter2Lng(arrowLength, p_p.lat), lat: p_p.lat, alt: p_p.alt })
let endLat = toCartesian({ Cesium: Cesium, viewer: viewer }, { lng: p_p.lng, lat: p_p.lat + meter2Lat(arrowLength), alt: p_p.alt })
let endAlt = toCartesian({ Cesium: Cesium, viewer: viewer }, { lng: p_p.lng, lat: p_p.lat, alt: p_p.alt + arrowLength })
let AxisLng = viewer.entities.getOrCreateEntity("AxisLng")
AxisLng.polyline = {
positions: new Cesium.CallbackProperty(function () {
return [startPosition, endLng];
}, false),
width: 10,
material: pickedId === "AxisLng" ? activePolyLineMaterial : new Cesium.PolylineArrowMaterialProperty(Cesium.Color.RED),
}
let AxisLat = viewer.entities.getOrCreateEntity("AxisLat")
AxisLat.polyline = {
positions: new Cesium.CallbackProperty(function () {
return [startPosition, endLat];
}, false),
width: 10,
material: pickedId === "AxisLat" ? activePolyLineMaterial : new Cesium.PolylineArrowMaterialProperty(Cesium.Color.GREEN),
}
let AxisAlt = viewer.entities.getOrCreateEntity("AxisAlt")
AxisAlt.polyline = {
positions: new Cesium.CallbackProperty(function () {
return [startPosition, endAlt];
}, false),
width: 10,
material: pickedId === "AxisAlt" ? activePolyLineMaterial : new Cesium.PolylineArrowMaterialProperty(Cesium.Color.BLUE),
}
}
}
let Init = () => {
// 左键按下
handler.setInputAction((movement: any) => {
pointDraged = viewer.scene.pick(movement.position);//选取当前的entity
leftDownFlag = true;
if (pointDraged) {
viewer.scene.screenSpaceCameraController.enableRotate = false;//锁定相机
//当前实体Entity的polyline坐标属性信息暂存
if (pointDraged.id.polyline) {
activePolyLineEntity = pointDraged.id//记录正在活动的线实体
lastMaterial = activePolyLineEntity.polyline.material//线实体材质
activePolyLineEntity.polyline.material = activePolyLineMaterial
}
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
// 左键抬起
handler.setInputAction(() => {
leftDownFlag = false;
pointDraged = null;
viewer.scene.screenSpaceCameraController.enableInputs = true;
viewer.scene.screenSpaceCameraController.enableRotate = true;//锁定相机
if (activePolyLineEntity && lastMaterial) {
activePolyLineEntity.polyline.material = lastMaterial
activePolyLineEntity = null;
}
lastEndPosition = null;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
// 鼠标移动
handler.setInputAction((movement: any) => {
if (leftDownFlag === true && pointDraged != null && activePolyLineEntity && activeModelEntity) {
let endPosition = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
if (!endPosition) {
return
}
let cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(endPosition);
let cartographic2: any;
if (endPosition && lastEndPosition) {
cartographic2 = viewer.scene.globe.ellipsoid.cartesianToCartographic(lastEndPosition);
}
let nowPosition_Cartesian = activeModelEntity.position.getValue(viewer.clock.currentTime);//模型当前位置
let nowPosition_Degree = toDegrees({ Cesium: Cesium, viewer: viewer }, nowPosition_Cartesian)
let temp = 0.5;//这个可以通过传参来搞
let pickedId = pointDraged.id.id
if (!(["AxisAlt", "AxisLng", "AxisLat"].includes(pickedId))) {
return
}
if (pickedId === "AxisAlt") {
//高度调整
let pixel_difference = movement.endPosition.y - movement.startPosition.y
//pixel_difference > 0高度减少 pixel_difference < 0 高度增加
nowPosition_Degree.alt = nowPosition_Degree.alt - (temp * pixel_difference)
} else if (pickedId === "AxisLng") {
//经度调整
if (cartographic2 && cartographic) {
let lng = Cesium.Math.toDegrees(cartographic.longitude);//鼠标拾取的经度
let lng2 = Cesium.Math.toDegrees(cartographic2.longitude);
nowPosition_Degree.lng -= (lng2 - lng);
}
} else if (pickedId === "AxisLat") {
//纬度调整
if (cartographic2 && cartographic) {
let lat = Cesium.Math.toDegrees(cartographic.latitude);//鼠标拾取的纬度
let lat2 = Cesium.Math.toDegrees(cartographic2.latitude);
nowPosition_Degree.lat -= (lat2 - lat);
}
}
lastEndPosition = endPosition
let r = toCartesian({ Cesium: Cesium, viewer: viewer }, nowPosition_Degree)
activeModelEntity.position.setValue(r);
addOrUpdateAxis(pickedId, activePolyLineMaterial)
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// 右键结束
handler.setInputAction(() => {
handler.destroy();
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
}
return ConstructMoveEntity;
})();
MoveEntity({ Cesium: Cesium, viewer: viewer, activeModelEntity: activeModelEntity, arrowLength: arrowLength })
}
export {
dragEntity
}
欢迎各位给出宝贵意见