/** * @description 道路 */ import Dialog from '../../Element/Dialog'; import { html } from "./_element"; import EventBinding from '../../Element/Dialog/eventBinding'; import Base from "../index"; import { syncData } from '../../../Global/MultiViewportMode' import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen' import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../Global/global' class Road extends Base { /** * @constructor * @param sdk * @description 道路 * @param options {object} 道路属性 * @param options.name=未命名对象 {string} 名称 * @param options.carRoadWidth=2 {number} 车道宽度 * @param options.sideWidth=2 {number} 人行道宽度 * @param options.positions=[] {array} 道路positions * @param options.roadImage='' {string} 车道贴图 * @param options.sideImage='' {string} 人行道贴图 * @param Dialog {object} 弹框对象 * @param Dialog.confirmCallBack {function} 弹框确认时的回调 * */ constructor(sdk, options = {}, _Dialog = {}) { super(sdk, options); this.viewer = this.sdk.viewer this.options.name = options.name || '道路' this.options.carRoadWidth = options.carRoadWidth || 10 this.options.sideWidth = options.sideWidth || 5 this.options.positions = options.positions || [] this.options.roadImage = options.roadImage || (this.getSourceRootPath() + '/img/roadPhoto.png') this.options.sideImage = options.sideImage || (this.getSourceRootPath() + '/img/sidePhoto.png') this.options.show = (options.show || options.show === false) ? options.show : true this.Dialog = _Dialog this._EventBinding = new EventBinding() this._elms = {}; this.positionArea = [] this.positions = [] this.lineEntity = '' this.crossArr = [] this.pointArr = [] this.sdk.addIncetance(this.options.id, this) Road.create(this) } // 创建道路 static create(that) { let positions = [] that.options.positions.forEach(v => { positions.push(new Cesium.Cartesian3.fromDegrees(v.lng, v.lat, v.alt)) }) let newPosi = [] for (let i = 0; i < positions.length - 1; i++) { const start = positions[i]; const end = positions[i + 1]; newPosi.push([start, end]) that.pointArr = newPosi } let area = [[], [], []] // area[1] = that.getRectangle(positions, that.options.carRoadWidth) area[1][0] = that.getRectangle(newPosi, that.options.carRoadWidth) let sideArr = that.getSideRectangle(area[1][0], that.options.sideWidth) area[0] = sideArr.left area[2] = sideArr.right // area[1] = that.createLineBufferPolygon2(positions, that.options.carRoadWidth / 2) // area[1] = newPositions // area[0] = that.createLineBufferPolygonSide(area[1][2], -that.options.sideWidth) // area[2] = that.createLineBufferPolygonSide(area[1][1], that.options.sideWidth) //判断道路边是否相交 for (let i = 0; i < area[0].length - 1; i++) { let leftItem = area[0][i] let leftItem2 = area[0][i + 1] let rightItem = area[2][i] let rightItem2 = area[2][i + 1] let carItem = area[1][0][i] let carItem2 = area[1][0][i + 1] let leftLine = that.getIntersects(leftItem[2], leftItem[3], leftItem2[2], leftItem2[3]) let rightLine = that.getIntersects(rightItem[0], rightItem[1], rightItem2[0], rightItem2[1]) console.log(leftLine, rightLine, 'leftLine') if (leftLine) {//左侧相交 //获取右侧延长交点 let point1 = that.getExtendPoint(rightItem[0], rightItem[1], 1000) let point2 = that.getExtendPoint(rightItem2[1], rightItem2[0], 1000) console.log('aaaa') let rightIntersection = that.getIntersects(rightItem[0], point1, rightItem2[1], point2) //将其他几条边都延长 let leftLineNeiPoint = that.getExtendPoint(leftItem[0], leftItem[1], 1000) let carLeftPoint = that.getExtendPoint(carItem[3], carItem[2], 1000) let carRightPoint = that.getExtendPoint(carItem[0], carItem[1], 1000) let rightLineNeiPoint = that.getExtendPoint(rightItem[3], rightItem[2], 1000) console.log(leftLine, rightIntersection, leftItem[0], leftLineNeiPoint, 'bbbb') //跟左侧里相交点 let leftLineNei = that.getIntersects(leftLine, rightIntersection, leftItem[0], leftLineNeiPoint) console.log(leftLineNei, 'leftLineNei') //跟车道左侧相交点 let carLeft = that.getIntersects(leftLine, rightIntersection, carItem[3], carLeftPoint) //跟车道右侧相交点 let carRight = that.getIntersects(leftLine, rightIntersection, carItem[0], carRightPoint) let rightLineNei = that.getIntersects(leftLine, rightIntersection, rightItem[3], rightLineNeiPoint) console.log('ccc') // let leftLineNei = that.getIntersects(leftLine, rightItem[2], leftItem[0], leftItem[3]) // let carLeft = that.getIntersects(leftLine, rightItem[2], carItem[3], carItem[2]) // let carRight = that.getIntersects(leftLine, rightItem[2], carItem[0], carItem[1]) // let rightLineNei = that.getIntersects(leftLine, rightItem[2], rightItem[0], rightItem[3]) // let leftLineNei = that.getIntersects(leftLine, intersection, leftItem[0], leftItem[3]) // //跟车道左侧相交点 // let carLeft = that.getIntersects(leftLine, intersection, carItem[3], carItem[2]) // //跟车道右侧相交点 // let carRight = that.getIntersects(leftLine, intersection, carItem[0], carItem[1]) // let rightLineNei = that.getIntersects(leftLine, intersection, rightItem[0], rightItem[3]) leftItem[2] = leftLine leftItem[1] = leftLineNei carItem[2] = carLeft carItem[1] = carRight rightItem[2] = rightLineNei rightItem[1] = rightIntersection console.log(leftItem, carItem, rightItem, 'leftItemleft') //将其他几条边都延长 let leftLineNeiPoint2 = that.getExtendPoint(leftItem2[1], leftItem2[0], 1000) let carLeftPoint2 = that.getExtendPoint(carItem2[2], carItem2[3], 1000) let carRightPoint2 = that.getExtendPoint(carItem2[1], carItem2[0], 1000) let rightLineNeiPoint2 = that.getExtendPoint(rightItem2[2], rightItem2[3], 1000) // let leftLineNei2 = that.getIntersects(leftLine, rightItem2[1], leftItem2[0], leftItem2[3]) // let carLeft2 = that.getIntersects(leftLine, rightItem2[1], carItem2[3], carItem2[2]) // let carRight2 = that.getIntersects(leftLine, rightItem2[1], carItem2[0], carItem2[1]) // let rightLineNei2 = that.getIntersects(leftLine, rightItem2[1], rightItem2[0], rightItem2[3]) let leftLineNei2 = that.getIntersects(leftLine, rightIntersection, leftItem2[1], leftLineNeiPoint2) let carLeft2 = that.getIntersects(leftLine, rightIntersection, carItem2[2], carLeftPoint2) let carRight2 = that.getIntersects(leftLine, rightIntersection, carItem2[1], carRightPoint2) let rightLineNei2 = that.getIntersects(leftLine, rightIntersection, rightItem2[2], rightLineNeiPoint2) // let arr = [leftLine, rightIntersection, leftItem2[3], leftLineNeiPoint2] // arr.forEach((item, index) => { // that.sdk.viewer.entities.add({ // name: 'node-secondary-edit-point', // index: i, // position: item, // billboard: { // image: that.getSourceRootPath() + '/img/point.png', // width: 15, // height: 15, // disableDepthTestDistance: Number.POSITIVE_INFINITY, // color: Cesium.Color.WHITE.withAlpha(0.99) // }, // label: { // text: '' + index, // pixelOffset: { x: 0, y: -20 }, // }, // }) // }) // let leftLineNei2 = that.getIntersects(leftLine, intersection, leftItem2[0], leftItem2[3]) // //跟车道左侧相交点 // let carLeft2 = that.getIntersects(leftLine, intersection, carItem2[3], carItem2[2]) // //跟车道右侧相交点 // let carRight2 = that.getIntersects(leftLine, intersection, carItem2[0], carItem2[1]) // let rightLineNei2 = that.getIntersects(leftLine, intersection, rightItem2[0], rightItem2[3]) leftItem2[3] = leftLine leftItem2[0] = leftLineNei carItem2[3] = carLeft carItem2[0] = carRight rightItem2[3] = rightLineNei rightItem2[0] = rightIntersection console.log(leftItem2, carItem2, rightItem2, 'leftItem2left') } else if (rightLine) {//右侧相交 //获取左侧延长交点 let point1 = that.getExtendPoint(leftItem[3], leftItem[2], 1000) let point2 = that.getExtendPoint(leftItem2[2], leftItem2[3], 1000) let rightIntersection = that.getIntersects(leftItem[3], point1, leftItem2[2], point2) if (!rightIntersection) { return } //将其他几条边都延长 let leftLineNeiPoint = that.getExtendPoint(leftItem[0], leftItem[1], 1000) let carLeftPoint = that.getExtendPoint(carItem[3], carItem[2], 1000) let carRightPoint = that.getExtendPoint(carItem[0], carItem[1], 1000) let rightLineNeiPoint = that.getExtendPoint(rightItem[3], rightItem[2], 1000) // //跟左侧里相交点 let leftLineNei = that.getIntersects(rightLine, rightIntersection, leftItem[0], leftLineNeiPoint) //跟车道左侧相交点 let carLeft = that.getIntersects(rightLine, rightIntersection, carItem[3], carLeftPoint) //跟车道右侧相交点 let carRight = that.getIntersects(rightLine, rightIntersection, carItem[0], carRightPoint) let rightLineNei = that.getIntersects(rightLine, rightIntersection, rightItem[3], rightLineNeiPoint) // //跟左侧里相交点 // let leftLineNei = that.getIntersects(rightLine, leftItem[2], leftItem[0], leftItem[3]) // //跟车道左侧相交点 // let carLeft = that.getIntersects(rightLine, leftItem[2], carItem[3], carItem[2]) // //跟车道右侧相交点 // let carRight = that.getIntersects(rightLine, leftItem[2], carItem[0], carItem[1]) // let rightLineNei = that.getIntersects(rightLine, leftItem[2], rightItem[0], rightItem[3]) leftItem[2] = rightIntersection leftItem[1] = leftLineNei carItem[2] = carLeft carItem[1] = carRight rightItem[2] = rightLineNei rightItem[1] = rightLine console.log(leftItem, carItem, rightItem, 'leftItemright') //将其他几条边都延长 let leftLineNeiPoint2 = that.getExtendPoint(leftItem2[2], leftItem2[3], 1000) let carLeftPoint2 = that.getExtendPoint(carItem2[2], carItem2[3], 1000) let carRightPoint2 = that.getExtendPoint(carItem2[1], carItem2[0], 1000) let rightLineNeiPoint2 = that.getExtendPoint(rightItem2[2], rightItem2[3], 1000) let leftLineNei2 = that.getIntersects(rightLine, rightIntersection, leftItem2[1], leftLineNeiPoint2) //跟车道左侧相交点 let carLeft2 = that.getIntersects(rightLine, rightIntersection, carItem2[2], carLeftPoint2) //跟车道右侧相交点 let carRight2 = that.getIntersects(rightLine, rightIntersection, carItem2[1], carRightPoint2) let rightLineNei2 = that.getIntersects(rightLine, rightIntersection, rightItem2[2], rightLineNeiPoint2) // let leftLineNei2 = that.getIntersects(rightLine, leftItem2[1], leftItem2[0], leftItem2[3]) // //跟车道左侧相交点 // let carLeft2 = that.getIntersects(rightLine, leftItem2[1], carItem2[3], carItem2[2]) // //跟车道右侧相交点 // let carRight2 = that.getIntersects(rightLine, leftItem2[1], carItem2[0], carItem2[1]) // let rightLineNei2 = that.getIntersects(rightLine, leftItem2[1], rightItem2[0], rightItem2[3]) leftItem2[3] = rightIntersection leftItem2[0] = leftLineNei carItem2[3] = carLeft carItem2[0] = carRight rightItem2[3] = rightLineNei rightItem2[0] = rightLine console.log(leftItem2, carItem2, rightItem2, 'leftItem2right') } } if (that.viewer.entities.getById(that.options.id)) { that.viewer.entities.getById(that.options.id)._children.forEach((item) => { that.viewer.entities.remove(item); }); that.viewer.entities.remove(that.viewer.entities.getById(that.options.id)) } that.lineEntity = that.viewer.entities.add(new Cesium.Entity({ id: that.options.id, show: that.options.show })) const myImg = new Image() myImg.src = that.options.roadImage myImg.onload = function () { console.log(area[1][0], that.options.roadImage, 'llll') area[1][0].forEach((item, index) => { that.viewer.entities.add({ // id: that.options.id, parent: that.lineEntity, polygon: { hierarchy: new Cesium.PolygonHierarchy(item), material: new Cesium.ImageMaterialProperty({ image: that.options.roadImage, transparent: true,// 如果图片有透明部分,需要设置为 true repeat: that.calculateTextureRepeat(item, myImg) }), stRotation: that.calculateRoadAngle(positions[index], positions[index + 1]) } }); }) } const myImg2 = new Image() myImg2.src = that.options.sideImage myImg2.onload = function () { // area[0].forEach((item, index) => { area[0].forEach((item, index) => { that.viewer.entities.add({ parent: that.lineEntity, polygon: { hierarchy: new Cesium.PolygonHierarchy(item), material: new Cesium.ImageMaterialProperty({ image: that.options.sideImage, transparent: true,// 如果图片有透明部分,需要设置为 true repeat: that.calculateTextureRepeat(item, myImg2) }), stRotation: that.calculateRoadAngle(positions[index], positions[index + 1]) } }); }) // area[2].forEach((item, index) => { area[2].forEach((item, index) => { that.viewer.entities.add({ polygon: { hierarchy: new Cesium.PolygonHierarchy(item), material: new Cesium.ImageMaterialProperty({ image: that.options.sideImage, transparent: true,// 如果图片有透明部分,需要设置为 true repeat: that.calculateTextureRepeat(item, myImg2) }), stRotation: that.calculateRoadAngle(positions[index], positions[index + 1]) } }); }) } } getSideRectangle(positions, width) { let right = [] let left = [] let that = this positions.forEach(item => { right.push([item[0], item[1]]) left.push([item[2], item[3]]) }) let rightPosi = that.getRectangle(right, width, 'side') let leftPosi = this.getRectangle(left, width, 'side') return { left: leftPosi, right: rightPosi } } getRectangle(positions, width, type) { let areaArr = [] let newPositions = [] let that = this // for (let i = 0; i < positions.length - 1; i++) { for (let i = 0; i < positions.length; i++) { const start = positions[i][0]; const end = positions[i][1]; areaArr[i] = [] let posi = [] let Outlinegeometry = new Cesium.CorridorGeometry({ positions: [start, end], width: width, cornerType: Cesium.CornerType.MITERED, vertexFormat: Cesium.MaterialAppearance.MaterialSupport.ALL.vertexFormat }) let geometry = Cesium.CorridorGeometry.createGeometry(Outlinegeometry) for (let j = 0; j < geometry.attributes.position.values.length; j += 3) { let val = that.cartesian3Towgs84(new Cesium.Cartesian3(geometry.attributes.position.values[j], geometry.attributes.position.values[j + 1], geometry.attributes.position.values[j + 2]), that.sdk.viewer) posi.push([val.lng, val.lat]) } for (let x = 0; x < geometry.indices.length; x += 3) { areaArr[i].push(turf.polygon([[posi[geometry.indices[x]], posi[geometry.indices[x + 1]], posi[geometry.indices[x + 2]], posi[geometry.indices[x]]]])) } let geojson = turf.union(areaArr[i][0], areaArr[i][1]); let arr = [] geojson.geometry.coordinates[0].pop() geojson.geometry.coordinates[0].forEach(item => { arr.push(new Cesium.Cartesian3.fromDegrees(item[0], item[1])) }) let dotResult, angle const tempVec = new Cesium.Cartesian3(); // 计算并归一化第一个向量 const vector1 = Cesium.Cartesian3.normalize( Cesium.Cartesian3.subtract(that.pointArr[i][1], that.pointArr[i][0], tempVec), tempVec ); // 计算并归一化第二个向量 const vector2 = Cesium.Cartesian3.normalize( Cesium.Cartesian3.subtract(arr[1], arr[0], new Cesium.Cartesian3()), new Cesium.Cartesian3() ); dotResult = Cesium.Cartesian3.dot(vector1, vector2); if ((0.999 < dotResult && dotResult < 1.001) || (-0.999 > dotResult && dotResult > -1.001)) {//调整方向 newPositions.push(arr) } else { let newArr = [] newArr[0] = arr[1] newArr[1] = arr[2] newArr[2] = arr[3] newArr[3] = arr[0] newPositions.push(newArr) } // } // if (!type) { // // if (cross > 0 && !type) {//调整方向 // if ((0.999 < dotResult && dotResult < 1.001) || (-0.999 > dotResult && dotResult > -1.001)) {//调整方向 // newPositions.push(arr) // } else { // let newArr = [] // newArr[0] = arr[1] // newArr[1] = arr[2] // newArr[2] = arr[3] // newArr[3] = arr[0] // newPositions.push(newArr) // } // } else { // newPositions.push(arr) // } } return newPositions } getExtendPoint(position1, position2, distance) { // let position1 = Cesium.Cartesian3.fromDegrees(p1[0], p1[1], 0); // let position2 = Cesium.Cartesian3.fromDegrees(p2[0], p2[1], 0); let pot = Cesium.Cartesian3.subtract(position2, position1, new Cesium.Cartesian3());//方向 var dir = Cesium.Cartesian3.normalize(pot, new Cesium.Cartesian3());//向量归一化 var ray = new Cesium.Ray(position1, dir); let np = Cesium.Ray.getPoint(ray, distance * 10);//计算延长点 return np } getArr(arr1, arr2) { arr2 = arr2.reverse() let polygon = [] for (let index = 0; index < arr1.length - 1; index++) { polygon.push([arr1[index], arr1[index + 1], arr2[index + 1], arr2[index]]) } return polygon } calculateRoadAngle2(startPoint, endPoint) { // 1. 获取地表法向量 const normal = this.sdk.viewer.scene.globe.ellipsoid.geodeticSurfaceNormal( startPoint, new Cesium.Cartesian3()); // 2. 构建带椭球参数的ENU矩阵 const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame( startPoint, this.sdk.viewer.scene.globe.ellipsoid, normal); const inverseMatrix = Cesium.Matrix4.inverse( enuMatrix, new Cesium.Matrix4()); // 3. 转换坐标并计算相对向量 const localEnd = Cesium.Matrix4.multiplyByPoint( inverseMatrix, endPoint, new Cesium.Cartesian3()); const heightFactor = Math.abs(localEnd.z) / 1000; // 高度差补偿 // 4. 使用四象限反正切计算角度 const angle = Math.atan2(localEnd.y, localEnd.x); const adjustedAngle = angle - (heightFactor * 0.01); // 高度补偿 let result = Cesium.Math.toDegrees(adjustedAngle) console.log(result, 'result') return result; } calculateRoadAngle(startPoint, endPoint) { // 1. 获取地表法向量 const normal = Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(startPoint); // 2. 构建精确ENU坐标系 const enuMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(startPoint, undefined, normal); const inverseMatrix = Cesium.Matrix4.inverse(enuMatrix, new Cesium.Matrix4()); // 3. 转换终点并计算水平向量 const localEnd = Cesium.Matrix4.multiplyByPoint(inverseMatrix, endPoint, new Cesium.Cartesian3()); const horizontalVec = new Cesium.Cartesian2(localEnd.x, localEnd.y); Cesium.Cartesian2.normalize(horizontalVec, horizontalVec); const north = new Cesium.Cartesian2(1, 0); const angle = Cesium.Cartesian2.angleBetween(north, horizontalVec); const cross = Cesium.Cartesian2.cross(north, horizontalVec, new Cesium.Cartesian2()); return cross < 0 ? angle : -angle; } calculatePolygonOrientation(positions) { // 假设 position 是 Cesium.Cartesian3 对象,表示地球上的某个点 var position = positions[0] // 获取东、北、上坐标系 var eastNorthUp = Cesium.Transforms.eastNorthUpToFixedFrame(position); // northAxis 是北方向向量 var northAxis = eastNorthUp.getColumn(1, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(northAxis, northAxis); const direction = Cesium.Cartesian3.subtract(positions[0], positions[1], new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(direction, direction); const dot = Cesium.Cartesian3.dot(northAxis, direction); const magA = Cesium.Cartesian3.magnitude(northAxis); const magB = Cesium.Cartesian3.magnitude(direction); return Math.acos(dot / (magA * magB)); } calculateTextureRepeat(polygonPositions, textureSize, meterPerPixel = 0.01) { // 验证纹理尺寸 if (!textureSize.width || !textureSize.height) { throw new Error('Texture size must contain width and height in pixels'); } // 创建多边形几何体 const geometry = Cesium.PolygonGeometry.createGeometry( new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy(polygonPositions), vertexFormat: Cesium.VertexFormat.POSITION_ONLY }) ); // 计算多边形面积(平方米) let area = 0; const indices = geometry.indices; const positions = geometry.attributes.position.values; for (let i = 0; i < indices.length; i += 3) { const i0 = indices[i] * 3; const i1 = indices[i + 1] * 3; const i2 = indices[i + 2] * 3; const p0 = new Cesium.Cartesian3(positions[i0], positions[i0 + 1], positions[i0 + 2]); const p1 = new Cesium.Cartesian3(positions[i1], positions[i1 + 1], positions[i1 + 2]); const p2 = new Cesium.Cartesian3(positions[i2], positions[i2 + 1], positions[i2 + 2]); const cross = Cesium.Cartesian3.cross( Cesium.Cartesian3.subtract(p1, p0, new Cesium.Cartesian3()), Cesium.Cartesian3.subtract(p2, p0, new Cesium.Cartesian3()), new Cesium.Cartesian3() ); area += Cesium.Cartesian3.magnitude(cross) * 0.5; } // 将像素尺寸转换为实际尺寸(平方米) const textureWidthMeters = textureSize.width * meterPerPixel; const textureHeightMeters = textureSize.height * meterPerPixel; const textureArea = textureWidthMeters * textureHeightMeters; // 计算各轴向重复次数 const repeatX = Math.sqrt(area) / textureWidthMeters; const repeatY = Math.sqrt(area) / textureHeightMeters; return new Cesium.Cartesian2(Math.max(1, Math.ceil(repeatX)), 1.0); } swapLastElements(arr1, arr2) { const last = arr1[arr1.length - 1] const first = arr2[0] arr1[arr1.length - 1] = first arr2[0] = last return [arr1, arr2]; } createLineBufferPolygonSide(positions, width) { let area = [] for (let i = 0; i < positions.length; i++) { const posi = positions[i]; const dir = Cesium.Cartesian3.subtract(posi[1], posi[0], new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(dir, dir); // 获取垂直向量(基于Z轴) const perp = Cesium.Cartesian3.cross(dir, Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(perp, perp); // 生成偏移向量 const offset = Cesium.Cartesian3.multiplyByScalar(perp, width, new Cesium.Cartesian3()); let point1 = Cesium.Cartesian3.add(posi[0], offset, new Cesium.Cartesian3()) let point3 = Cesium.Cartesian3.add(posi[1], offset, new Cesium.Cartesian3()) // i == positions.length - 2 ? area.push(start, point1, end, point3) : area.push(start, point1) area.push([posi[0], point1, point3, posi[1]]) } // let arr = [] // for (let i = 0; i < area.length - 2; i += 2) { // arr.push([area[i], area[i + 1], area[i + 3], area[i + 2]]) // } return area } createLineBufferPolygon2(positions, width) { let area = [] let leftPositions = []; let rightPositions = []; for (let i = 0; i < positions.length - 1; i++) { const start = positions[i]; // const end = positions[i + 1] || positions[i - 1]; const end = positions[i + 1]; const dir = Cesium.Cartesian3.subtract(end, start, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(dir, dir); // 获取垂直向量(基于Z轴) const perp = Cesium.Cartesian3.cross(dir, Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(perp, perp); const dir2 = Cesium.Cartesian3.subtract(start, end, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(dir2, dir2); // 获取垂直向量(基于Z轴) const perp2 = Cesium.Cartesian3.cross(dir2, Cesium.Cartesian3.UNIT_Z, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(perp2, perp2); // 生成偏移向量 const offset = Cesium.Cartesian3.multiplyByScalar(perp, width, new Cesium.Cartesian3()); const offset2 = Cesium.Cartesian3.multiplyByScalar(perp, -width, new Cesium.Cartesian3()); const offsetEnd = Cesium.Cartesian3.multiplyByScalar(perp2, -width, new Cesium.Cartesian3()); const offsetEnd2 = Cesium.Cartesian3.multiplyByScalar(perp2, width, new Cesium.Cartesian3()); let point1 = Cesium.Cartesian3.add(start, offset, new Cesium.Cartesian3()) let point2 = Cesium.Cartesian3.add(start, offset2, new Cesium.Cartesian3()) let point3 = Cesium.Cartesian3.add(end, offsetEnd, new Cesium.Cartesian3()) let point4 = Cesium.Cartesian3.add(end, offsetEnd2, new Cesium.Cartesian3()) area.push([point1, point3, point4, point2]) rightPositions.push([point1, point3]) leftPositions.push([point2, point4]) // if (i == positions.length - 2) { // area.push(point1, point2, point3, point4) // rightPositions.push(point1) // leftPositions.push(point2) // leftPositions.push(point4) // rightPositions.push(point3) // } else { // area.push(point1, point2) // rightPositions.push(point1) // leftPositions.push(point2) // } } // let arr = [] // for (let i = 0; i < area.length - 2; i += 2) { // arr.push([area[i], area[i + 1], area[i + 3], area[i + 2]]) // } console.log(area, rightPositions, 'rightPositions') let that = this // return [arr, rightPositions, leftPositions] return [area, rightPositions, leftPositions] } getIntersects(point1, point2, point3, point4) { let carPoint1 = this.getLonLat(point1) let carPoint2 = this.getLonLat(point2) let carPoint3 = this.getLonLat(point3) let carPoint4 = this.getLonLat(point4) var line1 = turf.lineString([ [carPoint1.lon, carPoint1.lat], [carPoint2.lon, carPoint2.lat] ]); var line2 = turf.lineString([ [carPoint3.lon, carPoint3.lat], [carPoint4.lon, carPoint4.lat] ]); var intersects = turf.lineIntersect(line1, line2); if (intersects.features.length > 0) { return Cesium.Cartesian3.fromDegrees(intersects.features[0].geometry.coordinates[0], intersects.features[0].geometry.coordinates[1]) } } getLonLat(point) { let pointDe = Cesium.Cartographic.fromCartesian(point) const longitude = Cesium.Math.toDegrees(pointDe.longitude); const latitude = Cesium.Math.toDegrees(pointDe.latitude); return { lon: longitude, lat: latitude } } createLineBufferPolygon(viewer, positions, width) { // 计算每个线段的左右偏移点 const leftPositions = []; const rightPositions = []; for (let i = 0; i < positions.length; i++) { const start = positions[i]; const end = positions[i + 1] || positions[i - 1]; // 计算线段方向向量 const direction = Cesium.Cartesian3.subtract(end, start, new Cesium.Cartesian3()); // const direction = Cesium.Cartesian3.subtract(start, end, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(direction, direction); // 计算垂直向量(使用上向量叉积) const up = Cesium.Cartesian3.UNIT_Z; const perpendicular = Cesium.Cartesian3.cross(direction, up, new Cesium.Cartesian3()); Cesium.Cartesian3.normalize(perpendicular, perpendicular); // 计算左右偏移点 const leftOffset = Cesium.Cartesian3.multiplyByScalar( perpendicular, width, new Cesium.Cartesian3() ); if (width > 0) { rightPositions.unshift(Cesium.Cartesian3.add(start, leftOffset, new Cesium.Cartesian3())); } else if (width < 0) { rightPositions.push(Cesium.Cartesian3.add(start, leftOffset, new Cesium.Cartesian3())); } } return rightPositions } //计算角度 calculateAangle(arr) { // let fromDegreesArray = that.calSector(that.options.center, that.options.radius, that.options.startAngle, that.options.endAngle, 360, true) function getAangle(start, end) { let rad = Math.PI / 180, lat1 = start.y * rad, lat2 = end.y * rad, lon1 = start.x * rad, lon2 = end.x * rad; const a = Math.sin(lon2 - lon1) * Math.cos(lat2); const b = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1); const radians = Math.atan2(a, b) const degrees = radians % (2 * Math.PI); let bearing = 450 - ((degrees * 180) / Math.PI < 0 ? 360 + (degrees * 180) / Math.PI : (degrees * 180) / Math.PI) - 90; return 360 - (bearing % 360) } let center = arr[0] let pos84_1 = arr[1] let pos84_2 = arr[2] let start = { x: center.lng, y: center.lat } let end1 = { x: pos84_1.lng, y: pos84_1.lat } let end2 = { x: pos84_2.lng, y: pos84_2.lat } let angle1 = getAangle(start, end1) let angle2 = getAangle(start, end2) return { angle1, angle2 } } get carRoadWidth() { return this.options.carRoadWidth } set carRoadWidth(v) { this.options.carRoadWidth = v Road.create(this) } get sideWidth() { return this.options.sideWidth } set sideWidth(v) { this.options.sideWidth = v Road.create(this) } /** * @description 编辑框 * @param state=false {boolean} 状态: true打开, false关闭 */ async edit(state = false) { let _this = this this.originalOptions = this.deepCopyObj(this.options) if (this._DialogObject && this._DialogObject.close) { this._DialogObject.close() this._DialogObject = null } if (state) { this._DialogObject = await new Dialog(this.sdk, this.originalOptions, { title: '道路属性', left: '180px', top: '100px', confirmCallBack: (options) => { this.name = this.name.trim() if (!this.name) { this.name = '道路' } this.originalOptions = this.deepCopyObj(this.options) this._DialogObject.close() this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions) syncData(this.sdk, this.options.id) syncSplitData(this.sdk, this.options.id) }, resetCallBack: () => { this.reset() this.Dialog.resetCallBack && this.Dialog.resetCallBack() }, closeCallBack: () => { this.reset() this.Dialog.closeCallBack && this.Dialog.closeCallBack() }, showCallBack: (show) => { this.show = show this.Dialog.showCallBack && this.Dialog.showCallBack() } }, true) this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' road-surface' let contentElm = document.createElement('div'); contentElm.innerHTML = html() this._DialogObject.contentAppChild(contentElm) // 下拉选项 // let heightModeData = [ // { // name: '海拔高度', // value: '海拔高度', // key: '0', // }, // { // name: '相对地表', // value: '相对地表', // key: '1', // }, // { // name: '依附模型', // value: '依附模型', // key: '2', // } // ] // let heightModeObject = legp( // this._DialogObject._element.content.getElementsByClassName( // 'road-box' // )[0], // '.road-type' // ) // if (heightModeObject) { // heightModeObject.legp_search(heightModeData) // let heightModeDataLegpElm = this._DialogObject._element.content // .getElementsByClassName('road-type')[0] // .getElementsByTagName('input')[0] // for (let i = 0; i < heightModeData.length; i++) { // if (heightModeData[i].key == this.heightMode) { // heightModeDataLegpElm.value = heightModeData[i].value // heightModeObject.legp_searchActive( // heightModeData[i].value // ) // break // } // } // heightModeDataLegpElm.addEventListener('input', () => { // for (let i = 0; i < heightModeData.length; i++) { // if (heightModeData[i].value === heightModeDataLegpElm.value) { // this.heightMode = heightModeData[i].key // break // } // } // }) // this._elms.height = heightElm // this._elms.heightBox = heightBoxElm // this._elms.heightMode = heightModeDataLegpElm // this._elms.heightConfirm = heightConfirmElm // this._elms.heightModeObject = heightModeObject // heightConfirmElm.addEventListener('click', () => { // this.positionEditing = false // for (let i = 0; i < this.options.positions.length; i++) { // this.options.positions[i].alt = Number((this.options.positions[i].alt + Number(heightElm.value)).toFixed(2)) // this._elms.alt[i].innerHTML = this.options.positions[i].alt // } // let fromDegreesArray = this.renewPositions(this.options.positions) // this.entity.polyline.positions = Cesium.Cartesian3.fromDegreesArrayHeights( // fromDegreesArray // ) // this.positionEditing = false // PolylineObject.closeNodeEdit(this) // }) // } let all_elm = contentElm.getElementsByTagName("*") this._EventBinding.on(this, all_elm) this._elms = this._EventBinding.element } else { // if (this._element_style) { // document.getElementsByTagName('head')[0].removeChild(this._element_style) // this._element_style = null // } // if (this._DialogObject && this._DialogObject.remove) { // this._DialogObject.remove() // this._DialogObject = null // } } } reset() { if (!this.viewer.entities.getById(this.options.id)) { return } this.name = this.originalOptions.name this.carRoadWidth = this.originalOptions.carRoadWidth this.sideWidth = this.originalOptions.sideWidth this.positions = this.originalOptions.positions this.roadImage = this.originalOptions.roadImage this.sideImage = this.originalOptions.sideImage } /** * 飞到对应实体 */ async flyTo(options = {}) { setActiveViewer(0) closeRotateAround(this.sdk) closeViewFollow(this.sdk) if (this.options.customView && this.options.customView.relativePosition && this.options.customView.orientation) { let orientation = { heading: Cesium.Math.toRadians(this.options.customView.orientation.heading || 0.0), pitch: Cesium.Math.toRadians(this.options.customView.orientation.pitch || -60.0), roll: Cesium.Math.toRadians(this.options.customView.orientation.roll || 0.0) } let lng = this.options.customView.relativePosition.lng let lat = this.options.customView.relativePosition.lat let alt = this.options.customView.relativePosition.alt let destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt) let position = { lng: 0, lat: 0 } if (this.options.position) { position = { ...this.options.position } } else if (this.options.positions) { position = { ...this.options.positions[0] } } else if (this.options.center) { position = { ...this.options.center } } else if (this.options.start) { position = { ...this.options.start } } else { if (this.options.hasOwnProperty('lng')) { position.lng = this.options.lng } if (this.options.hasOwnProperty('lat')) { position.lat = this.options.lat } if (this.options.hasOwnProperty('alt')) { position.alt = this.options.alt } } // 如果没有高度值,则获取紧贴高度计算 // if (!position.hasOwnProperty('alt')) { // position.alt = await this.getClampToHeight(position) // } lng = this.options.customView.relativePosition.lng + position.lng lat = this.options.customView.relativePosition.lat + position.lat alt = this.options.customView.relativePosition.alt + position.alt destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt) this.sdk.viewer.camera.flyTo({ destination: destination, orientation: orientation }) } else { let positionArray = [] for (let i = 0; i < this.positions.length; i++) { let a = Cesium.Cartesian3.fromDegrees( this.positions[i][0], this.positions[i][1], this.options.height + this.options.heightDifference / 2 ) positionArray.push(a.x, a.y, a.z) } let BoundingSphere = Cesium.BoundingSphere.fromVertices(positionArray) this.viewer.camera.flyToBoundingSphere(BoundingSphere, { offset: { heading: Cesium.Math.toRadians(0.0), pitch: Cesium.Math.toRadians(-20.0), roll: Cesium.Math.toRadians(0.0) } }) } } getSphere() { return new Promise((resolve) => { // entity没有加载完成时 state 不会等于0 所以设置定时器直到获取到为止 const interval = setInterval(() => { const sphere = new Cesium.BoundingSphere() const state = this.sdk.viewer._dataSourceDisplay.getBoundingSphere( this.viewer.entities.getById(this.options.id), false, sphere ) if (state === Cesium.BoundingSphereState.DONE) { clearInterval(interval) } }, 1000) }) } /** * 删除 */ async remove() { this.positions = [] this.lineEntity = null if (this.viewer.entities.getById(this.options.id)) { this.viewer.entities.getById(this.options.id)._children.forEach((item) => { this.viewer.entities.remove(item); }); this.viewer.entities.remove(this.viewer.entities.getById(this.options.id)) } if (this._DialogObject && !this._DialogObject.isDestroy) { this._DialogObject.close() this._DialogObject = null } await this.sdk.removeIncetance(this.options.id) await syncData(this.sdk, this.options.id) } flicker() { } } export default Road