diff --git a/src/In/index.js b/src/In/index.js index ebfff60..40f7487 100644 --- a/src/In/index.js +++ b/src/In/index.js @@ -186,7 +186,7 @@ import Frustum from '../Obj/AirLine/frustum' import DrawTakeOff from '../Obj/AirLine/DrawTakeOff' import FlowLine from '../Obj/Base/FlowLine' import Sunshine from '../Global/efflect/Sunshine' -// import Road2 from '../Obj/Base/RoadObject' +import Road2 from '../Obj/Base/RoadObject' import TextBox from '../Obj/Base/TextBox' import BatchModel from '../Obj/Base/BatchModel' @@ -261,7 +261,7 @@ if (!window.YJ) { // GenerateRoute Dialog, FlowLine, - // Road2, + Road2, TextBox, BatchModel }, diff --git a/src/Obj/Base/BatchModel/_element_拓展.js b/src/Obj/Base/BatchModel/_element_拓展.js new file mode 100644 index 0000000..e64eaa5 --- /dev/null +++ b/src/Obj/Base/BatchModel/_element_拓展.js @@ -0,0 +1,229 @@ +import { attributeElm } from '../../Element/elm_html' + +function html(that) { + return ` + +
+
+
+ 颜色 +
+
+
+
+
+
+ +
+
+
+
+
添加方式 +
+
+
+
+
+
+
+ 朝向偏移 +
+ + ° + +
+
+
+
+
+

模型间隔

+
+
+
+ + 自定义距离 +
+
+
+
+ + 固定距离 +
+
+
+ 模型间隔 +
+ + + +
+
+
+

线型选择

+
+
+
+ + 折线 +
+
+
+
+ + 曲线 +
+
+
+ 线条数量 +
+ + + +
+
+
+ 线条间隔 +
+ + + +
+
+
+
+
+
+ + 随机采样 +
+
+
+ 随机数量 +
+ + + +
+
+
+
+
+
+
+ + 网格采样 +
+
+
+ 首边间隔 +
+ + + +
+
+
+ 次边间隔 +
+ + + +
+
+
+
+ +
+ + +
+
+ 高度模式 +
+
+
+
+
+
+
缩放 +
+ + 是否等比例缩放 +
+
+
+
+
+
+ +
+
+
+ 新增模型风格设置 + +
+
+ +
+
+ +
+
+ 显隐 + +
+
+ 图标 +
+ +
+
+
+ 默认图标 +
+ +
+
+
+ 图标倍数 +
+ + + +
+
+
+
+
+

文字设置

+
+
+ 显隐 + +
+
+ 字体选择 +
+
+
+ 文字大小 +
+ + px + +
+
+
+ 文字颜色 +
+
+
+
+
+
+
+ + ` +} + +export { html } diff --git a/src/Obj/Base/Road/index.js b/src/Obj/Base/Road/index.js index bb43225..2e946f1 100644 --- a/src/Obj/Base/Road/index.js +++ b/src/Obj/Base/Road/index.js @@ -5,7 +5,7 @@ class Corridor extends Base { // /** // * @constructor // * @description 道路 - // * @param sdk + // * @param sdk // * @param options {object} 属性 // * @param options.name{string} 名称 // * @param options.image{string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} 指定 Image、URL、Canvas 或 Video 的属性 @@ -67,7 +67,7 @@ class Corridor extends Base { // material: new Cesium.ImageMaterialProperty({ // image: this.options.image, // repeat: new Cesium.Cartesian2(100, 1.0), - // color: Cesium.Color.TOMATO + // color: Cesium.Color.TOMATO // }) // } // }); @@ -217,10 +217,10 @@ class Corridor extends Base { let aa = 0 const shader = ` - uniform sampler2D image; + uniform sampler2D image; uniform vec4 color; uniform vec2 repeat; - + czm_material czm_getMaterial(czm_materialInput materialInput){ czm_material material=czm_getDefaultMaterial(materialInput); mat2 rotationMatrix = mat2(cos(radians(-rotate)), sin(radians(-rotate)), -sin(radians(-rotate)), cos(radians(-rotate))); diff --git a/src/Obj/Base/RoadObject/_element.js b/src/Obj/Base/RoadObject/_element.js new file mode 100644 index 0000000..49b49dc --- /dev/null +++ b/src/Obj/Base/RoadObject/_element.js @@ -0,0 +1,39 @@ +function html() { + return ` + +
+
+
+ 名称 + +
+
+ 道路类型 +
+
+
+
+ +
+
+
+ 车道宽度 +
+ + +
+
+
+ 人行道宽度 +
+ + +
+
+
+
+ + ` +} + +export { html } diff --git a/src/Obj/Base/RoadObject/eventBinding.js b/src/Obj/Base/RoadObject/eventBinding.js new file mode 100644 index 0000000..ccbf026 --- /dev/null +++ b/src/Obj/Base/RoadObject/eventBinding.js @@ -0,0 +1,92 @@ +class eventBinding { + constructor() { + this.element = {} + } + static event = {} + + getEvent(name) { + return eventBinding.event[name] + } + + getEventAll() { + return eventBinding.event + } + + setEvent(name, event) { + eventBinding.event[name] = event + } + + on(that, elements) { + for (let i = 0; i < elements.length; i++) { + let Event = [] + let isEvent = false + let removeName = [] + if (!elements[i] || !elements[i].attributes) { + continue; + } + for (let m of elements[i].attributes) { + switch (m.name) { + case '@model': { + isEvent = true + if (elements[i].type == 'checkbox') { + Event.push((e) => { that[m.value] = e.target.checked }) + elements[i].checked = that[m.value] + } + else { + Event.push((e) => { + let value = e.target.value + if (e.target.type == 'number') { + value = Number(value) + } + that[m.value] = value + }) + if (elements[i].nodeName == 'IMG') { + elements[i].src = that[m.value] + } + else { + elements[i].value = that[m.value] + } + } + if (this.element[m.value]) { + this.element[m.value].push(elements[i]) + } + else { + this.element[m.value] = [elements[i]] + } + removeName.push(m.name) + break; + } + case '@click': { + elements[i].addEventListener('click', (e) => { + if (typeof (that.Dialog[m.value]) === 'function') { + that.Dialog[m.value](e) + } + }); + removeName.push(m.name) + // elements[i].attributes.removeNamedItem(m.name) + break; + } + } + // elements[i].attributes[m] = undefined + } + for (let n = 0; n < removeName.length; n++) { + elements[i].attributes.removeNamedItem(removeName[n]) + } + + if (isEvent) { + let ventType = 'input' + if (elements[i].tagName != 'INPUT' || elements[i].type == 'checkbox') { + ventType = 'change' + } + elements[i].addEventListener(ventType, (e) => { + for (let t = 0; t < Event.length; t++) { + Event[t](e) + } + }); + } + } + } +} + +const EventBinding = new eventBinding(); +export default EventBinding; \ No newline at end of file diff --git a/src/Obj/Base/RoadObject/index-8.4.js b/src/Obj/Base/RoadObject/index-8.4.js new file mode 100644 index 0000000..48f1d50 --- /dev/null +++ b/src/Obj/Base/RoadObject/index-8.4.js @@ -0,0 +1,1549 @@ +/** + * @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.positionChangeIndex = [] + + 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]) + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: [leftItem[2], leftItem[3]], + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: Cesium.Color.YELLOW, + // }), + // }, + // }); + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: [leftItem2[2], leftItem2[3]], + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: Cesium.Color.YELLOW, + // }), + // }, + // }); + + let rightLine = that.getIntersects(rightItem[0], rightItem[1], rightItem2[0], rightItem2[1]) + // if (!leftLine && !rightLine) { + // for (let index = 0; index < 4; index++) { + // let positions = [] + // index === 0 ? positions.push(leftItem[2], leftItem[3]) : index === 1 ? positions.push(leftItem2[2], leftItem2[3]) : index === 2 ? positions.push(rightItem[0], rightItem[1]) : positions.push(rightItem2[0], rightItem2[1]) + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: positions, + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: index === 0 ? Cesium.Color.RED : index === 1 ? Cesium.Color.BLUE : index === 2 ? Cesium.Color.YELLOW : Cesium.Color.GREEN, + // }), + // }, + // }); + + // } + // } + + + + for (let index = 0; index < 4; index++) { + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: index, + // position: area[0][i][index], + // 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 }, + // }, + // }) + + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: index, + // position: area[2][i][index], + // 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 }, + // }, + // }) + } + + + if (leftLine) {//左侧相交 + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: 1, + // position: leftLine, + // billboard: { + // image: that.getSourceRootPath() + '/img/locate2.png', + // width: 15, + // height: 15, + // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // color: Cesium.Color.WHITE.withAlpha(0.99) + // }, + // label: { + // text: '', + // pixelOffset: { x: 0, y: -20 }, + // }, + // }) + + //获取右侧延长交点 + let point1 = that.getExtendPoint(rightItem[0], rightItem[1], 1000) + let point2 = that.getExtendPoint(rightItem2[1], rightItem2[0], 1000) + + that.sdk.viewer.entities.add({ + polyline: { + positions: [rightItem[0], point1], + width: 2.0, + clampToGround: true, + material: new Cesium.PolylineGlowMaterialProperty({ + color: Cesium.Color.AQUA, + }), + }, + }); + that.sdk.viewer.entities.add({ + polyline: { + positions: [rightItem2[1], point2], + width: 2.0, + clampToGround: true, + material: new Cesium.PolylineGlowMaterialProperty({ + color: Cesium.Color.AQUA, + }), + }, + }); + + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: i, + position: point1, + billboard: { + image: that.getSourceRootPath() + '/img/point.png', + width: 15, + height: 15, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + color: Cesium.Color.WHITE.withAlpha(0.99) + }, + label: { + text: '' + 7 + "", + pixelOffset: { x: 0, y: -20 }, + }, + }) + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: i, + position: point2, + billboard: { + image: that.getSourceRootPath() + '/img/end.png', + width: 15, + height: 15, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + color: Cesium.Color.WHITE.withAlpha(0.99) + }, + label: { + text: '' + 7 + "", + pixelOffset: { x: 0, y: -20 }, + }, + }) + + + let rightIntersection = that.getIntersects(rightItem[0], point1, rightItem2[1], 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(leftLine, rightIntersection, leftItem[0], leftLineNeiPoint) + //跟车道左侧相交点 + 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) + // 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[2] = leftLineNei + // carItem[1] = carRight + carItem[1] = rightLineNei + rightItem[2] = rightLineNei + rightItem[1] = rightIntersection + + + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: 1, + // position: leftLineNei, + // billboard: { + // image: that.getSourceRootPath() + '/img/locate2.png', + // width: 15, + // height: 15, + // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // color: Cesium.Color.WHITE.withAlpha(0.99) + // }, + // label: { + // text: '', + // pixelOffset: { x: 0, y: -20 }, + // }, + // }) + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: 1, + position: rightIntersection, + billboard: { + image: that.getSourceRootPath() + '/img/locate2.png', + width: 15, + height: 15, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + color: Cesium.Color.WHITE.withAlpha(0.99) + }, + label: { + text: '', + pixelOffset: { x: 0, y: -20 }, + }, + }) + + + + //将其他几条边都延长 + 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[3] = leftLineNei + // carItem2[0] = carRight + carItem2[0] = rightLineNei + rightItem2[3] = rightLineNei + rightItem2[0] = rightIntersection + + + } else if (rightLine) {//右侧相交 + + //获取左侧延长交点 + let point1 = that.getExtendPoint(leftItem[3], leftItem[2], 1000) + let point2 = that.getExtendPoint(leftItem2[2], leftItem2[3], 1000) + + that.sdk.viewer.entities.add({ + polyline: { + positions: [leftItem[3], point1], + width: 2.0, + clampToGround: true, + material: new Cesium.PolylineGlowMaterialProperty({ + color: Cesium.Color.AQUA, + }), + }, + }); + that.sdk.viewer.entities.add({ + polyline: { + positions: [leftItem2[2], point2], + width: 2.0, + clampToGround: true, + material: new Cesium.PolylineGlowMaterialProperty({ + color: Cesium.Color.AQUA, + }), + }, + }); + + 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[2] = leftLineNei + // carItem[1] = carRight + carItem[1] = rightLineNei + rightItem[2] = rightLineNei + rightItem[1] = rightLine + + //将其他几条边都延长 + 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[3] = leftLineNei + // carItem2[0] = carRight + carItem2[0] = rightLineNei + rightItem2[3] = rightLineNei + rightItem2[0] = rightLine + + // leftItem[2] = rightIntersection + // leftItem[1] = leftLineNei + // // carItem[2] = carLeft + // carItem[2] = leftLineNei + // // carItem[1] = carRight + // carItem[1] = rightLineNei + // rightItem[2] = rightLineNei + // rightItem[1] = rightLine + } + + // area[0][i] = leftItem + // area[0][i + 1] = leftItem2 + // area[2][i] = rightItem + // area[2][i + 1] = rightItem2 + // area[1][0][i] = carItem + // area[1][0][i + 1] = carItem2 + } + 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 () { + area[1][0].forEach((item, index) => { + that.viewer.entities.add({ + // id: that.options.id, + parent: that.lineEntity, + polygon: { + hierarchy: new Cesium.PolygonHierarchy(item), + heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, + classificationType: Cesium.ClassificationType.BOTH, + distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000), + material: new Cesium.ImageMaterialProperty({ + image: that.options.roadImage, + transparent: true,// 如果图片有透明部分,需要设置为 true + repeat: that.calculateTextureRepeat(item, myImg) + }), + // stRotation: that.calculateRoadAngle(positions[index], positions[index + 1]) + stRotation: that.calculateRoadAngle(item[0], item[1]) + // material: Cesium.Color.fromRandom({ alpha: 0.5 }), + } + }); + }) + } + + const myImg2 = new Image() + myImg2.src = that.options.sideImage + myImg2.onload = function () { + 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]) + // material: Cesium.Color.fromRandom({ alpha: 0.5 }), + } + }); + }) + + area[2].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]) + // material: Cesium.Color.fromRandom({ alpha: 0.5 }), + } + }); + }) + } + + } + getSideRectangle(positions, width) { + let right = [] + let left = [] + let that = this + positions.forEach((item, i) => { + // console.log(that.positionChangeIndex, 'positionChangeIndex') + // if (that.positionChangeIndex[i + '']) { + // console.log('1111') + // right.push([item[2], item[3]]) + // left.push([item[0], item[1]]) + // } else { + right.push([item[0], item[1]]) + // left.push([item[2], item[3]]) + left.push([item[3], item[2]]) + // } + + + for (let index = 0; index < 2; index++) { + let ArrArr = [] + index === 0 ? ArrArr.push(item[0], item[1]) : ArrArr.push(item[2], item[3]); + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: ArrArr, + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: index === 0 ? Cesium.Color.RED : Cesium.Color.BLUE, + // }), + // }, + // }); + } + }) + let rightPosi = that.getRectangle(right, width, 'side') + let newRightPosi = [] + right.forEach((item, index) => { + newRightPosi.push([rightPosi[index][0], rightPosi[index][1], item[1], item[0]]) + }) + + + let leftPosi = this.getRectangle(left, width, 'side') + let newLeftPosi = [] + left.forEach((item, index) => { + // newLeftPosi.push([item[0], item[1], leftPosi[index][2]], leftPosi[index][3]) + newLeftPosi.push([item[0], item[1], leftPosi[index][2], leftPosi[index][3]]) + }) + return { left: newLeftPosi, right: newRightPosi } + } + 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)) {//调整方向 + // let newArr = [] + // newArr[0] = arr[2] + // newArr[1] = arr[3] + // newArr[2] = arr[0] + // newArr[3] = arr[1] + // newPositions.push(newArr) + //判断方向是否正确 + const vec1 = Cesium.Cartesian3.normalize( + Cesium.Cartesian3.subtract(start, arr[0], new Cesium.Cartesian3()), + new Cesium.Cartesian3() + ); + + // 计算并归一化第二个向量 + const vec2 = Cesium.Cartesian3.normalize( + Cesium.Cartesian3.subtract(arr[1], arr[0], new Cesium.Cartesian3()), + new Cesium.Cartesian3() + ); + + let dRst = Cesium.Cartesian3.dot(vec1, vec2); + + + if (0 < dRst && dRst < 0.0001) { + newPositions.push(arr) + } else { + + let dis1 = that.distancePointToLine(start, arr[0], arr[1]) + let dis2 = that.distancePointToLine(start, arr[2], arr[3]) + let newArr = [] + if (dis1 > dis2) {// + newArr[0] = arr[3] + newArr[1] = arr[0] + newArr[2] = arr[1] + newArr[3] = arr[2] + } else { + newArr[0] = arr[2] + newArr[1] = arr[3] + newArr[2] = arr[0] + newArr[3] = arr[1] + } + newPositions.push(newArr) + + + // let newArr = [] + // newArr[0] = arr[2] + // newArr[1] = arr[3] + // newArr[2] = arr[0] + // newArr[3] = arr[1] + // newPositions.push(newArr) + } + + // newPositions.push(arr) + + if (!type) { + for (let index = 0; index < 4; index++) { + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: index, + position: arr[index], + billboard: { + image: this.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 }, + }, + }) + + } + + } + } else { + let dis1 = that.distancePointToLine(that.pointArr[i][0], arr[0], arr[1]) + let dis2 = that.distancePointToLine(that.pointArr[i][0], arr[2], arr[3]) + let newArr = [] + if (dis1 > dis2) { + newArr[0] = arr[3] + newArr[1] = arr[0] + newArr[2] = arr[1] + newArr[3] = arr[2] + } else { + newArr[0] = arr[1] + newArr[1] = arr[2] + newArr[2] = arr[3] + newArr[3] = arr[0] + } + newPositions.push(newArr) + + if (!type) { + for (let index = 0; index < 4; index++) { + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: index, + // position: newArr[index], + position: newArr[index], + billboard: { + image: this.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 }, + }, + }) + } + } + // !type && that.positionChangeIndex.push(i + "") + } + // } + + // 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 + } + distancePointToLine(p, a, b) { + let ab = new Cesium.Cartesian3(); + Cesium.Cartesian3.subtract(b, a, ab); + + let ap = new Cesium.Cartesian3(); + Cesium.Cartesian3.subtract(p, a, ap); + + let abNormalized = new Cesium.Cartesian3(); + Cesium.Cartesian3.normalize(ab, abNormalized); + + let apProjectionMagnitude = Cesium.Cartesian3.dot(ap, abNormalized); + let apProjection = Cesium.Cartesian3.multiplyByScalar(abNormalized, apProjectionMagnitude, new Cesium.Cartesian3()); + + let footPoint = new Cesium.Cartesian3(); + Cesium.Cartesian3.add(a, apProjection, footPoint); + + return Cesium.Cartesian3.distance(p, footPoint); + } + getExtendPoint2(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 + } + getExtendPoint3(pos1, pos2, distance) { + const geodesic = new Cesium.EllipsoidGeodesic(); + geodesic.setEndPoints(pos1, pos2); + + // 关键步骤:获取实际测地距离 + const actualDist = geodesic.surfaceDistance; + const ratio = Math.max(1.1, distance / actualDist); // 强制外延比例 + + // 基于地理坐标的弧度插值 + const carto1 = Cesium.Cartographic.fromCartesian(pos1); + const carto2 = Cesium.Cartographic.fromCartesian(pos2); + + const resultCarto = new Cesium.Cartographic( + carto1.longitude + (carto2.longitude - carto1.longitude) * ratio, + carto1.latitude + (carto2.latitude - carto1.latitude) * ratio, + 0 + ); + + return Cesium.Cartesian3.fromRadians( + resultCarto.longitude, + resultCarto.latitude + ); + } + getExtendPoint(position1, position2, distance) { + // 1. 向量计算与归一化 + const direction = Cesium.Cartesian3.subtract( + position2, + position1, + new Cesium.Cartesian3() + ); + Cesium.Cartesian3.normalize(direction, direction); + + // 2. 使用Ellipsoid修正地球曲率影响 + const ellipsoid = Cesium.Ellipsoid.WGS84; + const geodesic = new Cesium.EllipsoidGeodesic(); + geodesic.setEndPoints(position1, position2); + const actualDistance = geodesic.surfaceDistance; // 获取实际测地距离 + if (distance <= actualDistance) distance = actualDistance * 100; // 强制向外延伸 + + // 3. 考虑椭球面曲率的精确延长 + const surfaceNormal = ellipsoid.geodeticSurfaceNormal(position1); + const projection = Cesium.Cartesian3.multiplyByScalar( + surfaceNormal, + Cesium.Cartesian3.dot(direction, surfaceNormal), + new Cesium.Cartesian3() + ); + Cesium.Cartesian3.subtract(direction, projection, direction); + Cesium.Cartesian3.normalize(direction, direction); + + // 4. 最终坐标计算 + return Cesium.Cartesian3.add( + position2, + Cesium.Cartesian3.multiplyByScalar(direction, distance, new Cesium.Cartesian3()), + new Cesium.Cartesian3() + ); + } + 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) + return result; + } + calculateRoadAngle3(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; + } + calculateRoadAngle(startPoint, endPoint) { + // 1. 获取精确地形法向量(需配合地形服务使用) + const normal = Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(startPoint); + + // 2. 构建ENU坐标系(增加异常处理) + if (!Cesium.defined(startPoint) || !Cesium.defined(endPoint)) { + return 0; + } + + 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()); + + // 4. 使用三维向量计算角度(保留高程信息) + const north3D = new Cesium.Cartesian3(1, 0, 0); + const direction3D = new Cesium.Cartesian3( + localEnd.x, localEnd.y, localEnd.z); + Cesium.Cartesian3.normalize(direction3D, direction3D); + + // 5. 计算带符号角度(考虑三维空间关系) + const angle = Cesium.Cartesian3.angleBetween( + north3D, direction3D); + const cross = Cesium.Cartesian3.cross( + north3D, direction3D, new Cesium.Cartesian3()); + + // 6. 返回带符号角度(Z轴分量为负则取反) + return cross.z < 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'); + } + + let widthDis = Cesium.Cartesian3.distance(polygonPositions[0], polygonPositions[1]) + let heightDis = Cesium.Cartesian3.distance(polygonPositions[0], polygonPositions[3]) + + // 计算纹理实际尺寸(米) + // const textureWidthMeters = textureSize.width * meterPerPixel; + // const textureHeightMeters = textureSize.height * meterPerPixel; + const textureWidthMeters = textureSize.width; + const textureHeightMeters = textureSize.height; + console.log(textureWidthMeters, textureHeightMeters, widthDis, heightDis, '宽度') + + // 保持宽高比计算重复次数 + const repeatX = widthDis / textureWidthMeters; + const repeatY = heightDis / textureHeightMeters; + const aspectRatio = textureWidthMeters / textureHeightMeters; + console.log(aspectRatio, 'aspectRatio') + + // 选择主导轴并保持比例 + const dominantRepeat = Math.max(repeatX, repeatY); + let x = Math.max(1, Math.ceil(widthDis / (aspectRatio * heightDis))) + console.log(x, '10') + return new Cesium.Cartesian2( + x, + 1 + ); + } + calculateTextureRepeat2(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]]) + // } + let that = this + // return [arr, rightPositions, leftPositions] + return [area, rightPositions, leftPositions] + } + getIntersects2(segment1Start, segment1End, segment2Start, segment2End) { + // 构造平面(使用线段2的起点和方向向量) + let direction = Cesium.Cartesian3.subtract(segment2End, segment2Start, new Cesium.Cartesian3()); + let plane = Cesium.Plane.fromPointNormal(segment2Start, direction); + + // 计算线段1与平面的交点(增加容差参数) + let intersection = Cesium.IntersectionTests.lineSegmentPlane( + segment1Start, segment1End, plane, 1e-10 + ); + if (!intersection) return null; + + // 使用参数方程验证交点有效性 + let vecToIntersect = Cesium.Cartesian3.subtract(intersection, segment2Start, new Cesium.Cartesian3()); + let t = Cesium.Cartesian3.dot(vecToIntersect, direction) / + Cesium.Cartesian3.magnitudeSquared(direction); + + let result = (t >= -1e-10 && t <= 1.0 + 1e-10) ? intersection : null; + return result; + } + 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 diff --git a/src/Obj/Base/RoadObject/index-last.js b/src/Obj/Base/RoadObject/index-last.js new file mode 100644 index 0000000..e6a958e --- /dev/null +++ b/src/Obj/Base/RoadObject/index-last.js @@ -0,0 +1,1704 @@ +/** + * @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.positionChangeIndex = [] + + this.sdk.addIncetance(this.options.id, this) + // Road.create(this) + const myImg = new Image() + myImg.src = this.options.roadImage + myImg.onload = () => { + console.log('加载完成') + this.createCorridor(myImg, this.options.positions) + } + } + + // 创建走廊几何体 + createCorridor(myImg, posis) { + let posiArr = [] + posis.forEach(item => { + posiArr.push(item.lng, item.lat) + }) + console.log(posiArr, 'posiArr') + + const positions = Cesium.Cartesian3.fromDegreesArray(posiArr); + + const corridorInstance = new Cesium.GeometryInstance({ + geometry: new Cesium.CorridorGeometry({ + positions: positions, + width: this.options.carRoadWidth, + vertexFormat: Cesium.VertexFormat.POSITION_AND_ST, + cornerType: Cesium.CornerType.MITERED, + extrudedHeight: 10.0 + }), + attributes: { + color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE) + } + }); + + const primitive = new Cesium.Primitive({ + geometryInstances: corridorInstance, + appearance: new Cesium.MaterialAppearance({ + material: new Cesium.Material({ + fabric: { + type: 'Image', + uniforms: { + image: myImg + } + } + }), + translucent: false + }), + asynchronous: false + }); + + this.sdk.viewer.scene.primitives.add(primitive); + + // 定位到走廊 + // this.sdk.viewer.camera.flyTo({ + // destination: Cesium.Cartesian3.fromDegrees(103.70271877620554, 41.95279346036913, 100), + // // orientation: { + // // heading: Cesium.Math.toRadians(0), + // // pitch: Cesium.Math.toRadians(-30), + // // roll: 0.0 + // // } + // }); + + return primitive; + } + // 横断面计算函数 + computeCrossSection(width, slope) { + const halfWidth = width / 2; + return [ + new Cesium.Cartesian2(-halfWidth, 0), + new Cesium.Cartesian2(-halfWidth, -slope * 10), + new Cesium.Cartesian2(halfWidth, -slope * 10), + new Cesium.Cartesian2(halfWidth, 0) + ]; + } + computeST(geometry) { + // 安全校验:确保几何体包含位置属性 + if (!geometry.attributes.position) { + throw new Error('Geometry must contain position attribute'); + } + + const positions = geometry.attributes.position.values; + const vertexCount = positions.length / 3; + const st = new Float32Array(vertexCount * 2); + + // 计算UV坐标(改进版) + for (let i = 0; i < vertexCount; i++) { + const vertexIndex = i * 3; + const uvIndex = i * 2; + + // 根据顶点在横截面中的位置计算V坐标 + const isTopVertex = positions[vertexIndex + 2] > 0; // Z坐标判断顶面/底面 + st[uvIndex + 1] = isTopVertex ? 1 : 0; + + // 根据路径比例计算U坐标(自动适应不同路段长度) + const pathProgress = i % 4; // 每4个顶点为一个横截面 + st[uvIndex] = (Math.floor(i / 4) + pathProgress / 4) / (vertexCount / 4) * 10; + } + return st; + } + // 创建道路 + 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 + // 1. 定义道路中心线路径(WGS84坐标) + const roadPath = [start, end]; + // 3. 计算纹理坐标(确保贴图沿道路方向连续) + console.log(roadPath, 'roadPath') + // 4. 创建道路几何体 + const roadGeometry = new Cesium.PolylineVolumeGeometry({ + polylinePositions: roadPath, + shapePositions: that.computeCrossSection(20, 0.5), + vertexFormat: Cesium.VertexFormat.POSITION_AND_ST, + cornerType: Cesium.CornerType.ROUNDED + }); + console.log('kkkkk') + + // 5. 使用Primitive渲染带贴图的道路 + const roadPrimitive = that.viewer.scene.primitives.add( + new Cesium.Primitive({ + geometryInstances: new Cesium.GeometryInstance({ + geometry: roadGeometry, + attributes: { + st: new Cesium.GeometryAttribute({ + componentDatatype: Cesium.ComponentDatatype.FLOAT, + componentsPerAttribute: 2, + values: (function () { + if (!roadGeometry.attributes.position) { + console.error('Road geometry lacks position data'); + return new Float32Array(0); + } + return that.computeST(roadGeometry); + })() + }) + } + }), + appearance: new Cesium.MaterialAppearance({ + material: new Cesium.Material({ + fabric: { + type: 'Image', + uniforms: { + image: that.options.roadImage, // 沥青纹理示例 + repeat: new Cesium.Cartesian2(1, 1) + } + }, + translucent: false + }), + faceForward: false // 确保双面渲染 + }) + }) + ); + + } + + 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]) + // // that.sdk.viewer.entities.add({ + // // polyline: { + // // positions: [leftItem[2], leftItem[3]], + // // width: 2.0, + // // clampToGround: true, + // // material: new Cesium.PolylineGlowMaterialProperty({ + // // color: Cesium.Color.YELLOW, + // // }), + // // }, + // // }); + // // that.sdk.viewer.entities.add({ + // // polyline: { + // // positions: [leftItem2[2], leftItem2[3]], + // // width: 2.0, + // // clampToGround: true, + // // material: new Cesium.PolylineGlowMaterialProperty({ + // // color: Cesium.Color.YELLOW, + // // }), + // // }, + // // }); + + // let rightLine = that.getIntersects(rightItem[0], rightItem[1], rightItem2[0], rightItem2[1]) + // // if (!leftLine && !rightLine) { + // // for (let index = 0; index < 4; index++) { + // // let positions = [] + // // index === 0 ? positions.push(leftItem[2], leftItem[3]) : index === 1 ? positions.push(leftItem2[2], leftItem2[3]) : index === 2 ? positions.push(rightItem[0], rightItem[1]) : positions.push(rightItem2[0], rightItem2[1]) + // // that.sdk.viewer.entities.add({ + // // polyline: { + // // positions: positions, + // // width: 2.0, + // // clampToGround: true, + // // material: new Cesium.PolylineGlowMaterialProperty({ + // // color: index === 0 ? Cesium.Color.RED : index === 1 ? Cesium.Color.BLUE : index === 2 ? Cesium.Color.YELLOW : Cesium.Color.GREEN, + // // }), + // // }, + // // }); + + // // } + // // } + + + + // for (let index = 0; index < 4; index++) { + // // that.sdk.viewer.entities.add({ + // // name: 'node-secondary-edit-point', + // // index: index, + // // position: area[0][i][index], + // // 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 }, + // // }, + // // }) + + // // that.sdk.viewer.entities.add({ + // // name: 'node-secondary-edit-point', + // // index: index, + // // position: area[2][i][index], + // // 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 }, + // // }, + // // }) + // } + + + // if (leftLine) {//左侧相交 + // // that.sdk.viewer.entities.add({ + // // name: 'node-secondary-edit-point', + // // index: 1, + // // position: leftLine, + // // billboard: { + // // image: that.getSourceRootPath() + '/img/locate2.png', + // // width: 15, + // // height: 15, + // // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // // color: Cesium.Color.WHITE.withAlpha(0.99) + // // }, + // // label: { + // // text: '', + // // pixelOffset: { x: 0, y: -20 }, + // // }, + // // }) + + // //获取右侧延长交点 + // let point1 = that.getExtendPoint(rightItem[0], rightItem[1], 1000) + // let point2 = that.getExtendPoint(rightItem2[1], rightItem2[0], 1000) + + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: [rightItem[0], point1], + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: Cesium.Color.AQUA, + // }), + // }, + // }); + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: [rightItem2[1], point2], + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: Cesium.Color.AQUA, + // }), + // }, + // }); + + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: i, + // position: point1, + // billboard: { + // image: that.getSourceRootPath() + '/img/point.png', + // width: 15, + // height: 15, + // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // color: Cesium.Color.WHITE.withAlpha(0.99) + // }, + // label: { + // text: '' + 7 + "", + // pixelOffset: { x: 0, y: -20 }, + // }, + // }) + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: i, + // position: point2, + // billboard: { + // image: that.getSourceRootPath() + '/img/end.png', + // width: 15, + // height: 15, + // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // color: Cesium.Color.WHITE.withAlpha(0.99) + // }, + // label: { + // text: '' + 7 + "", + // pixelOffset: { x: 0, y: -20 }, + // }, + // }) + + + // let rightIntersection = that.getIntersects(rightItem[0], point1, rightItem2[1], 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(leftLine, rightIntersection, leftItem[0], leftLineNeiPoint) + // //跟车道左侧相交点 + // 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) + // // 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[2] = leftLineNei + // // carItem[1] = carRight + // carItem[1] = rightLineNei + // rightItem[2] = rightLineNei + // rightItem[1] = rightIntersection + + + // // that.sdk.viewer.entities.add({ + // // name: 'node-secondary-edit-point', + // // index: 1, + // // position: leftLineNei, + // // billboard: { + // // image: that.getSourceRootPath() + '/img/locate2.png', + // // width: 15, + // // height: 15, + // // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // // color: Cesium.Color.WHITE.withAlpha(0.99) + // // }, + // // label: { + // // text: '', + // // pixelOffset: { x: 0, y: -20 }, + // // }, + // // }) + // that.sdk.viewer.entities.add({ + // name: 'node-secondary-edit-point', + // index: 1, + // position: rightIntersection, + // billboard: { + // image: that.getSourceRootPath() + '/img/locate2.png', + // width: 15, + // height: 15, + // disableDepthTestDistance: Number.POSITIVE_INFINITY, + // color: Cesium.Color.WHITE.withAlpha(0.99) + // }, + // label: { + // text: '', + // pixelOffset: { x: 0, y: -20 }, + // }, + // }) + + + + // //将其他几条边都延长 + // 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[3] = leftLineNei + // // carItem2[0] = carRight + // carItem2[0] = rightLineNei + // rightItem2[3] = rightLineNei + // rightItem2[0] = rightIntersection + + + // } else if (rightLine) {//右侧相交 + + // //获取左侧延长交点 + // let point1 = that.getExtendPoint(leftItem[3], leftItem[2], 1000) + // let point2 = that.getExtendPoint(leftItem2[2], leftItem2[3], 1000) + + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: [leftItem[3], point1], + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: Cesium.Color.AQUA, + // }), + // }, + // }); + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: [leftItem2[2], point2], + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: Cesium.Color.AQUA, + // }), + // }, + // }); + + // 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[2] = leftLineNei + // // carItem[1] = carRight + // carItem[1] = rightLineNei + // rightItem[2] = rightLineNei + // rightItem[1] = rightLine + + // //将其他几条边都延长 + // 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[3] = leftLineNei + // // carItem2[0] = carRight + // carItem2[0] = rightLineNei + // rightItem2[3] = rightLineNei + // rightItem2[0] = rightLine + + // // leftItem[2] = rightIntersection + // // leftItem[1] = leftLineNei + // // // carItem[2] = carLeft + // // carItem[2] = leftLineNei + // // // carItem[1] = carRight + // // carItem[1] = rightLineNei + // // rightItem[2] = rightLineNei + // // rightItem[1] = rightLine + // } + + // // area[0][i] = leftItem + // // area[0][i + 1] = leftItem2 + // // area[2][i] = rightItem + // // area[2][i + 1] = rightItem2 + // // area[1][0][i] = carItem + // // area[1][0][i + 1] = carItem2 + // } + // 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 () { + // area[1][0].forEach((item, index) => { + + + + + // // that.viewer.entities.add({ + // // // id: that.options.id, + // // parent: that.lineEntity, + // // polygon: { + // // hierarchy: new Cesium.PolygonHierarchy(item), + // // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, + // // classificationType: Cesium.ClassificationType.BOTH, + // // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000), + // // material: new Cesium.ImageMaterialProperty({ + // // image: that.options.roadImage, + // // transparent: true,// 如果图片有透明部分,需要设置为 true + // // repeat: that.calculateTextureRepeat(item, myImg) + // // }), + // // // stRotation: that.calculateRoadAngle(positions[index], positions[index + 1]) + // // stRotation: that.calculateRoadAngle(item[0], item[1]) + // // // material: Cesium.Color.fromRandom({ alpha: 0.5 }), + // // } + // // }); + // }) + // } + + // const myImg2 = new Image() + // myImg2.src = that.options.sideImage + // myImg2.onload = function () { + // 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]) + // // material: Cesium.Color.fromRandom({ alpha: 0.5 }), + // } + // }); + // }) + + // area[2].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]) + // // material: Cesium.Color.fromRandom({ alpha: 0.5 }), + // } + // }); + // }) + // } + + } + getSideRectangle(positions, width) { + let right = [] + let left = [] + let that = this + positions.forEach((item, i) => { + // console.log(that.positionChangeIndex, 'positionChangeIndex') + // if (that.positionChangeIndex[i + '']) { + // console.log('1111') + // right.push([item[2], item[3]]) + // left.push([item[0], item[1]]) + // } else { + right.push([item[0], item[1]]) + // left.push([item[2], item[3]]) + left.push([item[3], item[2]]) + // } + + + for (let index = 0; index < 2; index++) { + let ArrArr = [] + index === 0 ? ArrArr.push(item[0], item[1]) : ArrArr.push(item[2], item[3]); + // that.sdk.viewer.entities.add({ + // polyline: { + // positions: ArrArr, + // width: 2.0, + // clampToGround: true, + // material: new Cesium.PolylineGlowMaterialProperty({ + // color: index === 0 ? Cesium.Color.RED : Cesium.Color.BLUE, + // }), + // }, + // }); + } + }) + let rightPosi = that.getRectangle(right, width, 'side') + let newRightPosi = [] + right.forEach((item, index) => { + newRightPosi.push([rightPosi[index][0], rightPosi[index][1], item[1], item[0]]) + }) + + + let leftPosi = this.getRectangle(left, width, 'side') + let newLeftPosi = [] + left.forEach((item, index) => { + // newLeftPosi.push([item[0], item[1], leftPosi[index][2]], leftPosi[index][3]) + newLeftPosi.push([item[0], item[1], leftPosi[index][2], leftPosi[index][3]]) + }) + return { left: newLeftPosi, right: newRightPosi } + } + 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)) {//调整方向 + // let newArr = [] + // newArr[0] = arr[2] + // newArr[1] = arr[3] + // newArr[2] = arr[0] + // newArr[3] = arr[1] + // newPositions.push(newArr) + //判断方向是否正确 + const vec1 = Cesium.Cartesian3.normalize( + Cesium.Cartesian3.subtract(start, arr[0], new Cesium.Cartesian3()), + new Cesium.Cartesian3() + ); + + // 计算并归一化第二个向量 + const vec2 = Cesium.Cartesian3.normalize( + Cesium.Cartesian3.subtract(arr[1], arr[0], new Cesium.Cartesian3()), + new Cesium.Cartesian3() + ); + + let dRst = Cesium.Cartesian3.dot(vec1, vec2); + + + if (0 < dRst && dRst < 0.0001) { + newPositions.push(arr) + } else { + + let dis1 = that.distancePointToLine(start, arr[0], arr[1]) + let dis2 = that.distancePointToLine(start, arr[2], arr[3]) + let newArr = [] + if (dis1 > dis2) {// + newArr[0] = arr[3] + newArr[1] = arr[0] + newArr[2] = arr[1] + newArr[3] = arr[2] + } else { + newArr[0] = arr[2] + newArr[1] = arr[3] + newArr[2] = arr[0] + newArr[3] = arr[1] + } + newPositions.push(newArr) + + + // let newArr = [] + // newArr[0] = arr[2] + // newArr[1] = arr[3] + // newArr[2] = arr[0] + // newArr[3] = arr[1] + // newPositions.push(newArr) + } + + // newPositions.push(arr) + + if (!type) { + for (let index = 0; index < 4; index++) { + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: index, + position: arr[index], + billboard: { + image: this.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 }, + }, + }) + + } + + } + } else { + let dis1 = that.distancePointToLine(that.pointArr[i][0], arr[0], arr[1]) + let dis2 = that.distancePointToLine(that.pointArr[i][0], arr[2], arr[3]) + let newArr = [] + if (dis1 > dis2) { + newArr[0] = arr[3] + newArr[1] = arr[0] + newArr[2] = arr[1] + newArr[3] = arr[2] + } else { + newArr[0] = arr[1] + newArr[1] = arr[2] + newArr[2] = arr[3] + newArr[3] = arr[0] + } + newPositions.push(newArr) + + if (!type) { + for (let index = 0; index < 4; index++) { + that.sdk.viewer.entities.add({ + name: 'node-secondary-edit-point', + index: index, + // position: newArr[index], + position: newArr[index], + billboard: { + image: this.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 }, + }, + }) + } + } + // !type && that.positionChangeIndex.push(i + "") + } + // } + + // 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 + } + distancePointToLine(p, a, b) { + let ab = new Cesium.Cartesian3(); + Cesium.Cartesian3.subtract(b, a, ab); + + let ap = new Cesium.Cartesian3(); + Cesium.Cartesian3.subtract(p, a, ap); + + let abNormalized = new Cesium.Cartesian3(); + Cesium.Cartesian3.normalize(ab, abNormalized); + + let apProjectionMagnitude = Cesium.Cartesian3.dot(ap, abNormalized); + let apProjection = Cesium.Cartesian3.multiplyByScalar(abNormalized, apProjectionMagnitude, new Cesium.Cartesian3()); + + let footPoint = new Cesium.Cartesian3(); + Cesium.Cartesian3.add(a, apProjection, footPoint); + + return Cesium.Cartesian3.distance(p, footPoint); + } + getExtendPoint2(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 + } + getExtendPoint3(pos1, pos2, distance) { + const geodesic = new Cesium.EllipsoidGeodesic(); + geodesic.setEndPoints(pos1, pos2); + + // 关键步骤:获取实际测地距离 + const actualDist = geodesic.surfaceDistance; + const ratio = Math.max(1.1, distance / actualDist); // 强制外延比例 + + // 基于地理坐标的弧度插值 + const carto1 = Cesium.Cartographic.fromCartesian(pos1); + const carto2 = Cesium.Cartographic.fromCartesian(pos2); + + const resultCarto = new Cesium.Cartographic( + carto1.longitude + (carto2.longitude - carto1.longitude) * ratio, + carto1.latitude + (carto2.latitude - carto1.latitude) * ratio, + 0 + ); + + return Cesium.Cartesian3.fromRadians( + resultCarto.longitude, + resultCarto.latitude + ); + } + getExtendPoint(position1, position2, distance) { + // 1. 向量计算与归一化 + const direction = Cesium.Cartesian3.subtract( + position2, + position1, + new Cesium.Cartesian3() + ); + Cesium.Cartesian3.normalize(direction, direction); + + // 2. 使用Ellipsoid修正地球曲率影响 + const ellipsoid = Cesium.Ellipsoid.WGS84; + const geodesic = new Cesium.EllipsoidGeodesic(); + geodesic.setEndPoints(position1, position2); + const actualDistance = geodesic.surfaceDistance; // 获取实际测地距离 + if (distance <= actualDistance) distance = actualDistance * 100; // 强制向外延伸 + + // 3. 考虑椭球面曲率的精确延长 + const surfaceNormal = ellipsoid.geodeticSurfaceNormal(position1); + const projection = Cesium.Cartesian3.multiplyByScalar( + surfaceNormal, + Cesium.Cartesian3.dot(direction, surfaceNormal), + new Cesium.Cartesian3() + ); + Cesium.Cartesian3.subtract(direction, projection, direction); + Cesium.Cartesian3.normalize(direction, direction); + + // 4. 最终坐标计算 + return Cesium.Cartesian3.add( + position2, + Cesium.Cartesian3.multiplyByScalar(direction, distance, new Cesium.Cartesian3()), + new Cesium.Cartesian3() + ); + } + 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) + return result; + } + calculateRoadAngle3(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; + } + calculateRoadAngle(startPoint, endPoint) { + // 1. 获取精确地形法向量(需配合地形服务使用) + const normal = Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(startPoint); + + // 2. 构建ENU坐标系(增加异常处理) + if (!Cesium.defined(startPoint) || !Cesium.defined(endPoint)) { + return 0; + } + + 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()); + + // 4. 使用三维向量计算角度(保留高程信息) + const north3D = new Cesium.Cartesian3(1, 0, 0); + const direction3D = new Cesium.Cartesian3( + localEnd.x, localEnd.y, localEnd.z); + Cesium.Cartesian3.normalize(direction3D, direction3D); + + // 5. 计算带符号角度(考虑三维空间关系) + const angle = Cesium.Cartesian3.angleBetween( + north3D, direction3D); + const cross = Cesium.Cartesian3.cross( + north3D, direction3D, new Cesium.Cartesian3()); + + // 6. 返回带符号角度(Z轴分量为负则取反) + return cross.z < 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'); + } + + let widthDis = Cesium.Cartesian3.distance(polygonPositions[0], polygonPositions[1]) + let heightDis = Cesium.Cartesian3.distance(polygonPositions[0], polygonPositions[3]) + + // 计算纹理实际尺寸(米) + // const textureWidthMeters = textureSize.width * meterPerPixel; + // const textureHeightMeters = textureSize.height * meterPerPixel; + const textureWidthMeters = textureSize.width; + const textureHeightMeters = textureSize.height; + console.log(textureWidthMeters, textureHeightMeters, widthDis, heightDis, '宽度') + + // 保持宽高比计算重复次数 + const repeatX = widthDis / textureWidthMeters; + const repeatY = heightDis / textureHeightMeters; + const aspectRatio = textureWidthMeters / textureHeightMeters; + console.log(aspectRatio, 'aspectRatio') + + // 选择主导轴并保持比例 + const dominantRepeat = Math.max(repeatX, repeatY); + let x = Math.max(1, Math.ceil(widthDis / (aspectRatio * heightDis))) + console.log(x, '10') + return new Cesium.Cartesian2( + x, + 1 + ); + } + calculateTextureRepeat2(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]]) + // } + let that = this + // return [arr, rightPositions, leftPositions] + return [area, rightPositions, leftPositions] + } + getIntersects2(segment1Start, segment1End, segment2Start, segment2End) { + // 构造平面(使用线段2的起点和方向向量) + let direction = Cesium.Cartesian3.subtract(segment2End, segment2Start, new Cesium.Cartesian3()); + let plane = Cesium.Plane.fromPointNormal(segment2Start, direction); + + // 计算线段1与平面的交点(增加容差参数) + let intersection = Cesium.IntersectionTests.lineSegmentPlane( + segment1Start, segment1End, plane, 1e-10 + ); + if (!intersection) return null; + + // 使用参数方程验证交点有效性 + let vecToIntersect = Cesium.Cartesian3.subtract(intersection, segment2Start, new Cesium.Cartesian3()); + let t = Cesium.Cartesian3.dot(vecToIntersect, direction) / + Cesium.Cartesian3.magnitudeSquared(direction); + + let result = (t >= -1e-10 && t <= 1.0 + 1e-10) ? intersection : null; + return result; + } + 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 diff --git a/src/Obj/Base/RoadObject/index-拐角连接.js b/src/Obj/Base/RoadObject/index-拐角连接.js new file mode 100644 index 0000000..9fb0c6c --- /dev/null +++ b/src/Obj/Base/RoadObject/index-拐角连接.js @@ -0,0 +1,889 @@ +/** + * @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.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 area = [[], [], []] + area[1] = that.createLineBufferPolygon2(positions, that.options.carRoadWidth / 2) + 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[1], leftItem[2], leftItem2[1], leftItem2[2]) + let rightLine = that.getIntersects(rightItem[1], rightItem[2], rightItem2[1], rightItem2[2]) + + console.log(leftLine, 'leftLine') + if (leftLine) {//左侧相交 + //获取右侧延长交点 + let point1 = that.getExtendPoint(rightItem[1], rightItem[2], 1000) + let point2 = that.getExtendPoint(rightItem2[2], rightItem2[1], 1000) + let rightIntersection = that.getIntersects(rightItem[2], point1, rightItem2[1], point2) + //将其他几条边都延长 + let leftLineNeiPoint = that.getExtendPoint(leftItem[0], leftItem[3], 1000) + let carLeftPoint = that.getExtendPoint(carItem[3], carItem[2], 1000) + let carRightPoint = that.getExtendPoint(carItem[0], carItem[1], 1000) + let rightLineNeiPoint = that.getExtendPoint(rightItem[0], rightItem[3], 1000) + + + + + //跟左侧里相交点 + let leftLineNei = that.getIntersects(leftLine, rightIntersection, leftItem[0], leftLineNeiPoint) + //跟车道左侧相交点 + 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[0], rightLineNeiPoint) + + // 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[3] = leftLineNei + carItem[2] = carLeft + carItem[1] = carRight + rightItem[3] = rightLineNei + rightItem[2] = rightIntersection + console.log(leftItem, carItem, rightItem, 'leftItemleft') + + + //将其他几条边都延长 + let leftLineNeiPoint2 = that.getExtendPoint(leftItem2[3], 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[3], rightItem2[0], 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[3], 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[3], 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[1] = leftLine + leftItem2[0] = leftLineNei2 + carItem2[3] = carLeft2 + carItem2[0] = carRight2 + rightItem2[0] = rightLineNei2 + rightItem2[1] = rightIntersection + console.log(leftItem2, carItem2, rightItem2, 'leftItem2left') + + } else if (rightLine) {//右侧相交 + + //获取左侧延长交点 + let point1 = that.getExtendPoint(leftItem[1], leftItem[2], 1000) + let point2 = that.getExtendPoint(leftItem2[2], leftItem2[1], 1000) + let rightIntersection = that.getIntersects(leftItem[2], point1, leftItem2[1], point2) + //将其他几条边都延长 + let leftLineNeiPoint = that.getExtendPoint(leftItem[0], leftItem[3], 1000) + let carLeftPoint = that.getExtendPoint(carItem[3], carItem[2], 1000) + let carRightPoint = that.getExtendPoint(carItem[0], carItem[1], 1000) + let rightLineNeiPoint = that.getExtendPoint(rightItem[0], rightItem[3], 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[0], 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[3] = leftLineNei + carItem[2] = carLeft + carItem[1] = carRight + rightItem[3] = rightLineNei + rightItem[2] = rightLine + console.log(leftItem, carItem, rightItem, 'leftItemright') + + //将其他几条边都延长 + let leftLineNeiPoint2 = that.getExtendPoint(leftItem2[3], 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[3], rightItem2[0], 1000) + + let leftLineNei2 = that.getIntersects(rightLine, rightIntersection, leftItem2[3], 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[3], 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[1] = rightIntersection + leftItem2[0] = leftLineNei2 + carItem2[3] = carLeft2 + carItem2[0] = carRight2 + rightItem2[0] = rightLineNei2 + rightItem2[1] = rightLine + console.log(leftItem2, carItem2, rightItem2, 'leftItem2right') + + } + } + + + console.log(area[0], 'area') + + 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], 'arr') + 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) => { + 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) => { + 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]) + } + }); + }) + + } + + } + 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 + } + + 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) { + console.log(intersects.features, 'ooooo') + 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 diff --git a/src/Obj/Base/RoadObject/index-直接连接.js b/src/Obj/Base/RoadObject/index-直接连接.js new file mode 100644 index 0000000..e31297a --- /dev/null +++ b/src/Obj/Base/RoadObject/index-直接连接.js @@ -0,0 +1,615 @@ +/** + * @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.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 area = [[], [], []] + area[1] = that.createLineBufferPolygon2(positions, that.options.carRoadWidth / 2) + area[0] = that.createLineBufferPolygonSide(area[1][2], -that.options.sideWidth) + area[2] = that.createLineBufferPolygonSide(area[1][1], that.options.sideWidth) + + 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 () { + 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) => { + 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) => { + 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]) + } + }); + }) + + } + + } + 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 + } + + 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 - 1; i++) { + const start = positions[i]; + 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 offset = Cesium.Cartesian3.multiplyByScalar(perp, width, new Cesium.Cartesian3()); + let point1 = Cesium.Cartesian3.add(start, offset, new Cesium.Cartesian3()) + let point3 = Cesium.Cartesian3.add(end, offset, new Cesium.Cartesian3()) + + i == positions.length - 2 ? area.push(start, point1, end, point3) : area.push(start, point1) + } + 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 arr + } + 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 offset = Cesium.Cartesian3.multiplyByScalar(perp, width, new Cesium.Cartesian3()); + const offset2 = Cesium.Cartesian3.multiplyByScalar(perp, -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, offset, new Cesium.Cartesian3()) + let point4 = Cesium.Cartesian3.add(end, offset2, new Cesium.Cartesian3()) + + 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]]) + } + return [arr, rightPositions, leftPositions] + } + 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 + } + + 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 diff --git a/src/Obj/Base/RoadObject/index-面大小一致.js b/src/Obj/Base/RoadObject/index-面大小一致.js new file mode 100644 index 0000000..620efa6 --- /dev/null +++ b/src/Obj/Base/RoadObject/index-面大小一致.js @@ -0,0 +1,1023 @@ +/** + * @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 diff --git a/src/Obj/Base/RoadObject/index.js b/src/Obj/Base/RoadObject/index.js new file mode 100644 index 0000000..8c58a0b --- /dev/null +++ b/src/Obj/Base/RoadObject/index.js @@ -0,0 +1,1207 @@ +/** + * @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) + // console.log('1212') + function createCustomCorridor(viewer, positions, width) { + // 计算两侧顶点位置 + const leftPositions = []; + const rightPositions = []; + const topPositions = []; + + // 生成两侧和顶部顶点 + for (let i = 0; i < positions.length; i++) { + const position = positions[i]; + const nextPosition = positions[i + 1]; + + if (!nextPosition) continue; + + // 计算方向向量 + const direction = Cesium.Cartesian3.subtract( + nextPosition, + position, + new Cesium.Cartesian3() + ); + Cesium.Cartesian3.normalize(direction, direction); + + // 计算垂直向量 + const normal = Cesium.Cartesian3.cross( + direction, + Cesium.Cartesian3.UNIT_Z, + new Cesium.Cartesian3() + ); + Cesium.Cartesian3.normalize(normal, normal); + + // 计算两侧偏移量 + const offset = Cesium.Cartesian3.multiplyByScalar( + normal, + width / 2, + new Cesium.Cartesian3() + ); + + // 左侧点 + const left = Cesium.Cartesian3.add(position, offset, new Cesium.Cartesian3()); + leftPositions.push(left.x, left.y, left.z); + + // 右侧点 + const right = Cesium.Cartesian3.subtract(position, offset, new Cesium.Cartesian3()); + rightPositions.push(right.x, right.y, right.z); + + // 顶部点(高度增加) + const top = Cesium.Cartesian3.clone(position); + top.z += 100; // 设置顶部高度 + topPositions.push(top.x, top.y, top.z); + } + + // 合并所有顶点 + const allPositions = new Float64Array([ + ...leftPositions, + ...rightPositions, + ...topPositions + ]); + + // 创建几何体 + const geometry = new Cesium.Geometry({ + attributes: { + position: new Cesium.GeometryAttribute({ + componentDatatype: Cesium.ComponentDatatype.DOUBLE, + componentsPerAttribute: 3, + values: allPositions + }) + }, + indices: new Uint16Array([ + // 左侧面索引 + 0, 1, 3, + 1, 4, 3, + // 右侧面索引 + 2, 5, 6, + 2, 6, 7, + // 顶面索引 + 8, 9, 10, + 8, 10, 11 + ]), + primitiveType: Cesium.PrimitiveType.TRIANGLES, + boundingSphere: Cesium.BoundingSphere.fromVertices(allPositions) + }); + + // 创建图元 + const primitive = new Cesium.Primitive({ + geometryInstances: new Cesium.GeometryInstance({ + geometry: geometry + }), + appearance: new Cesium.PerInstanceColorAppearance({ + flat: true, + translucent: false + }), + asynchronous: false + }); + + viewer.scene.primitives.add(primitive); + return primitive; + } + + // 使用示例 + const positions = Cesium.Cartesian3.fromDegreesArray([ + -75.0, 39.0, + -74.5, 39.5, + -74.0, 40.0 + ]); + createCustomCorridor(this.sdk.viewer, positions, 1000); + this.sdk.viewer.camera.flyTo({ + destination: Cesium.Cartesian3.fromDegrees(-75.0, 39.0, 100), + // orientation: { + // heading: Cesium.Math.toRadians(0), + // pitch: Cesium.Math.toRadians(-30), + // roll: 0.0 + // } + }); + + + } + // 创建走廊几何体 + createCorridor(myImg) { + const positions = Cesium.Cartesian3.fromDegreesArray([ + 116.391, 39.907, // 北京 + 116.404, 39.914, + 116.417, 39.921, + 116.430, 39.928 + ]); + + const corridorInstance = new Cesium.GeometryInstance({ + geometry: new Cesium.CorridorGeometry({ + positions: positions, + width: 200.0, + vertexFormat: Cesium.VertexFormat.POSITION_AND_ST, + cornerType: Cesium.CornerType.ROUNDED + }), + attributes: { + color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE) + } + }); + + const primitive = new Cesium.Primitive({ + geometryInstances: corridorInstance, + appearance: new Cesium.MaterialAppearance({ + material: new Cesium.Material({ + fabric: { + type: 'Image', + uniforms: { + image: myImg + } + } + }), + translucent: false + }), + asynchronous: false + }); + + this.sdk.viewer.scene.primitives.add(primitive); + + // 定位到走廊 + this.sdk.viewer.camera.flyTo({ + destination: Cesium.Cartesian3.fromDegrees(116.404, 39.914, 2000), + orientation: { + heading: Cesium.Math.toRadians(0), + pitch: Cesium.Math.toRadians(-30), + roll: 0.0 + } + }); + + return primitive; + } + // 创建道路 + 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]) + if (!leftLine && !rightLine) { + for (let index = 0; index < 4; index++) { + let positions = [] + index === 0 ? positions.push(leftItem[2], leftItem[3]) : index === 1 ? positions.push(leftItem2[2], leftItem2[3]) : index === 2 ? positions.push(rightItem[0], rightItem[1]) : positions.push(rightItem2[0], rightItem2[1]) + that.sdk.viewer.entities.add({ + polyline: { + positions: positions, + width: 10.0, + material: new Cesium.PolylineGlowMaterialProperty({ + color: index === 0 ? Cesium.Color.RED : index === 1 ? Cesium.Color.BLUE : index === 2 ? Cesium.Color.YELLOW : Cesium.Color.GREEN, + glowPower: 0.25, + }), + }, + }); + + } + + } + + 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 diff --git a/src/Obj/Element/Dialog/eventBinding.js b/src/Obj/Element/Dialog/eventBinding.js index 70cecf8..96ef856 100644 --- a/src/Obj/Element/Dialog/eventBinding.js +++ b/src/Obj/Element/Dialog/eventBinding.js @@ -46,8 +46,16 @@ class EventBinding { value = Number(value) if (e.data != '.' && (e.data != '-' || e.target.value)) { if (((!e.target.max) && (!e.target.min)) || ((value <= Number(e.target.max)) && value >= Number(e.target.min))) { - that[m.value] = value + // that[m.value] = value + value = value } + if ((e.target.max) && value > Number(e.target.max)) { + value = Number(e.target.max) + } + if ((e.target.min) && value < Number(e.target.min)) { + value = Number(e.target.min) + } + that[m.value] = value } } }) diff --git a/src/Obj/Materail/RoadTextureMaterialProperty.js b/src/Obj/Materail/RoadTextureMaterialProperty.js new file mode 100644 index 0000000..8f759b2 --- /dev/null +++ b/src/Obj/Materail/RoadTextureMaterialProperty.js @@ -0,0 +1,113 @@ +/* + * @Description: 流动线 + */ +function RoadTexture() { + class RoadTextureMaterialProperty { + constructor(options) { + this._definitionChanged = new Cesium.Event(); + this._image = undefined; + this._repeat = undefined; + this._stRotation = undefined; + this._repeatLength = undefined; + this.image = options.image || ""; + this.repeat = options.repeat || 1.0; + this.stRotation = options.stRotation || 0.0; + // this.rotations = options.rotations || new Array(100).fill(0.0); + } + + get isConstant() { + return false; + } + + get definitionChanged() { + return this._definitionChanged; + } + + getType(time) { + return Cesium.Material.RoadTextureMaterialType; + } + + getValue(time, result) { + if (!Cesium.defined(result)) { + result = {}; + } + result.image = Cesium.Property.getValueOrDefault( + this._image, + time, + "", + result.image + ); + result.repeat = Cesium.Property.getValueOrDefault( + this._repeat, + time, + 1.0, + result.repeat + ); + result.stRotation = Cesium.Property.getValueOrDefault( + this._stRotation, + time, + 0.0, + result.stRotation + ); + console.log(result, 'result') + return result; + } + + equals(other) { + return ( + this === other || + (other instanceof RoadTextureMaterialProperty && + Cesium.Property.equals(this._image, other._image) && + Cesium.Property.equals(this._repeat, other._repeat) && + // Cesium.Property.equals(this._rotations, other._rotations) && + Cesium.Property.equals(this._stRotation, other._stRotation) + ) + ); + } + } + + Object.defineProperties(RoadTextureMaterialProperty.prototype, { + image: Cesium.createPropertyDescriptor("image"), + repeat: Cesium.createPropertyDescriptor("repeat"), + repeatLength: Cesium.createPropertyDescriptor("stRotation"), + }); + + Cesium.RoadTextureMaterialProperty = RoadTextureMaterialProperty; + Cesium.Material.RoadTextureMaterialProperty = "RoadTextureMaterialProperty"; + Cesium.Material.RoadTextureMaterialType = "RoadTextureMaterialType"; + Cesium.Material.RoadTextureMaterialSource = ` + uniform sampler2D image; + uniform float repeat; + czm_material czm_getMaterial(czm_materialInput materialInput) + { + czm_material material = czm_getDefaultMaterial(materialInput); + vec2 st = materialInput.st; + st.s *= repeat; + mat2 rot = mat2(cos(stRotation), -sin(stRotation), sin(stRotation), cos(stRotation)); + vec2 newSt = rot * (st - 0.5) + 0.5; + + vec4 colorImage = texture2D(image, newSt); + material.diffuse = colorImage.rgb; + return material; + } + `; + Cesium.Material._materialCache.addMaterial( + Cesium.Material.RoadTextureMaterialType, + { + fabric: { + type: Cesium.Material.RoadTextureMaterialType, + uniforms: { + image: '', + repeat: 1.0, + stRotation: 0.0, + }, + source: Cesium.Material.RoadTextureMaterialSource, + }, + translucent: function (material) { + return true; + }, + } + ); +} + +export { RoadTexture } diff --git a/src/Obj/Materail/index.js b/src/Obj/Materail/index.js index e7fff6b..324d41c 100644 --- a/src/Obj/Materail/index.js +++ b/src/Obj/Materail/index.js @@ -7,6 +7,7 @@ import { PolylineFlow } from './PolylineFlowMaterialProperty' import { PolylineFlowMult } from './PolylineFlowMultMaterialProperty' import { FlowDashedLine } from './FlowDashedLineFlowMaterialProperty' import { LineTexture } from './LineTextureMaterialProperty' +import { RoadTexture } from './RoadTextureMaterialProperty' function init_material() { StreamWall1() @@ -19,6 +20,7 @@ function init_material() { PolylineFlowMult() FlowDashedLine() LineTexture() + RoadTexture() } export { init_material } diff --git a/static/img/roadPhoto.png b/static/img/roadPhoto.png new file mode 100644 index 0000000..8000eb9 Binary files /dev/null and b/static/img/roadPhoto.png differ diff --git a/static/img/roadTexture.png b/static/img/roadTexture.png new file mode 100644 index 0000000..407266c Binary files /dev/null and b/static/img/roadTexture.png differ diff --git a/static/img/sidePhoto.png b/static/img/sidePhoto.png new file mode 100644 index 0000000..d6218a4 Binary files /dev/null and b/static/img/sidePhoto.png differ