diff --git a/src/Global/efflect/Sunshine/eventBinding.js b/src/Global/efflect/Sunshine/eventBinding.js
index 6e1b840..321dbdb 100644
--- a/src/Global/efflect/Sunshine/eventBinding.js
+++ b/src/Global/efflect/Sunshine/eventBinding.js
@@ -1,45 +1,89 @@
-class eventBinding {
+class EventBinding {
constructor() {
this.element = {}
}
static event = {}
getEvent(name) {
- return eventBinding.event[name]
+ return EventBinding.event[name]
}
getEventAll() {
- return eventBinding.event
+ return EventBinding.event
}
setEvent(name, event) {
- eventBinding.event[name] = event
+ EventBinding.event[name] = event
}
on(that, elements) {
+ this.element = {}
for (let i = 0; i < elements.length; i++) {
- let Event = []
- let isEvent = false
- let removeName = []
if (!elements[i] || !elements[i].attributes) {
continue;
}
+ let Event = {
+ 'input': [],
+ 'change': [],
+ 'blur': [],
+ 'click': []
+ }
+ let isEvent = false
+ let removeName = []
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 })
+ Event.change.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].type == 'number') {
+ Event.input.push((e) => {
+ if (e.target.value || e.target.value === 0) {
+ let value = e.target.value
+ 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
+ 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)
+ }
+ // if ((e.target.dataset.min) && value < Number(e.target.dataset.min)) {
+ // value = Number(e.target.dataset.min)
+ // }
+ that[m.value] = value
+ }
+ }
+ })
+ Event.blur.push((e) => {
+ let value = e.target.value
+ if (e.target.value || (e.target.dataset.null !== 'undefined' && e.target.dataset.null !== '' && !Boolean(e.target.dataset.null))) {
+ value = Number(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)
+ }
+ if ((e.target.dataset.min) && value < Number(e.target.dataset.min)) {
+ value = Number(e.target.dataset.min)
+ }
+ }
+ that[m.value] = value
+ })
+ }
+ else {
+ Event.input.push((e) => {
+ that[m.value] = e.target.value
+ })
+ }
if (elements[i].nodeName == 'IMG') {
elements[i].src = that[m.value]
}
@@ -57,13 +101,13 @@ class eventBinding {
break;
}
case '@click': {
- elements[i].addEventListener('click', (e) => {
- if (typeof (that.Dialog[m.value]) === 'function') {
- that.Dialog[m.value](e)
+ isEvent = true
+ Event.click.push((e) => {
+ if (typeof (that[m.value]) === 'function') {
+ that[m.value](e)
}
- });
+ })
removeName.push(m.name)
- // elements[i].attributes.removeNamedItem(m.name)
break;
}
}
@@ -74,19 +118,18 @@ class eventBinding {
}
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)
+ for (let key in Event) {
+ if (Event[key].length > 0) {
+ elements[i].addEventListener(key, (e) => {
+ for (let t = 0; t < Event[key].length; t++) {
+ Event[key][t](e)
+ }
+ });
}
- });
+ }
}
}
}
}
-const EventBinding = new eventBinding();
export default EventBinding;
diff --git a/src/Global/efflect/Sunshine/index.js b/src/Global/efflect/Sunshine/index.js
index 12119d5..4a921a1 100644
--- a/src/Global/efflect/Sunshine/index.js
+++ b/src/Global/efflect/Sunshine/index.js
@@ -3,7 +3,7 @@
*/
import Dialog from '../../../Obj/Element/Dialog';
import { html } from "./_element";
-import EventBinding from '../../../Obj/Element/Dialog/eventBinding';
+import EventBinding from './eventBinding';
import { syncData } from '../../MultiViewportMode'
import Tools from '../../../Tools'
import TimeLine from './TimeLine'
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 `
+
+
+
+
+
+
模型间隔
+
+
线型选择
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 新增模型风格设置
+
+
+
+
+
+
+
+
+
+ 显隐
+
+
+
+
图标
+
+
![]()
+
+
+
+
默认图标
+
+
![]()
+
+
+
+
+
+
+
+
+
+
+ `
+}
+
+export { html }
diff --git a/src/Obj/Base/BatchModel/index.js b/src/Obj/Base/BatchModel/index.js
index d61e6cd..a42c94e 100644
--- a/src/Obj/Base/BatchModel/index.js
+++ b/src/Obj/Base/BatchModel/index.js
@@ -48,7 +48,7 @@ class BatchModel extends Base {
this.sdk.addIncetance(this.options.id, this)
// BatchModel.computeDis(this)
// if (this.options.positions.length > 0 || this.options.positions.lng) {
- if (options.type && options.spacing != undefined) {
+ if ((options.type && options.spacing != undefined) || options.type == '点') {
// BatchModel.computeDis(this)
let Draw
diff --git a/src/Obj/Base/BillboardObject/index.js b/src/Obj/Base/BillboardObject/index.js
index efcbfe7..98f8857 100644
--- a/src/Obj/Base/BillboardObject/index.js
+++ b/src/Obj/Base/BillboardObject/index.js
@@ -40,6 +40,11 @@ import {
import { getGoodsList } from '../../../Tools/getGoodsList'
class BillboardObject extends Base {
+ #_postRenderEvent = null
+ #_destroyMouseEvent = null
+ #_billboardHeight = 0
+
+
/**
* @constructor
* @description 创建点标注
@@ -118,6 +123,7 @@ class BillboardObject extends Base {
this.options.positions.alt = Number(
Number(options.positions.alt || 0).toFixed(2)
)
+ this.#_billboardHeight = this.options.positions.alt
// this.options.diffuseShow = options.diffuseShow || false
// this.options.diffuseRadius = (options.diffuseRadius || options.diffuseRadius === 0) ? options.diffuseRadius : 10
// this.options.diffuseDuration = (options.diffuseDuration || options.diffuseDuration === 0) ? options.diffuseDuration : 2000
@@ -145,11 +151,18 @@ class BillboardObject extends Base {
this.options.attribute.goods.content || []
this.options.attributeType = options.attributeType || 'richText'
this.options.coordinate = options.coordinate || ''
+ this.options.attributeBoxState = options.attributeBoxState || false
this.operate = {}
this._elms = {}
this.previous = {
positions: { ...this.options.positions }
}
+ this.options.attributePos = options.attributePos || {
+ x: 60,
+ y: 60,
+ width: 200,
+ height: 120
+ }
this.entity
this._proj = this.sdk.proj
@@ -182,7 +195,108 @@ class BillboardObject extends Base {
+ this.#_destroyMouseEvent = () => {
+ this.attributeElm && (this.attributeElm.style.pointerEvents = 'unset')
+ this.sdk.viewer._element.onmousemove = null
+ document.removeEventListener('mouseup', this.#_destroyMouseEvent)
+ document.removeEventListener('mouseleave', this.#_destroyMouseEvent)
+ }
+ this.#_postRenderEvent = () => {
+ let siteInfoPosition = Cesium.Cartesian3.fromDegrees(
+ this.options.positions.lng,
+ this.options.positions.lat,
+ this.#_billboardHeight
+ )
+ if (this.attributeElm && this.entity) {
+ let winpos = this.sdk.viewer.scene.cartesianToCanvasCoordinates(
+ siteInfoPosition
+ )
+ let pixelOffset = this.entity.label.pixelOffset.getValue()
+ if (winpos) {
+ let scale = getCurrentBillboardScale(this.entity, this.sdk.viewer.scene)
+ let height = ((this.entity.billboard.height.getValue() * (this.options.billboard.scale || 0)) + this.options.label.fontSize) * (1 - (scale * scale))
+ let flag = false
+ let lineElm = this.attributeElm.getElementsByClassName('billboard-attribute-box-line')[0]
+ let leftTopElm = this.attributeElm.getElementsByClassName('left-top')[0]
+ let rightTopElm = this.attributeElm.getElementsByClassName('right-top')[0]
+ this.attributeElm.style.left = (winpos.x + this.options.attributePos.x).toFixed(0) + 'px'
+ this.attributeElm.style.top = (winpos.y + pixelOffset.y - (this.options.label.show ? (this.options.label.fontSize / 2) : -(this.options.label.fontSize / 2)) - this.attributeElm.offsetHeight - this.options.attributePos.y + height).toFixed(0) + 'px'
+ this.attributeElm.style.width = this.options.attributePos.width + 'px'
+ this.attributeElm.style.height = this.options.attributePos.height + 'px'
+ if (this.options.attributePos.x < -this.options.attributePos.width / 2) {
+ flag = true
+ lineElm.style.left = 'unset'
+ lineElm.style.right = '0'
+ leftTopElm.style.display = 'block'
+ rightTopElm.style.display = 'none'
+ }
+ else {
+ lineElm.style.left = '0'
+ lineElm.style.right = 'unset'
+ leftTopElm.style.display = 'none'
+ rightTopElm.style.display = 'block'
+ }
+
+ let lineLength
+ let lineAngleRad
+ let lineAngle
+ let x
+ let y
+ if (flag) {
+ x = this.attributeElm.offsetWidth + this.options.attributePos.x
+ y = this.options.attributePos.y ? this.options.attributePos.y : 0
+ }
+ else {
+ x = this.options.attributePos.x
+ y = this.options.attributePos.y ? this.options.attributePos.y : 0
+ }
+ lineLength = Math.sqrt((x * x) + (y * y)).toFixed(2);
+ lineAngleRad = Math.atan(x / y);
+ lineAngle = parseFloat((lineAngleRad * 180 / Math.PI).toFixed(2));
+ if (this.options.attributePos.y < 0) {
+ lineAngle = lineAngle + 180
+ }
+ // if(this.options.attributePos.y<-this.options.attributePos.height/2) {
+ // lineElm.style.bottom = 'unset'
+ // lineElm.style.top = '0'
+ // }
+ // else {
+ // lineElm.style.bottom = -lineLength + 'px'
+ // lineElm.style.top = 'unset'
+ // }
+ lineElm.style.height = lineLength + 'px'
+ lineElm.style.transform = 'rotate(' + lineAngle + 'deg)'
+ }
+ }
+ }
+
+ function getCurrentBillboardScale(entity, scene) {
+ // 获取相机到Billboard的距离
+ const distance = Cesium.Cartesian3.distance(
+ scene.camera.positionWC,
+ entity.position.getValue()
+ );
+ // 获取缩放距离配置
+ const scaleByDistance = entity.billboard.scaleByDistance ? entity.billboard.scaleByDistance.getValue() : undefined;
+
+ if (!scaleByDistance) {
+ // 如果没有设置距离缩放,则使用基础缩放值
+ return 1.0;
+ }
+
+ // 解析缩放距离参数 [near, nearScale, far, farScale]
+ const { near, nearValue, far, farValue } = scaleByDistance;
+ if (distance <= near) {
+ return nearValue;
+ } else if (distance >= far) {
+ return farValue;
+ } else {
+ // 计算中间距离的缩放值(线性插值)
+ const t = (distance - near) / (far - near);
+ return Cesium.Math.lerp(nearValue, farValue, t);
+ }
+ }
this.sdk.addIncetance(this.options.id, this)
@@ -243,6 +357,7 @@ class BillboardObject extends Base {
that.entity.billboard.imgHeight = 0
that.entity.billboard.image = canvas
addCluster(that.sdk, that.entity)
+ that.attributeBoxState && (that.attributeBoxState = true)
}
return
}
@@ -267,6 +382,7 @@ class BillboardObject extends Base {
return img
}, false)
addCluster(that.sdk, that.entity)
+ that.attributeBoxState && (that.attributeBoxState = true)
}
})
}
@@ -298,6 +414,7 @@ class BillboardObject extends Base {
that.entity.billboard.imgHeight = height
that.entity.billboard.image = canvas
addCluster(that.sdk, that.entity)
+ that.attributeBoxState && (that.attributeBoxState = true)
}
}
image.onerror = function (err) {
@@ -309,6 +426,7 @@ class BillboardObject extends Base {
that.entity.billboard.imgHeight = 0
that.entity.billboard.image = canvas
addCluster(that.sdk, that.entity)
+ that.attributeBoxState && (that.attributeBoxState = true)
}
};
}
@@ -465,15 +583,36 @@ class BillboardObject extends Base {
return this.options.show
}
set show(v) {
- if(!this.isShowView) {
+ if (!this.isShowView) {
this.options.show = v
this.originalOptions.show = v
}
- if(!this.showView || this.showView == 3) {
+ if (!this.showView || this.showView == 3) {
this.entity && (this.entity.show = this.options.show)
+ if (this.attributeBoxState && this.options.show) {
+ this.attributeBoxState = this.options.show
+ }
+ else {
+ // 关闭属性框
+ document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ if (this.attributeElm) {
+ this.sdk.viewer._element.removeChild(this.attributeElm)
+ this.attributeElm = null
+ }
+ this.sdk.viewer.scene.postRender.removeEventListener(this.#_postRenderEvent)
+ }
}
else {
this.entity && (this.entity.show = false)
+ // 关闭属性框
+ document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ if (this.attributeElm) {
+ this.sdk.viewer._element.removeChild(this.attributeElm)
+ this.attributeElm = null
+ }
+ this.sdk.viewer.scene.postRender.removeEventListener(this.#_postRenderEvent)
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
@@ -562,6 +701,26 @@ class BillboardObject extends Base {
if (this.entity) {
this.entity.billboard.heightReference = heightMode
this.entity.label.heightReference = heightMode
+ if(heightMode == Cesium.HeightReference.CLAMP_TO_GROUND) {
+ if (this.sdk.viewer.scene.terrainProvider.availability) {
+ Cesium.sampleTerrainMostDetailed(
+ this.sdk.viewer.scene.terrainProvider,
+ [
+ Cesium.Cartographic.fromDegrees(
+ this.options.positions.lng,
+ this.options.positions.lat
+ )
+ ]
+ ).then(position => {
+ this.#_billboardHeight = position[0].height
+ })
+ } else {
+ this.#_billboardHeight = 0
+ }
+ }
+ else {
+ this.#_billboardHeight = this.options.positions.alt
+ }
}
this._elms.heightMode && (this._elms.heightMode.value = heightModeName)
}
@@ -616,6 +775,7 @@ class BillboardObject extends Base {
}
set alt(v) {
this.options.positions.alt = Number(Number(v).toFixed(2))
+ this.#_billboardHeight = this.options.positions.alt
// this.scan && (this.scan.alt = v)
// this.diffuse && (this.diffuse.alt = v)
this.renewPoint()
@@ -1716,6 +1876,22 @@ class BillboardObject extends Base {
this.cameraSelect && this.cameraSelect()
this.ISCSelect && this.ISCSelect()
this.goodsSelect && this.goodsSelect()
+
+ let col = document.createElement('div')
+ col.className = 'col'
+ col.style.flex = '0 0 110px'
+ col.innerHTML = `
+ 属性框
+
+ `
+
+ let row = this._DialogObject._element.content.getElementsByClassName('attribute')[0].getElementsByClassName('row')[0]
+ row.appendChild(col)
+ let boxSwitch = col.getElementsByClassName('btn-switch')[0]
+ boxSwitch.checked = this.attributeBoxState
+ boxSwitch.addEventListener('change', (e) => {
+ this.attributeBoxState = boxSwitch.checked
+ })
let tagData = this.attributeSelect
let attributeElm = this._DialogObject._element.content.getElementsByClassName(
'attribute-select-box'
@@ -2227,6 +2403,7 @@ class BillboardObject extends Base {
this.attributeCamera = this.options.attribute.camera.content
this.attributeGoods = this.options.attribute.goods.content
this.attributeISC = this.options.attribute.ISC.content
+ this.attributeBoxState = this.options.attributeBoxState
this.cameraSelect && this.cameraSelect()
this.goodsSelect && this.goodsSelect()
}
@@ -2234,6 +2411,7 @@ class BillboardObject extends Base {
async remove() {
await remove_entity_from_cluster(this.sdk.viewer, this.entity)
this.entity = null
+ this.attributeBoxState = false
if (!this.sdk.viewer || !this.sdk.viewer.entities) {
return
}
@@ -2439,6 +2617,7 @@ class BillboardObject extends Base {
switch (this._elms.heightMode.value) {
case '海拔高度':
heightElm.value = this.options.positions.alt
+ this.#_billboardHeight = this.options.positions.alt
break
case '相对地表':
if (this.sdk.viewer.scene.terrainProvider.availability) {
@@ -2454,15 +2633,18 @@ class BillboardObject extends Base {
heightElm.value = Number(
(this.options.positions.alt - position[0].height).toFixed(2)
)
+ this.#_billboardHeight = this.options.positions.alt
})
} else {
heightElm.value = this.options.positions.alt
+ this.#_billboardHeight = this.options.positions.alt
}
break
case '依附地表':
break
case '依附模型':
heightElm.value = this.options.positions.alt
+ this.#_billboardHeight = this.options.positions.alt
break
}
}
@@ -2736,6 +2918,216 @@ class BillboardObject extends Base {
(this.originalOptions.customView = this.options.customView)
}
}
+
+ get attributeBoxState() {
+ return this.options.attributeBoxState
+ }
+
+ set attributeBoxState(state) {
+ state = state ? true : false
+ this.options.attributeBoxState = state
+ document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ if (this.attributeElm) {
+ this.sdk.viewer._element.removeChild(this.attributeElm)
+ this.attributeElm = null
+ }
+ this.sdk.viewer.scene.postRender.removeEventListener(this.#_postRenderEvent)
+ if (state && this.sdk && this.sdk.viewer && this.sdk.viewer._element && this.show) {
+ let attributeElm = document.createElement('div')
+ this.attributeElm = attributeElm
+ attributeElm.className = 'billboard-attribute-box'
+ attributeElm.style.top = '0px'
+ attributeElm.style.left = '0px'
+ attributeElm.style.width = 0
+ attributeElm.style.height = 0
+ // attributeElm.innerHTML = this.options.richTextContent
+ this.sdk.viewer._element.appendChild(attributeElm)
+ let linkHtml = ''
+ let goodsHtml = ''
+ let richTextHtml = ''
+ for (let i = 0; i < this.options.attribute.link.content.length; i++) {
+ linkHtml += ``
+ }
+ if (this.options.attribute.goods && this.options.attribute.goods.content && this.options.attribute.goods.content.length > 0) {
+ goodsHtml += `
+
+
+
+ `
+ for (let i = 0; i < this.options.attribute.goods.content.length; i++) {
+ goodsHtml += `
+
${i + 1}
+
${this.options.attribute.goods.content[i].name}
+
${this.options.attribute.goods.content[i].cnt}
+
`
+ }
+ goodsHtml += `
`
+ }
+ if (this.options.richTextContent) {
+ richTextHtml = `
+ ${this.options.richTextContent}
+ `
+ }
+
+ let boxHtml = `
+
+
+ `
+
+ if (!linkHtml && !goodsHtml && !richTextHtml) {
+ boxHtml = boxHtml + '暂无属性信息
'
+ }
+ else {
+ boxHtml = boxHtml + `
+
+ ${richTextHtml}
+ ${goodsHtml}
+ ${linkHtml}
+
+ `
+ }
+
+ attributeElm.innerHTML = boxHtml
+
+ if (attributeElm.getElementsByClassName('tabs')[0]) {
+ let tabsElm = new cy_tabs(attributeElm.getElementsByClassName('tabs')[0], undefined, this.sdk)
+ }
+
+ let imgElm = attributeElm.getElementsByTagName('img')
+ for (let i = 0; i < imgElm.length; i++) {
+ if (!imgElm[i].style.width) {
+ imgElm[i].style.width = '100%'
+ }
+ }
+
+ this.sdk.viewer.scene.postRender.addEventListener(this.#_postRenderEvent)
+ let leftOnmousedown = (e) => {
+ if (this.options.attributePos.width < 200) {
+ this.options.attributePos.width = 200
+ }
+ if (this.options.attributePos.height < 120) {
+ this.options.attributePos.height = 120
+ }
+ let x = e.x
+ let y = e.y
+ let width = this.options.attributePos.width
+ let height = this.options.attributePos.height
+ let positionx = this.options.attributePos.x
+ this.sdk.viewer._element.onmousemove = (e2) => {
+ this.options.attributePos.width = width + (x - e2.x)
+ this.options.attributePos.height = height + (y - e2.y)
+ if (this.options.attributePos.width < 200) {
+ this.options.attributePos.width = 200
+ }
+ else {
+ this.options.attributePos.x = positionx - (x - e2.x)
+ }
+ if (this.options.attributePos.height < 120) {
+ this.options.attributePos.height = 120
+ }
+ // this.options.attributePos.y = positiony + (y - e2.y)
+ }
+ document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ }
+ let rightOnmousedown = (e) => {
+ let x = e.x
+ let y = e.y
+ if (this.options.attributePos.width < 200) {
+ this.options.attributePos.width = 200
+ }
+ if (this.options.attributePos.height < 120) {
+ this.options.attributePos.height = 120
+ }
+ let width = this.options.attributePos.width
+ let height = this.options.attributePos.height
+ this.sdk.viewer._element.onmousemove = (e2) => {
+ this.options.attributePos.width = width + (e2.x - x)
+ this.options.attributePos.height = height + (y - e2.y)
+ }
+ document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ }
+ // leftTopElm.onmousedown = (e) => {
+ // console.log(1111111111)
+ // if (this.options.attributePos.width < 200) {
+ // this.options.attributePos.width = 200
+ // }
+ // if (this.options.attributePos.height < 120) {
+ // this.options.attributePos.height = 120
+ // }
+ // let x = e.x
+ // let y = e.y
+ // let width = this.options.attributePos.width
+ // let height = this.options.attributePos.height
+ // let positionx = this.options.attributePos.x
+ // this.sdk.viewer._element.onmousemove = (e2) => {
+ // this.options.attributePos.width = width + (x - e2.x)
+ // this.options.attributePos.height = height + (y - e2.y)
+ // if (this.options.attributePos.width < 200) {
+ // this.options.attributePos.width = 200
+ // }
+ // else {
+ // this.options.attributePos.x = positionx - (x - e2.x)
+ // }
+ // if (this.options.attributePos.height < 120) {
+ // this.options.attributePos.height = 120
+ // }
+ // // this.options.attributePos.y = positiony + (y - e2.y)
+ // }
+ // document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ // document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ // }
+ // rightTopElm.onmousedown = (e) => {
+ // let x = e.x
+ // let y = e.y
+ // if (this.options.attributePos.width < 200) {
+ // this.options.attributePos.width = 200
+ // }
+ // if (this.options.attributePos.height < 120) {
+ // this.options.attributePos.height = 120
+ // }
+ // let width = this.options.attributePos.width
+ // let height = this.options.attributePos.height
+ // this.sdk.viewer._element.onmousemove = (e2) => {
+ // this.options.attributePos.width = width + (e2.x - x)
+ // this.options.attributePos.height = height + (y - e2.y)
+ // }
+ // document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ // document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ // }
+
+ attributeElm.onmousedown = (e) => {
+ attributeElm.style.pointerEvents = 'none'
+ if (e.target.className.indexOf('left-top') != -1) {
+ leftOnmousedown(e)
+ }
+ else if (e.target.className.indexOf('right-top') != -1) {
+ rightOnmousedown(e)
+ }
+ else {
+ let x = e.x
+ let y = e.y
+ let oldX = this.options.attributePos.x
+ let oldXY = this.options.attributePos.y
+ let height = this.options.attributePos.height
+ this.sdk.viewer._element.onmousemove = (e2) => {
+ this.options.attributePos.x = oldX + (e2.x - x)
+ this.options.attributePos.y = oldXY - (e2.y - y)
+ }
+ document.addEventListener('mouseup', this.#_destroyMouseEvent);
+ document.addEventListener('mouseleave', this.#_destroyMouseEvent);
+ }
+ }
+ }
+ }
}
export default BillboardObject
diff --git a/src/Obj/Base/LabelObject/index.js b/src/Obj/Base/LabelObject/index.js
index 5b127cd..322dd8a 100644
--- a/src/Obj/Base/LabelObject/index.js
+++ b/src/Obj/Base/LabelObject/index.js
@@ -14,6 +14,8 @@ import {
class LabelObject extends Base {
#updateBillboardImageTimeout
+ #canvas = document.createElement('canvas')
+ #canvas2 = document.createElement('canvas')
constructor(sdk, options = {}, model) {
super(sdk, options)
this.model = model
@@ -438,11 +440,12 @@ class LabelObject extends Base {
this.updateBillboardImage()
}
updateBillboardImage() {
- clearTimeout(this.#updateBillboardImageTimeout)
- this.#updateBillboardImageTimeout = setTimeout(() => {
- clearTimeout(this.#updateBillboardImageTimeout)
- this.entity && (this.entity.billboard.image = this.getcanvas())
- }, 500)
+ this.entity.billboard.image = this.getcanvas()
+ // clearTimeout(this.#updateBillboardImageTimeout)
+ // this.#updateBillboardImageTimeout = setTimeout(() => {
+ // clearTimeout(this.#updateBillboardImageTimeout)
+ // this.entity.billboard.image = this.getcanvas()
+ // }, 500)
}
get lineColor() {
return this.options.pixelOffset
@@ -489,9 +492,8 @@ class LabelObject extends Base {
// }
getcanvas() {
- const canvas = document.createElement('canvas')
- const ctx = canvas.getContext('2d')
-
+ const ctx = this.#canvas.getContext('2d')
+ ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);
ctx.font = this.options.fontSize + 'px ' + this.font
let texts = this.options.text.split('\n')
let canvasWidth = 0
@@ -509,9 +511,8 @@ class LabelObject extends Base {
if (canvasWidth < this.options.lineWidth) {
canvasWidth = this.options.lineWidth
}
- canvas.width = canvasWidth
-
- canvas.height = this.options.pixelOffset + canvasHeight
+ this.#canvas.width = canvasWidth
+ this.#canvas.height = this.options.pixelOffset + canvasHeight
const linearGradient = ctx.createLinearGradient(
0,
0,
@@ -558,15 +559,14 @@ class LabelObject extends Base {
ctx.stroke()
ctx.closePath()
- const canvas2 = document.createElement('canvas')
- const ctx2 = canvas2.getContext('2d')
- canvas2.width = canvas.width + 10
- canvas2.height = canvas.height + 10
- ctx2.drawImage(canvas, 5, 5);
+ const ctx2 = this.#canvas2.getContext('2d')
+ this.#canvas2.width = this.#canvas.width + 10
+ this.#canvas2.height = this.#canvas.height + 10
+ ctx2.drawImage(this.#canvas, 5, 5);
// const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// ctx.putImageData(imageData, 40, 40);
- return canvas2
+ return this.#canvas2.toDataURL("image/png")
}
remove() {
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/Base/TrajectoryMotion/_element.js b/src/Obj/Base/TrajectoryMotion/_element.js
index 3303918..81497e3 100644
--- a/src/Obj/Base/TrajectoryMotion/_element.js
+++ b/src/Obj/Base/TrajectoryMotion/_element.js
@@ -182,6 +182,23 @@ function html() {
+
+
`
}
diff --git a/src/Obj/Base/TrajectoryMotion/index.js b/src/Obj/Base/TrajectoryMotion/index.js
index 167135a..aefb9dc 100644
--- a/src/Obj/Base/TrajectoryMotion/index.js
+++ b/src/Obj/Base/TrajectoryMotion/index.js
@@ -78,6 +78,7 @@ class TrajectoryMotion extends Base {
this.options.line.smooth = options.line.smooth ? options.line.smooth : false
this.options.line.noseToTail = options.line.noseToTail ? options.line.noseToTail : false
this.positions_smooth = []
+ this.options.unitFuelConsumption = options.unitFuelConsumption || 0
this.options.ground = options.ground || false
this.options.state = (options.state || options.state === false) ? options.state : true
this.options.routeDirection = (options.routeDirection || options.routeDirection === false) ? options.routeDirection : true
@@ -180,7 +181,8 @@ class TrajectoryMotion extends Base {
if (this.realTimeRoute) {
this.realTimeLine && (this.realTimeLine.show = (!this.showView || this.showView == 3 || !sdkD) ? true : false)
}
- this.label && (this.label.show = (!this.showView || this.showView == 3 || !sdkD) ? this.options.label.show : false)
+ this.label && (this.label.show = (!this.showView || this.showView == 3) ? this.options.label.show : false)
+ this.fuelLabel && (this.fuelLabel.show = (!this.showView || this.showView == 3) ? this.options.fuelShow : false)
}
else {
this.model.show = (!this.showView || this.showView == 3 || !sdkD) ? this.options.show : false
@@ -203,6 +205,7 @@ class TrajectoryMotion extends Base {
this.keyPoints[i].show = (!this.showView || this.showView == 3) ? show : false
}
this.label && (this.label.show = false)
+ this.fuelLabel && (this.fuelLabel.show = false)
this.viewFollow = false
}
@@ -257,14 +260,17 @@ class TrajectoryMotion extends Base {
// Cesium.Matrix4.multiplyByTranslation(this.model.modelMatrix, new Cesium.Cartesian3(0, 0, -difference), this.model.modelMatrix)
// Cesium.Matrix4.getTranslation(this.model.modelMatrix, this.model.position)
this.label && (this.label.show = this.label.show)
+ this.fuelLabel && (this.fuelLabel.show = this.fuelLabel.show)
if (this.options.label.position) {
setTimeout(() => {
if (this.options.label.position.alt) {
this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
+ this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
}
else {
this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, height])
+ this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, height])
})
}
}, 0)
@@ -1168,18 +1174,21 @@ class TrajectoryMotion extends Base {
show = false
}
if (this.show) {
- this.label && (this.label.show = show)
- if (this.options.label.position) {
- setTimeout(() => {
- if (this.options.label.position.alt) {
- this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
- }
- else {
- this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
- this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, height])
- })
- }
- }, 0);
+ if (this.label) {
+ this.label.show = show
+ this.label.pixelOffset = this.options.label.pixelOffset + (this.fuelShow ? this.labelFontSize + 20 : 0)
+ if (this.options.label.position) {
+ setTimeout(() => {
+ if (this.options.label.position.alt) {
+ this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
+ }
+ else {
+ this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
+ this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, height])
+ })
+ }
+ }, 0);
+ }
}
}
else {
@@ -1197,6 +1206,7 @@ class TrajectoryMotion extends Base {
set labelFontFamily(v) {
this.options.label.fontFamily = v || 0
this.label && (this.label.fontFamily = this.options.label.fontFamily)
+ this.fuelLabel && (this.fuelLabel.fontFamily = this.options.label.fontFamily)
let name = getFontFamilyName(this.labelFontFamily) || ''
this._elms.labelFontFamily &&
@@ -1211,6 +1221,7 @@ class TrajectoryMotion extends Base {
set labelColor(v) {
this.options.label.color = v
this.label && (this.label.color = v)
+ this.fuelLabel && (this.fuelLabel.color = v)
if (this._elms.labelColor) {
this._elms.labelColor.forEach((item, i) => {
let labelColorPicker = new YJColorPicker({
@@ -1238,6 +1249,13 @@ class TrajectoryMotion extends Base {
set labelFontSize(v) {
this.options.label.fontSize = v
this.label && (this.label.fontSize = v)
+ if (this.fuelLabel) {
+ this.fuelLabel.fontSize = v
+ this.label.pixelOffset = this.options.label.pixelOffset + v + 20
+ }
+ else {
+ this.label.pixelOffset = this.options.label.pixelOffset
+ }
this._elms.labelFontSize && this._elms.labelFontSize.forEach((item) => {
item.value = v
})
@@ -1249,6 +1267,7 @@ class TrajectoryMotion extends Base {
set labelScaleByDistance(v) {
this.options.label.scaleByDistance = v
this.label && (this.label.scaleByDistance = v)
+ this.fuelLabel && (this.fuelLabel.scaleByDistance = v)
this._elms.labelScaleByDistance && this._elms.labelScaleByDistance.forEach((item) => {
item.checked = v
})
@@ -1264,6 +1283,7 @@ class TrajectoryMotion extends Base {
}
this.options.label.near = near
this.label && (this.label.near = near)
+ this.fuelLabel && (this.fuelLabel.near = near)
this._elms.labelNear && this._elms.labelNear.forEach((item) => {
item.value = near
})
@@ -1279,11 +1299,66 @@ class TrajectoryMotion extends Base {
}
this.options.label.far = far
this.label && (this.label.far = far)
+ this.fuelLabel && (this.fuelLabel.far = far)
this._elms.labelFar && this._elms.labelFar.forEach((item) => {
item.value = far
})
}
+ get unitFuelConsumption() {
+ return this.options.unitFuelConsumption
+ }
+
+ set unitFuelConsumption(v) {
+ this.options.unitFuelConsumption = v
+ this._elms.unitFuelConsumption && this._elms.unitFuelConsumption.forEach((item) => {
+ item.value = v
+ })
+ }
+
+ get fuelShow() {
+ return this.options.fuelShow
+ }
+
+ set fuelShow(v) {
+ this.options.fuelShow = v
+ let show = v
+ if (this.show && (!this.showView || this.showView == 3)) {
+ show = v
+ }
+ else {
+ show = false
+ }
+ if (this.show) {
+ if (this.fuelLabel) {
+ this.fuelLabel.show = show
+ this.label.pixelOffset = this.options.label.pixelOffset + (show ? this.labelFontSize + 20 : 0)
+ }
+ else {
+ this.label.pixelOffset = this.options.label.pixelOffset
+ }
+ if (this.options.label.position) {
+ setTimeout(() => {
+ if (this.options.label.position.alt) {
+ this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
+ }
+ else {
+ this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
+ this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, height])
+ })
+ }
+ }, 0);
+ }
+ }
+ else {
+ this.fuelLabel && (this.fuelLabel.show = false)
+ this.label.pixelOffset = this.options.label.pixelOffset
+ }
+ this._elms.fuelShow && this._elms.fuelShow.forEach((item) => {
+ item.checked = v
+ })
+ }
+
// 创建路径
static addLine(that) {
let positions_smooth = that.renewLinePositions(that.options.line.positions)
@@ -1402,6 +1477,7 @@ class TrajectoryMotion extends Base {
}
let pos = that.smooth ? that.positions_smooth : Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights)
TrajectoryMotion.createLabel(that)
+ TrajectoryMotion.createFuelLabel(that)
that.modelMove(pos)
@@ -1411,13 +1487,13 @@ class TrajectoryMotion extends Base {
static async createLabel(that) {
let labelPosition = that.cartesian3Towgs84(that.model.position, that.sdk.viewer)
that.label = new LabelObject(that.sdk, {
- show: that.options.show ? (that.options.model.show ? that.options.label.show : false) : false,
+ show: that.options.show ? (that.options.label.show ? true : false) : false,
position: [labelPosition.lng, labelPosition.lat, labelPosition.alt],
text: that.options.name,
fontSize: that.options.label.fontSize,
fontFamily: that.options.label.fontFamily,
color: that.options.label.color,
- pixelOffset: that.options.label.pixelOffset,
+ pixelOffset: that.options.label.pixelOffset + (that.options.fuelShow ? that.options.label.fontSize + 20 : 0),
backgroundColor: that.options.label.backgroundColor,
lineColor: that.options.label.lineColor,
lineWidth: that.options.label.lineWidth,
@@ -1427,6 +1503,26 @@ class TrajectoryMotion extends Base {
}, that.model)
}
+ static async createFuelLabel(that) {
+ let labelPosition = that.cartesian3Towgs84(that.model.position, that.sdk.viewer)
+ that.fuelLabel = new LabelObject(that.sdk, {
+ show: that.options.show ? (that.options.fuelShow ? true : false) : false,
+ // show: true,
+ position: [labelPosition.lng, labelPosition.lat, labelPosition.alt],
+ text: '总油耗:',
+ fontSize: that.options.label.fontSize,
+ fontFamily: that.options.label.fontFamily,
+ color: that.options.label.color,
+ pixelOffset: 0,
+ backgroundColor: ['#6e6e6e', '#6e6e6e'],
+ lineColor: '#00ffff00',
+ lineWidth: 0,
+ scaleByDistance: that.options.label.scaleByDistance,
+ near: that.options.label.near,
+ far: that.options.label.far
+ }, that.model)
+ }
+
// 创建关键点
static async addKeyPoint(that) {
for (let i = 0; i < that.options.line.positions.length; i++) {
@@ -1531,8 +1627,8 @@ class TrajectoryMotion extends Base {
else {
setPosition(startDistance)
setTimeout(() => {
- _this.model && (_this.model.isMove = false)
- }, 500);
+ _this.model.isMove = false
+ }, 1000);
animateUpdate()
@@ -1555,6 +1651,8 @@ class TrajectoryMotion extends Base {
}
async function setPosition(distance) {
+ _this.totalFuelConsumption = Number((distance / 100 * _this.unitFuelConsumption).toFixed(2))
+ _this.fuelLabel.text = '总油耗:' + _this.totalFuelConsumption + ' L'
_this.model.isMove = true
let sdk2D = get2DView()
let splitSdk = getSdk()
@@ -1766,6 +1864,7 @@ class TrajectoryMotion extends Base {
}
let labelPosition = _this.cartesian3Towgs84(position, _this.sdk.viewer)
_this.label.position = [labelPosition.lng, labelPosition.lat, labelPosition.alt]
+ _this.fuelLabel.position = [labelPosition.lng, labelPosition.lat, labelPosition.alt]
lastDistance = distance
// console.log(position)
_this.realTimeRouteArray.push(position)
@@ -2162,6 +2261,7 @@ class TrajectoryMotion extends Base {
this.sdk.viewer.entities.remove(this.line)
this.sdk.viewer.entities.remove(this.realTimeLine)
this.label && this.label.remove()
+ this.fuelLabel && this.fuelLabel.remove()
for (let i = 0; i < this.keyPointShow.length; i++) {
this.sdk.viewer.entities.remove(this.keyPointShow[i])
}
@@ -2169,6 +2269,7 @@ class TrajectoryMotion extends Base {
this.realTimeLine = null
this.model = null
this.label = null
+ this.fuelLabel = null
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
@@ -2222,6 +2323,7 @@ class TrajectoryMotion extends Base {
this.model && (this.model.show = false)
}
this.labelShow = this.originalOptions.label.show
+ this.fuelLabelShow = this.originalOptions.fuelShow
this.labelColor = this.originalOptions.label.color
this.labelFontSize = this.originalOptions.label.fontSize
this.labelFontFamily = this.originalOptions.label.fontFamily
diff --git a/src/Obj/Element/cy_html_tabs.js b/src/Obj/Element/cy_html_tabs.js
index 1270e29..464c37b 100644
--- a/src/Obj/Element/cy_html_tabs.js
+++ b/src/Obj/Element/cy_html_tabs.js
@@ -1,6 +1,13 @@
class cy_tabs {
- constructor(id, clickTabCallBack, sdk) {
- let elm = document.getElementById(id);
+ constructor(boxElm, clickTabCallBack, sdk) {
+ let elm
+ if(typeof boxElm === 'string') {
+ elm = document.getElementById(boxElm);
+ }
+ else {
+ elm = boxElm
+ }
+ // let elm = document.getElementById(id);
let pane = elm.getElementsByTagName('DIV-cy-tab-pane')
let tabTop = ``
@@ -37,7 +44,9 @@
tabContent = tabContent + `
`
let BoxElm = document.createElement('div');
- BoxElm.setAttribute('id', id)
+ if(typeof boxElm === 'string') {
+ BoxElm.setAttribute('id', boxElm)
+ }
BoxElm.setAttribute('class', 'DIV-cy-tabs')
BoxElm.innerHTML = tabTop + tabContent
elm.parentNode.insertBefore(BoxElm, elm);
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/custom/css/index.css b/static/custom/css/index.css
index ebb0d0d..e27a648 100644
--- a/static/custom/css/index.css
+++ b/static/custom/css/index.css
@@ -1429,6 +1429,24 @@
margin-bottom: 10px;
display: flex;
position: relative;
+ overflow-y: auto;
+}
+
+.DIV-cy-tabs .DIV-cy-tab-top::-webkit-scrollbar {
+ width: 4px;
+ height: 4px;
+}
+
+.DIV-cy-tabs .DIV-cy-tab-top::-webkit-scrollbar-thumb {
+ border-radius: 5px;
+ -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+ background-color: rgba(var(--color-sdk-base-rgb));
+}
+
+.DIV-cy-tabs .DIV-cy-tab-top::-webkit-scrollbar-track {
+ -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+ border-radius: 5px;
+ background-color: rgba(var(--color-sdk-base-rgb), 0.1);
}
.DIV-cy-tabs .DIV-cy-tab-top::after {
@@ -1473,7 +1491,14 @@
border-bottom: 2px solid #dddddd00;
position: relative;
z-index: 2;
+ white-space: nowrap;
+ user-select: none;
cursor: pointer;
+ -webkit-pointer-events: auto;
+ -moz-pointer-events: auto;
+ -ms-pointer-events: auto;
+ -o-pointer-events: auto;
+ pointer-events: auto;
}
.DIV-cy-tabs .DIV-cy-tab-pane-title-p span {
@@ -3097,9 +3122,9 @@
/* 文本框 */
.popup-textarea{
/* width: 212px; */
- width: 161.6px;
+ width: 161px;
/* height: 154px; */
- height: 119.2px;
+ height: 119px;
display: block;
pointer-events: none;
position: absolute;
@@ -3109,6 +3134,8 @@
padding: 5px 5px 0px 5px;
}
.popup-textarea textarea{
+ width: 158px;
+ height: 95px;
background-color: unset!important;
border: unset!important;
color: #fff;
@@ -3586,22 +3613,35 @@
border: 1.5px solid;
border-image: linear-gradient(to bottom, var(--color-sdk-gradual)) 1;
color: #fff;
+ min-width: 200px;
+ min-height: 120px;
+ box-sizing: border-box;
+ /* -webkit-pointer-events: none;
+ -moz-pointer-events: none;
+ -ms-pointer-events: none;
+ -o-pointer-events: none;
+ pointer-events: none; */
}
+
.billboard-attribute-box .DIV-cy-tabs {
height: 100%;
display: flex;
flex-direction: column;
}
+
.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-top .DIV-cy-tab-pane-title {
padding: 0 2px;
}
+
.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-top .DIV-cy-tab-pane-title:first-child {
padding-left: 0;
}
+
.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-top .DIV-cy-tab-pane-title:last-child {
padding-right: 0;
}
-.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-top .DIV-cy-tab-pane-title span{
+
+.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-top .DIV-cy-tab-pane-title span {
margin: 0 5px;
}
@@ -3609,4 +3649,116 @@
padding: 0 5px 5px 5px;
box-sizing: border-box;
flex: 1;
+ overflow: auto;
+}
+
+.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-content::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-content::-webkit-scrollbar-thumb {
+ border-radius: 5px;
+ -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+ background-color: rgba(var(--color-sdk-base-rgb));
+}
+
+.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-content::-webkit-scrollbar-track {
+ -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+ border-radius: 5px;
+ background-color: rgba(var(--color-sdk-base-rgb), 0.1);
+}
+
+.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-content-pane {
+ width: 100%;
+ height: 100%;
+}
+
+.billboard-attribute-box .DIV-cy-tabs .DIV-cy-tab-content-pane iframe {
+ border: none;
+}
+
+.billboard-attribute-box .billboard-attribute-box-line {
+ position: absolute;
+ width: 0px;
+ /* border-left: 1px solid rgba(var(--color-sdk-base-rgb), 0.5); */
+ border-left: 1px solid rgba(var(--color-sdk-base-rgb), 1);
+ /* transform: rotate(45deg); */
+ transform-origin: 0px 0px;
+ -webkit-pointer-events: none;
+ -moz-pointer-events: none;
+ -ms-pointer-events: none;
+ -o-pointer-events: none;
+ pointer-events: none;
+}
+
+.billboard-attribute-box .drag-nook {
+ position: absolute;
+ width: 12px;
+ height: 12px;
+ display: block;
+ user-select: none;
+ -webkit-pointer-events: auto;
+ -moz-pointer-events: auto;
+ -ms-pointer-events: auto;
+ -o-pointer-events: auto;
+ pointer-events: auto;
+ z-index: 3;
+ clip-path: polygon(0% 100%, 100% 100%, 50% 50%);
+ background-image: linear-gradient(to top, #ffffff 1px, #00000000 1px);
+ background-size: 100% 3px;
+ /* background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAJRJREFUWEftltsJgFAMQ5NNdBJ1Eh3NTdRJdJPIBQXF50/p/WgHSNNDCSGch877EQbyIyCpBtAa/cZEsj9qXwhImgEURgZA8rTzzkAiYGVgITm+ErC6/Ek3vycMAkHAnYCkAUDKAosZSTaeSZiCqIwgCgJBIG8CWyXzKySSZBGBu+afStYBqIxMfJdSo8WPslHJgsAKWjkmIRBy/c8AAAAASUVORK5CYII='); */
+}
+
+.billboard-attribute-box .drag-nook.left-top {
+ top: -6px;
+ left: -6px;
+ cursor: se-resize;
+ transform: rotate(-45deg);
+ display: none;
+}
+
+.billboard-attribute-box .drag-nook.right-top {
+ top: -6px;
+ right: -6px;
+ cursor: ne-resize;
+ transform: rotate(45deg);
+ display: none;
+}
+
+.billboard-attribute-box .table {
+ background-color: #ffffff00;
+ color: #ffffff;
+ overflow: hidden;
+ border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
+}
+
+.billboard-attribute-box .table .table-head .tr {
+ border-top: none;
+ border-left: none;
+ border-right: none;
+}
+
+.billboard-attribute-box .table .tr {
+ display: flex;
+ border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
+ border-right: none;
+}
+.billboard-attribute-box .table .tr .th, .billboard-attribute-box .table .tr .td {
+ border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
+ display: flex;
+ justify-content: center;
+}
+.billboard-attribute-box .table .tr .th:last-child, .billboard-attribute-box .table .tr .td:last-child {
+ border-right: none;
+}
+
+
+.billboard-attribute-box .table .table-body .tr {
+ border-bottom: none;
+ border-left: none;
+}
+
+.billboard-attribute-box .table .table-body .tr:first-child {
+ border-top: none;
}
\ No newline at end of file
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