三维可视化上画圆

前言

在对接三维可视化的时候,工具中没有画圆的工具,这里就使用计算点,连接来后模拟画圆。

经纬度

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 生成一个以指定点为中心、半径为 radiusM 米的圆,返回一组经纬度坐标
* @param {number} centerLon 中心经度(度)
* @param {number} centerLat 中心纬度(度)
* @param {number} radiusM 半径,单位米(默认 50)
* @param {number} steps 生成点数(默认 360)
* @returns {Array<[number,number]>} 按顺序连接可成圆的 [[经度,纬度], …]
*/
function circlePoints(centerLon, centerLat, radiusM = 50, steps = 360) {
const earthRadius = 6371000 // 地球平均半径(米)
const angularDist = radiusM / earthRadius // 角距离(弧度)

const lat1 = (centerLat * Math.PI) / 180 // 中心纬度转弧度

const points = []
for (let i = 0; i < steps; i++) {
const bearing = (i * 2 * Math.PI) / steps // 当前方位角 0~2π

// 计算目标点纬度(弧度)
const lat2 = Math.asin(
Math.sin(lat1) * Math.cos(angularDist) +
Math.cos(lat1) * Math.sin(angularDist) * Math.cos(bearing)
)

// 计算经度差(弧度)
const deltaLon = Math.atan2(
Math.sin(bearing) * Math.sin(angularDist) * Math.cos(lat1),
Math.cos(angularDist) - Math.sin(lat1) * Math.sin(lat2)
)

const lon2 = (centerLon * Math.PI) / 180 + deltaLon // 目标经度(弧度)

// 转回角度并收集
points.push([
(lon2 * 180) / Math.PI, // 经度
(lat2 * 180) / Math.PI // 纬度
])
}
return points
}

调用示例

1
2
3
4
const center = [116.39739, 39.90931] // 天安门
const pts = circlePoints(center[0], center[1], 50, 20)

console.table(pts)

二维坐标

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 以指定圆心、半径生成圆上的离散点
* @param {number} cx 圆心 x
* @param {number} cy 圆心 y
* @param {number} r 半径,默认 50
* @param {number} step 总步长
* @returns {Array<{x:number,y:number}>} 圆上按逆时针顺序排列的点数组
*/
function getCirclePoints(cx, cy, r = 50, step = 20) {
const points = []
const stepAng = (2 * Math.PI) / step // 步长转弧度

for (let ang = 0; ang < 2 * Math.PI; ang += stepAng) {
points.push({
x: parseInt(cx + r * Math.cos(ang)),
y: parseInt(cy + r * Math.sin(ang))
})
}
return points
}

调用

1
2
3
const pts = getCirclePoints(100, 100, 100, 20)

console.table(pts)

项目示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function addRangeYuan() {
let data = {
id: 'Range_100',
template_id: 'Range_1',
template_name: ' 区域轮廓1',
template_icon: 'CityToolConfig/ToolUI/Icon/区域1.jpg',
opt: 'ADDRANGE',
type: 'Type_1',
coord_z: 25480,
color: '247424ff',
range_height: 300,
fill_area: true,
fill_color: '24742400',
points: []
}

let center = [10297.546875, -33800.582031]
const pts = getCirclePoints(center[0], center[1], 30000, 40)

for (let i = 0; i < pts.length; i++) {
data.points.push({
coord: `${pts[i].x},${pts[i].y}`,
coord_z: -10271.828125
})
}

ueCall(data)
}