Commit cd3d65b9 by lyc

init

parent 4df56558
### 创建扇形实体函数
### 创建扇形实体函数
通过entity添加实体ellipsoid,
ellipsoid是椭圆的实体,里面有角度信息,即配置角度可以显示想要范围的扇形,
代码如下:
```
function draw_sector(point, angleone, angletwo, r) {
console.log(angleone, angletwo)
const sector = viewer.entities.add({
name: "Wedge",
position: point,
ellipsoid: {
radii: new Cesium.Cartesian3(r, r, 1.0),
minimumClock: Cesium.Math.toRadians(angleone),
maximumClock: Cesium.Math.toRadians(angletwo),
material: Cesium.Color.DARKCYAN.withAlpha(0.3),
outline: false,
},
});
return sector
}
```
### 计算角度
```
function computerJiao(point_one, point_two) {
let one = Cesium.Cartographic.fromCartesian(point_one)
let two = Cesium.Cartographic.fromCartesian(point_two)
let onelon = Cesium.Math.toDegrees(one.longitude)
let onelat = Cesium.Math.toDegrees(one.latitude)
let twolon = Cesium.Math.toDegrees(two.longitude)
let twolat = Cesium.Math.toDegrees(two.latitude)
let jiaorad = Math.atan(((twolon) - (onelon)) / ((twolat) - (onelat)))
let jiao=jiaorad*(180/Math.PI)
return jiao
}
```
### 计算半径
```
function computerR(point_one, point_two) {
let one = Cesium.Cartographic.fromCartesian(point_one)
let two = Cesium.Cartographic.fromCartesian(point_two)
let onelon = Cesium.Math.toDegrees(one.longitude)
let onelat = Cesium.Math.toDegrees(one.latitude)
let twolon = Cesium.Math.toDegrees(two.longitude)
let twolat = Cesium.Math.toDegrees(two.latitude)
let chang = Math.abs(onelon - twolon)
let kuang = Math.abs(onelat - twolat)
let r = Math.sqrt(chang * chang + kuang * kuang)
return r*89990
}
```
### 点击事件
```
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (event) {
const ray = viewer.camera.getPickRay(event.position);
const earthPosition = viewer.scene.globe.pick(ray, viewer.scene);
let angleone
let angletwo
let r
if (Cesium.defined(earthPosition)) {
if (count == 0) {
onepoint = earthPosition;
count = count + 1
}
else if (count == 1) {
twopoint = earthPosition;
count = count + 1
}
else if (count == 2) {
threepoint = earthPosition;
count = count + 1
}
if (count==3) {
angleone = computerJiao(onepoint, twopoint)
angletwo = computerJiao(onepoint, threepoint)
r = computerR(onepoint, twopoint)
draw_sector(onepoint, angleone, angletwo, r)
console.log(r)
count=0
}
console.log(count)
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
```
点击事件通过三次点击来确定扇形所需要的三个点的坐标信息,再通过半径和角度的计算从而获得实体所需要的数据;
### 总结
在写扇形这一块的代码时遇到了许多的困难,
1、entity中没有扇形示例,圆形实例没有角度的配置项,询问良哥可以使用椭圆来写,
2、在计算角度时,计算给出的是弧度制,但是需要的是角度制,因此需要再加上一步运算,
3、因为在计算角度和半径的过程中是使用经纬度来计算的,但是经纬度在地球表面是弧形的,在精准度小的地方有很大的误差,但在精准度高的地方误差很小,这里还需要优化。
\ No newline at end of file
/**
* 计算夹角类
*/
import * as Cesium from "cesium";
class computerAngle {
/**
* 计算两个点坐标之间的直线与正北方向之间的夹角
* @param {Array} [p] -两个坐标经纬度高程坐标数组
* @return {Array} -返回两个数组元素,1.两个点坐标之间的直线与正北方向之间的夹角;2.两个坐标之间的直线距离
*/
angle(p) {
let A = Cesium.Cartesian3.fromDegrees(p[0], p[1]);
let B = Cesium.Cartesian3.fromDegrees(p[3], p[4]);
let ab = Cesium.Cartesian3.distance(A, B);
//以a点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵
const localToWorld = Cesium.Transforms.eastNorthUpToFixedFrame(
new Cesium.Cartesian3.fromDegrees(p[0], p[1])
);
//求世界坐标到局部坐标的变换矩阵
const worldToLocal = Cesium.Matrix4.inverse(
localToWorld,
new Cesium.Matrix4()
);
//A点在局部坐标的位置,其实就是局部坐标原点
const localPosition_A = Cesium.Matrix4.multiplyByPoint(
worldToLocal,
new Cesium.Cartesian3.fromDegrees(p[0], p[1]),
new Cesium.Cartesian3()
);
//B点在以A点为原点的局部的坐标位置
const localPosition_B = Cesium.Matrix4.multiplyByPoint(
worldToLocal,
new Cesium.Cartesian3.fromDegrees(p[3], p[4]),
new Cesium.Cartesian3()
);
//弧度
const angle = Math.atan2(
localPosition_B.x - localPosition_A.x,
localPosition_B.y - localPosition_A.y
);
//角度
let theta = angle * (180 / Math.PI);
if (theta < 0) {
theta = theta + 360;
}
return [theta, ab];
}
}
export default computerAngle;
import * as Cesium from "cesium";
import computerAngle from "./angle";
let myAngle = new computerAngle();
let sectorNum = 0;
// 存储高程数组
let height = [];
// 地图容器对象
let v;
/**
* 扇形实体
*/
draw(parameter) {
let xy = parameter.clickPointH;
v = parameter.viewer;
for (let i = 2; i < xy.length; i = i + 3) {
height.push(xy[i]);
}
// 计算扇形起始线和正北的夹角
let AB = xy.slice(0, 6);
let Pab = myAngle.angle(AB);
// 计算扇形终点线和正北的夹角
let AC = [...xy.slice(0, 3), ...xy.slice(6, 9)];
let Pac = myAngle.angle(AC);
// 如果C点是往北边画的,则置换两个角度,方便计算
Pab[0] > Pac[0] ? ([Pab[0], Pac[0]] = [Pac[0], Pab[0]]) : [];
if (
// 当B点在A点西部,且C点在A点东北部的时候||当B点在A点东部,且C点在A点西北部的时候
(xy[3] > xy[0] && xy[7] > xy[1] && xy[6] < xy[0]) ||
(xy[3] < xy[0] && xy[7] > xy[1] && xy[6] > xy[0])
) {
[Pab[0], Pac[0]] = [Pac[0], 360 + Pab[0]];
}
return this.drawNow(xy[0], xy[1], Pab[0], Pac[0], Pab[1], parameter);
}
drawNow(x, y, Pab, Pac, ac, p) {
let id = "扇形" + (sectorNum == 0 ? "" : sectorNum);
let points = [];
// 地球两极稍扁,赤道略鼓
// 计算椭球体中心到圆心的距离(纬度越接近极点,则使用短半径,否则使用长半径)
let oa = 6378137 - ((6378137 - 6356752) * y) / 90;
// 计算圆心在赤道面的垂足投影长度(米)
let oh = oa * Math.cos((y * Math.PI) / 180);
for (let i = Pab, j = 0; i <= Pac; i += 0.03, j++) {
// 计算距离坐标点ac米,方位角为i处的坐标点到圆心的X,Y轴距离(米)
let clon = ac * Math.sin((i * Math.PI) / 180);
let clat = ac * Math.cos((i * Math.PI) / 180);
// 在圆心坐标上叠加X,Y轴弧度(弧度=周长/半径)后的新坐标
let jlon = ((clon / oh + (x * Math.PI) / 180) * 180) / Math.PI;
let jlat = ((clat / oa + (y * Math.PI) / 180) * 180) / Math.PI;
j > 2 ? (j = 2) : "";
points.push(jlon, jlat, height[j]);
}
points.push(x, y, height[0]);
var sector = new Cesium.Entity({
id,
polygon: {
show: true,
hierarchy: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(points),
},
height: 2000,
extrudedHeight: 10,
material: Cesium.Color.fromCssColorString(p.entityColor || "#007acc"),
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
sectorNum++;
// 添加实体时新增,视图缩放至实体
v.entities.add(sector);
v.zoomTo(sector);
return sector;
}
const Sector = new SectorGraphics();
export function drawSector(a) {
let entity = Sector.draw(a);
return entity;
}
\ No newline at end of file
......@@ -6,12 +6,10 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import * as Cesium from 'Cesium'
import Viewer from 'cesium/Source/Widgets/Viewer/Viewer';
import * as Cesium from 'cesium'
import { ref } from 'vue'
import computerAngle from "./angle";
import { drawSector } from './draw_sector'
onMounted(() => {
......@@ -33,76 +31,15 @@ onMounted(() => {
// material: Cesium.Color.AQUA.withAlpha(0.9)
// }
// });
let myAngle = new computerAngle();
let sectorNum = 0;
// 存储高程数组
let height = [];
// 地图容器对象
let v;
draw(parameter) {
let xy = parameter.clickPointH;
v = parameter.viewer;
for (let i = 2; i < xy.length; i = i + 3) {
height.push(xy[i]);
const polyline = viewer.entities.add({
id: 'polyline',
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([120, 20, 121, 20, 121, 20.5, 122, 22, 120, 20]),
width:10,
material:Cesium.Color.YELLOW
}
// 计算扇形起始线和正北的夹角
let AB = xy.slice(0, 6);
let Pab = myAngle.angle(AB);
// 计算扇形终点线和正北的夹角
let AC = [...xy.slice(0, 3), ...xy.slice(6, 9)];
let Pac = myAngle.angle(AC);
// 如果C点是往北边画的,则置换两个角度,方便计算
Pab[0] > Pac[0] ? ([Pab[0], Pac[0]] = [Pac[0], Pab[0]]) : [];
if (
// 当B点在A点西部,且C点在A点东北部的时候||当B点在A点东部,且C点在A点西北部的时候
(xy[3] > xy[0] && xy[7] > xy[1] && xy[6] < xy[0]) ||
(xy[3] < xy[0] && xy[7] > xy[1] && xy[6] > xy[0])
) {
[Pab[0], Pac[0]] = [Pac[0], 360 + Pab[0]];
}
return this.drawNow(xy[0], xy[1], Pab[0], Pac[0], Pab[1], parameter);
}
drawNow(x, y, Pab, Pac, ac, p) {
let id = "扇形" + (sectorNum == 0 ? "" : sectorNum);
let points = [];
// 地球两极稍扁,赤道略鼓
// 计算椭球体中心到圆心的距离(纬度越接近极点,则使用短半径,否则使用长半径)
let oa = 6378137 - ((6378137 - 6356752) * y) / 90;
// 计算圆心在赤道面的垂足投影长度(米)
let oh = oa * Math.cos((y * Math.PI) / 180);
for (let i = Pab, j = 0; i <= Pac; i += 0.03, j++) {
// 计算距离坐标点ac米,方位角为i处的坐标点到圆心的X,Y轴距离(米)
let clon = ac * Math.sin((i * Math.PI) / 180);
let clat = ac * Math.cos((i * Math.PI) / 180);
// 在圆心坐标上叠加X,Y轴弧度(弧度=周长/半径)后的新坐标
let jlon = ((clon / oh + (x * Math.PI) / 180) * 180) / Math.PI;
let jlat = ((clat / oa + (y * Math.PI) / 180) * 180) / Math.PI;
j > 2 ? (j = 2) : "";
points.push(jlon, jlat, height[j]);
}
points.push(x, y, height[0]);
var sector = new Cesium.Entity({
id,
polygon: {
show: true,
hierarchy: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(points),
},
height: 2000,
extrudedHeight: 10,
material: Cesium.Color.fromCssColorString(p.entityColor || "#007acc"),
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
});
sectorNum++;
// 添加实体时新增,视图缩放至实体
v.entities.add(sector);
v.zoomTo(sector);
return sector;
}
})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment