Files
sdk4.0/src/Draw/drawAssemble.js
2025-07-03 13:54:01 +08:00

596 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import MouseTip from '../MouseTip'
import MouseEvent from '../Event'
import Draw from './draw'
const transformCartesianToWGS84 = cartesian => {
let ellipsoid = Cesium.Ellipsoid.WGS84
let cartographic = ellipsoid.cartesianToCartographic(cartesian)
const x = Cesium.Math.toDegrees(cartographic.longitude)
const y = Cesium.Math.toDegrees(cartographic.latitude)
const z = cartographic.height
return { x, y, z }
}
/**
* @extends Draw*/
class DrawAssemble extends Draw {
/**
* @constructor
* @param sdk
* @param [options] {object} 面属性
* @param [options.color=rgba(185,14,14,0.58)] {object} 线属性
* */
constructor(sdk, options = {}) {
super(sdk, options)
this.points = null
this.polygonHasCreated = false
}
static polygon(that, viewer = that.viewer) {
let id = that.randomString()
return viewer.entities.add(
new Cesium.Entity({
name: 'AssemblePolygon',
id,
polygon: {
hierarchy: new Cesium.CallbackProperty(e => {
let arr = that.computeAssemble(that.positions)
for (let i = 0; i < arr.length; i++) {
if (isNaN(arr[i].x)) {
arr = []
break
}
}
return new Cesium.PolygonHierarchy(arr)
}, false),
material: Cesium.Color.fromCssColorString(that.color),
outline: true,
outlineColor: Cesium.Color.GREEN,
zIndex: 99999999
}
})
)
}
/**
* @desc 开始动态绘制面
* @method start
* @param cb {function} 回调函数
* @memberOf DrawPolygon
* @example draw.start((err,positions)=>{
*
* })
* */
start(cb) {
let that = this
// eslint-disable-next-line no-undef
if (YJ.Measure.GetMeasureStatus()) {
cb('上一次测量未结束')
} else {
super.start()
// eslint-disable-next-line no-undef
YJ.Measure.SetMeasureStatus(true)
let into
this.tip = new MouseTip('左键确定,右键取消;', that.sdk)
this.event = new MouseEvent(that.sdk)
this.positions = []
this.points_ids = [] //存放左键点击时临时添加的point的id
let cache_positions = []
let cache_84_position = []
this.anchorpoints = []
this.event.mouse_left((movement, cartesian) => {
if (into === '2D') {
return
}
into = '3D'
if (!cartesian) return
if (this.anchorpoints.length === 3) {
this.anchorpoints[1] = cartesian;
}
else {
this.anchorpoints.push(cartesian)
}
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
// console.log(this.cartesian3Towgs84(cartesian))
this.points_ids.push(this.create_point(cartesian))
if (this.points_ids.length === 3) {
let array = [cache_positions[0], cache_positions[2], cache_positions[1]]
cb(null, array)
this.end()
}
})
this.event.mouse_move((movement, cartesian) => {
if (into === '2D') {
return
}
this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
if (!cartesian || this.points_ids.length === 0) return
if (cache_positions.length > 1) {
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer), cache_positions[1]]
}
else {
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer)]
}
if (this.points_ids.length === 1 && !Cesium.defined(this.assemblePolygon)) {
this.assemblePolygon = DrawAssemble.polygon(this)
}
if (this.anchorpoints.length >= 2) {
if (this.points_ids.length === 1) {
let pnts = new Array();
this.positions.forEach((item) => {
pnts.push([item.lng, item.lat]);
});
let mid = P.PlotUtils.mid(pnts[0], pnts[1])
let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
this.positions = [this.positions[0], { lng: pnt[0], lat: pnt[1] }, this.positions[1]];
}
//替换中间点
this.anchorpoints[1] = cartesian;
}
else {
this.anchorpoints.push(cartesian)
}
})
this.event.mouse_right((movement, cartesian) => {
if (into === '2D') {
return
}
cb(null)
this.end()
})
this.event.gesture_pinck_start((movement, cartesian) => {
if (into === '2D') {
return
}
let startTime = new Date()
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
this.end()
cb(false)
}
else {
if (this.anchorpoints.length === 2) {
this.anchorpoints.push(cartesian)
cb(null, this.positions)
this.end()
}
else {
if (!cartesian || Cesium.defined(this.assemblePolygon)) return
this.tip.setPosition(
cartesian,
(movement.position1.x + movement.position2.x) / 2,
(movement.position1.y + movement.position2.y) / 2
)
this.anchorpoints.push(cartesian)
this.assemblePolygon = DrawAssemble.polygon(this)
cache_positions.push(this.cartesian3Towgs84(cartesian))
// console.log(this.cartesian3Towgs84(cartesian))
this.points_ids.push(this.create_point(cartesian))
}
}
})
})
if (!this._is2D && this._sdk2D) {
this.event2D = new MouseEvent(this._sdk2D)
this.event2D.mouse_left((movement, cartesian) => {
if (into === '3D') {
return
}
into = '2D'
if (!cartesian) return
if (this.anchorpoints.length === 3) {
this.anchorpoints[1] = cartesian;
}
else {
this.anchorpoints.push(cartesian)
}
cache_positions.push(this.cartesian3Towgs84(cartesian, this.viewer))
// console.log(this.cartesian3Towgs84(cartesian))
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
if (this.points_ids.length === 3) {
let array = [cache_positions[0], cache_positions[2], cache_positions[1]]
cb(null, array)
this.end()
}
})
this.event2D.mouse_move((movement, cartesian) => {
if (into === '3D') {
return
}
this.tip.setPosition(
cartesian,
movement.endPosition.x + this.viewer.canvas.width,
movement.endPosition.y
)
if (!cartesian || this.points_ids.length === 0) return
if (cache_positions.length > 1) {
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer), cache_positions[1]]
}
else {
this.positions = [cache_positions[0], this.cartesian3Towgs84(cartesian, this.viewer)]
}
if (this.points_ids.length === 1 && !Cesium.defined(this.assemblePolygon)) {
this.assemblePolygon = DrawAssemble.polygon(this, this._sdk2D.viewer)
}
if (this.anchorpoints.length >= 2) {
if (this.points_ids.length === 1) {
let pnts = new Array();
this.positions.forEach((item) => {
pnts.push([item.lng, item.lat]);
});
let mid = P.PlotUtils.mid(pnts[0], pnts[1])
let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
this.positions = [this.positions[0], { lng: pnt[0], lat: pnt[1] }, this.positions[1]];
}
//替换中间点
this.anchorpoints[1] = cartesian;
}
else {
this.anchorpoints.push(cartesian)
}
})
this.event2D.mouse_right((movement, cartesian) => {
if (into === '3D') {
return
}
cb(null)
this.end()
})
this.event2D.gesture_pinck_start((movement, cartesian) => {
if (into === '3D') {
return
}
let startTime = new Date()
this.event2D.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
this.end()
cb(false)
}
else {
if (this.anchorpoints.length === 2) {
this.anchorpoints.push(cartesian)
cb(null, this.positions)
this.end()
}
else {
if (!cartesian || Cesium.defined(this.assemblePolygon)) return
this.tip.setPosition(
cartesian,
((movement.position1.x + movement.position2.x) / 2) + this.viewer.canvas.width,
(movement.position1.y + movement.position2.y) / 2
)
this.anchorpoints.push(cartesian)
this.assemblePolygon = DrawAssemble.polygon(this, this._sdk2D.viewer)
cache_positions.push(this.cartesian3Towgs84(cartesian))
// console.log(this.cartesian3Towgs84(cartesian))
this.points_ids.push(this.create_point(cartesian, this._sdk2D.viewer))
}
}
})
})
}
}
}
end() {
super.end();
this.viewer.entities.remove(this.assemblePolygon)
if (!this._is2D && this._sdk2D) {
this._sdk2D.viewer.entities.remove(this.assemblePolygon)
}
}
// computeAssemblePoints(anchorpoints) {
// let points = []
// let originP = transformCartesianToWGS84(anchorpoints[0])
// let lastP = anchorpoints[1]
// ? transformCartesianToWGS84(anchorpoints[1])
// : { x: originP.x + 0.00001, y: originP.y + 0.00001, z: originP.z }
// let vectorOL = { x: lastP.x - originP.x, y: lastP.y - originP.y }
// let dOL = Math.sqrt(vectorOL.x * vectorOL.x + vectorOL.y * vectorOL.y)
// let v_O_P1_lr = this.calculateVector(
// vectorOL,
// Math.PI / 3,
// (Math.sqrt(3) / 12) * dOL
// )
// let originP_P1 = v_O_P1_lr[1]
// let p1 = { x: originP.x + originP_P1.x, y: originP.y + originP_P1.y }
// let p2 = { x: (originP.x + lastP.x) / 2, y: (originP.y + lastP.y) / 2 }
// let v_L_P3_lr = this.calculateVector(
// vectorOL,
// (Math.PI * 2) / 3,
// (Math.sqrt(3) / 12) * dOL
// )
// let lastP_P3 = v_L_P3_lr[1]
// let p3 = { x: lastP.x + lastP_P3.x, y: lastP.y + lastP_P3.y }
// let v_O_P5_lr = this.calculateVector(vectorOL, Math.PI / 2, (1 / 2) * dOL)
// let v_O_P5 = v_O_P5_lr[0]
// let p5 = { x: v_O_P5.x + p2.x, y: v_O_P5.y + p2.y }
// let p0 = originP
// let p4 = lastP
// points.push(p0, p1, p2, p3, p4, p5)
// const closeCardinal = this.createCloseCardinal(points)
// const fb_points = this.calculatePointsFBZ3(closeCardinal, 100)
// let result = []
// let result2 = []
// for (let index = 0; index < fb_points.length; index++) {
// const ele = fb_points[index]
// let obj = {
// lng: ele.x,
// lat: ele.y,
// alt: 0
// }
// result.push(ele.x, ele.y, 0)
// result2.push(obj)
// }
// this.position = result2
// this.points = result
// }
// computeAssemblePoints2(anchorpoints) {
// let points = anchorpoints.length;
// if (points < 2) {
// return false
// } else {
// let pnts = new Array();
// anchorpoints.forEach((item) => {
// let posLonLat = this.cartesian3Towgs84(item, this.viewer);;
// pnts.push([posLonLat.lng, posLonLat.lat]);
// });
// //console.log("pnts6666",pnts);
// // pnts.push(tailPoint);
// // pnts.push(headerPoint);
// if (pnts.length === 2) {
// let mid = P.PlotUtils.mid(pnts[0], pnts[1])
// //let d = utils.MathDistance(pnts[0], mid) / 0.9
// let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
// //console.log("d",d);
// let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
// pnts = [pnts[0], pnt, pnts[1]];
// //console.log("pnt",pnt);
// //createPoint(Cesium.Cartesian3.fromDegrees(pnt[0], pnt[1]));
// }
// let mid = P.PlotUtils.mid(pnts[0], pnts[2])
// pnts.push(mid, pnts[0], pnts[1])
// let [normals, pnt1, pnt2, pnt3, result, result2] = [[], undefined, undefined, undefined, [], []]
// for (let i = 0; i < pnts.length - 2; i++) {
// pnt1 = pnts[i]
// pnt2 = pnts[i + 1]
// pnt3 = pnts[i + 2]
// let normalPoints = P.PlotUtils.getBisectorNormals(0.4, pnt1, pnt2, pnt3)
// normals = normals.concat(normalPoints)
// }
// let count = normals.length
// normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
// for (let i = 0; i < pnts.length - 2; i++) {
// pnt1 = pnts[i]
// pnt2 = pnts[i + 1]
// result = result.concat([...pnt1, 0])
// result2.push(
// {
// lng: pnt1[0],
// lat: pnt1[1],
// alt: 0
// }
// )
// for (let t = 0; t <= P.Constants.FITTING_COUNT; t++) {
// let pnt = P.PlotUtils.getCubicValue(t / P.Constants.FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
// result = result.concat([...pnt, 0])
// result2.push(
// {
// lng: pnt[0],
// lat: pnt[1],
// alt: 0
// }
// )
// }
// result = result.concat([...pnt2, 0])
// result2.push(
// {
// lng: pnt2[0],
// lat: pnt2[1],
// alt: 0
// }
// )
// }
// this.position = result2
// this.points = result
// }
// }
calculateVector(v, theta, d) {
if (!theta) theta = Math.PI / 2
if (!d) d = 1
let x_1
let x_2
let y_1
let y_2
let v_l
let v_r
let d_v = Math.sqrt(v.x * v.x + v.y * v.y)
if (v.y == 0) {
x_1 = x_2 = (d_v * d * Math.cos(theta)) / v.x
if (v.x > 0) {
y_1 = Math.sqrt(d * d - x_1 * x_1)
y_2 = -y_1
} else if (v.x < 0) {
y_2 = Math.sqrt(d * d - x_1 * x_1)
y_1 = -y_2
}
v_l = { x: x_1, y: y_1 }
v_r = { x: x_2, y: y_2 }
} else {
let n = -v.x / v.y
let m = (d * d_v * Math.cos(theta)) / v.y
let a = 1 + n * n
let b = 2 * n * m
let c = m * m - d * d
x_1 = (-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a)
x_2 = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a)
y_1 = n * x_1 + m
y_2 = n * x_2 + m
if (v.y >= 0) {
v_l = { x: x_1, y: y_1 }
v_r = { x: x_2, y: y_2 }
} else if (v.y < 0) {
v_l = { x: x_2, y: y_2 }
v_r = { x: x_1, y: y_1 }
}
}
return [v_l, v_r]
}
createCloseCardinal(points) {
if (points == null || points.length < 3) {
return points
}
//获取起点,作为终点,以闭合曲线。
let lastP = points[0]
points.push(lastP)
//定义传入的点数组,将在点数组中央(每两个点)插入两个控制点
let cPoints = points
//包含输入点和控制点的数组
let cardinalPoints = []
//至少三个点以上
//这些都是相关资料测出的经验数值
//定义张力系数取值在0<t<0.5
let t = 0.4
//为端点张力系数因子取值在0<b<1
// let b = 0.5;
//误差控制是一个大于等于0的数用于三点非常趋近与一条直线时减少计算量
let e = 0.005
//传入的点数量至少有三个n至少为2
let n = cPoints.length - 1
//从开始遍历到倒数第二个,其中倒数第二个用于计算起点(终点)的插值控制点
for (let k = 0; k <= n - 1; k++) {
let p0, p1, p2
//计算起点(终点)的左右控制点
if (k == n - 1) {
//三个基础输入点
p0 = cPoints[n - 1]
p1 = cPoints[0]
p2 = cPoints[1]
} else {
p0 = cPoints[k]
p1 = cPoints[k + 1]
p2 = cPoints[k + 2]
}
//定义p1的左控制点和右控制点
let p1l = { x: undefined, y: undefined }
let p1r = { x: undefined, y: undefined }
//通过p0、p1、p2计算p1点的做控制点p1l和又控制点p1r
//计算向量p0_p1和p1_p2
let p0_p1 = { x: p1.x - p0.x, y: p1.y - p0.y }
let p1_p2 = { x: p2.x - p1.x, y: p2.y - p1.y }
//并计算模
let d01 = Math.sqrt(p0_p1.x * p0_p1.x + p0_p1.y * p0_p1.y)
let d12 = Math.sqrt(p1_p2.x * p1_p2.x + p1_p2.y * p1_p2.y)
//向量单位化
let p0_p1_1 = { x: p0_p1.x / d01, y: p0_p1.y / d01 }
let p1_p2_1 = { x: p1_p2.x / d12, y: p1_p2.y / d12 }
//计算向量p0_p1和p1_p2的夹角平分线向量
let p0_p1_p2 = { x: p0_p1_1.x + p1_p2_1.x, y: p0_p1_1.y + p1_p2_1.y }
//计算向量 p0_p1_p2 的模
let d012 = Math.sqrt(p0_p1_p2.x * p0_p1_p2.x + p0_p1_p2.y * p0_p1_p2.y)
//单位化向量p0_p1_p2
let p0_p1_p2_1 = { x: p0_p1_p2.x / d012, y: p0_p1_p2.y / d012 }
//判断p0、p1、p2是否共线这里判定向量p0_p1和p1_p2的夹角的余弦和1的差值小于e就认为三点共线
let cosE_p0p1p2 = (p0_p1_1.x * p1_p2_1.x + p0_p1_1.y * p1_p2_1.y) / 1
//共线
if (Math.abs(1 - cosE_p0p1p2) < e) {
//计算p1l的坐标
p1l.x = p1.x - p1_p2_1.x * d01 * t
p1l.y = p1.y - p1_p2_1.y * d01 * t
//计算p1r的坐标
p1r.x = p1.x + p0_p1_1.x * d12 * t
p1r.y = p1.y + p0_p1_1.y * d12 * t
}
//非共线
else {
//计算p1l的坐标
p1l.x = p1.x - p0_p1_p2_1.x * d01 * t
p1l.y = p1.y - p0_p1_p2_1.y * d01 * t
//计算p1r的坐标
p1r.x = p1.x + p0_p1_p2_1.x * d12 * t
p1r.y = p1.y + p0_p1_p2_1.y * d12 * t
}
//记录起点(终点)的左右插值控制点及倒数第二个控制点
if (k == n - 1) {
cardinalPoints[0] = p1
cardinalPoints[1] = p1r
cardinalPoints[(n - 2) * 3 + 2 + 3] = p1l
cardinalPoints[(n - 2) * 3 + 2 + 4] = cPoints[n]
} else {
//记录下这三个控制点
cardinalPoints[k * 3 + 2 + 0] = p1l
cardinalPoints[k * 3 + 2 + 1] = p1
cardinalPoints[k * 3 + 2 + 2] = p1r
}
}
return cardinalPoints
}
calculatePointsFBZ3(points, part) {
if (!part) part = 20
//获取待拆分的点
let bezierPts = []
let scale = 0.05
if (part > 0) {
scale = 1 / part
}
for (let i = 0; i < points.length - 3;) {
//起始点
let pointS = points[i]
//第一个控制点
let pointC1 = points[i + 1]
//第二个控制点
let pointC2 = points[i + 2]
//结束点
let pointE = points[i + 3]
bezierPts.push(pointS)
for (let t = 0; t < 1;) {
//三次贝塞尔曲线公式
let x =
(1 - t) * (1 - t) * (1 - t) * pointS.x +
3 * t * (1 - t) * (1 - t) * pointC1.x +
3 * t * t * (1 - t) * pointC2.x +
t * t * t * pointE.x
let y =
(1 - t) * (1 - t) * (1 - t) * pointS.y +
3 * t * (1 - t) * (1 - t) * pointC1.y +
3 * t * t * (1 - t) * pointC2.y +
t * t * t * pointE.y
let point = { x: x, y: y }
bezierPts.push(point)
t += scale
}
i += 3
if (i >= points.length) {
bezierPts.push(pointS)
}
}
return bezierPts
}
}
export default DrawAssemble