Files
sdk4.0/src/Obj/Base/GroundSvg/index.js
2025-09-01 10:19:06 +08:00

2255 lines
82 KiB
JavaScript

import Dialog from '../../Element/Dialog';
import { html } from "./_element";
import EventBinding from '../../Element/Dialog/eventBinding';
import { syncData } from '../../../Global/MultiViewportMode'
import LabelObject from '../LabelObject'
import DrawPoint from '../../../Draw/drawPoint.js'
import richText from '../../Element/richText'
import { legp } from '../../Element/datalist'
import { FontLoader } from '../../../../static/3rdparty/three/jsm/loaders/FontLoader.js';
import { TextGeometry } from '../../../../static/3rdparty/three/jsm/geometries/TextGeometry.js';
import * as variable from '../../../../static/3rdparty/three/fonts/FZZongYi-M05S_regular.typeface.json'
import Base from "../index";
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../../../Global/global'
import { setSplitDirection, syncSplitData, setActiveId } from '../../../Global/SplitScreen'
class GroundSvg extends Base {
/**
* @constructor
* @param sdk
* @description 贴地svg
* @param options {object} 属性
* @param options.id {string} 唯一标识
* @param options.show=true {boolean} 显示/隐藏
* @param options.name {string} 名称
* @param options.angle=0 {number} 旋转角度
* @param options.scale {object} 比例
* @param options.scale.x=1 {number} x轴比例
* @param options.scale.y=1 {number} y轴比例
* @param options.url {string} 资源地址
* @param options.flipe {object} 翻转
* @param options.flipe.x=false {boolean} 绕X轴翻转
* @param options.flipe.y=false {boolean} 绕Y轴翻转
* @param {Array.<object>} options.position 位置
* @param options.position.lng {number} 经度
* @param options.position.lat {number} 纬度
* @param options.color {string} 颜色
* @param options.text {object} 文字
* @param options.text.show=true {boolean} 文字
* @param options.text.position.lng {number} 经度
* @param options.text.position.lat {number} 纬度
* @param options.text.position.alt {number} 高度
* @param options.text.fontSize=20 {number} 字体大小
* @param options.text.color=#ffffff {string} 字体大小
* @param options.text.scaleByDistance {boolean} 距离缩放
* @param options.text.near=2000 {number} 视野缩放最近距离
* @param options.text.far=100000 {number} 视野缩放最远距离
* @param options.attribute {object} 属性内容
* @param {object} options.attribute.link={} 链接
* @param options.attribute.link.content=[]] {array} 链接内容
* @param options.attribute.link.content[].name {string} 链接名称
* @param options.attribute.link.content[].url {string} 链接地址
* @param options.richTextContent {string} 富文本内容
* @param options.customView {object} 默认视角
* @param options.customView.orientation {object} 默认视角方位
* @param options.customView.orientation.heading {number} 航向角
* @param options.customView.orientation.pitch {number} 俯仰角
* @param options.customView.orientation.roll {number} 翻滚角
* @param options.customView.relativePosition {object} 视角相对位置
* @param options.customView.relativePosition.lng {number} 经度
* @param options.customView.relativePosition.lat {number} 纬度
* @param options.customView.relativePosition.alt {number} 高度
* */
#loadEvent = void 0
#loaded = false
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options);
let jsCode = `
importScripts('${this.getSourceRootPath()}/3rdparty/turf.min.js');
self.addEventListener('message', function (e) {
let features = []
eval(e.data.code);
self.postMessage(features);
}, false);
`;
let dataUri = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(jsCode);
this._worker = new Worker(dataUri);
this.options.angle = this.options.angle || 0
this.loaded = false;
this.ismove = false;
if (this.options.position.lat > 83.5) {
this.options.position.lat = 83.5
}
if (this.options.position.lat < -83.5) {
this.options.position.lat = -83.5
}
this.options.show = (options.show || options.show === false) ? options.show : true
this.options.scale = options.scale || {}
this.options.scale.x = (this.options.scale.x || this.options.scale.x === 0) ? this.options.scale.x : 1
this.options.scale.y = (this.options.scale.y || this.options.scale.y === 0) ? this.options.scale.y : 1
this.options.flipe = options.flipe || {}
this.options.flipe.x = this.options.flipe.x || false
this.options.flipe.y = this.options.flipe.y || false
this.options.attribute = options.attribute || {}
this.options.attribute.link = this.options.attribute.link || {}
this.options.attribute.link.content =
this.options.attribute.link.content || []
this.options.attributeType = options.attributeType || 'richText'
options.text = options.text || {}
this.options.text = {
value: options.text.value || '',
show: (options.text.show || options.text.show === false) ? options.text.show : true,
position: options.text.position,
fontSize: (options.text.fontSize || options.text.fontSize === 0) ? options.text.fontSize : 20,
color: options.text.color || '#ffffff',
scaleByDistance: options.text.scaleByDistance || false,
near: (options.text.near || options.text.near === 0) ? options.text.near : 2000,
far: (options.text.far || options.text.far === 0) ? options.text.far : 100000,
}
if (this.options.text.position) {
let point1 = turf.point([this.options.position.lng, this.options.position.lat])
let point2 = turf.point([this.options.text.position.lng, this.options.text.position.lat])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle = turf.rhumbBearing(point1, point2);
this._textToCenter = {
distance: distance,
angle: angle
}
}
this.hierarchys = []
this._elms = {};
this.Dialog = _Dialog
this._isdrag = false
this._EventBinding = new EventBinding()
if(this.sdk.entityMap.get(this.options.id)) {
return
}
this.sdk.addIncetance(this.options.id, this)
this.picking = true
if (this.options.show) {
setSplitDirection(0, this.options.id)
}
this._entityArray = []
this.init()
}
get type () {
return 'GroundSvg'
}
get attributeSelect() {
return [
{
name: '富文本',
value: '富文本',
key: 'richText'
},
{
name: '链接',
value: '链接',
key: 'link'
},
]
}
get name() {
return this.options.name
}
set name(v) {
this.options.name = v
this._elms.name && this._elms.name.forEach((item) => {
item.value = v
})
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
if (this.options.text && this.options.text.show) {
if(this.text) {
if((!this.showView || this.showView == 3)) {
this.text.show = v
}
else {
this.text.show = false
}
}
}
super.show = v
} else {
console.error("参数必须为boolean")
}
}
get position() {
return this.options.position
}
set position(v) {
this.options.position = v
if (this.options.position.lat > 83.5) {
this.options.position.lat = 83.5
}
if (this.options.position.lat < -83.5) {
this.options.position.lat = -83.5
}
this._update()
if (this._textToCenter) {
let point = turf.point([this.options.position.lng, this.options.position.lat])
let targetPoint = turf.destination(point, this._textToCenter.distance, this._textToCenter.angle, { units: 'kilometers' }).geometry.coordinates
this.getClampToHeight({ lng: targetPoint[0], lat: targetPoint[1] }).then((height) => {
let textPosition = [targetPoint[0], targetPoint[1], height]
this.text && (this.text.position = textPosition)
})
}
}
get color() {
return this.options.color
}
set color(v) {
this.options.color = v
if (this.options.color) {
for (let i = 0; i < this.entity.values.length; i++) {
this.entity.values[i].polygon.material = Cesium.Color.fromCssColorString(this.options.color)
}
}
else {
for (let i = 0; i < this.entity.values.length; i++) {
this.entity.values[i].polygon.material = Cesium.Color.fromCssColorString(this.entity.values[i].properties.color._value)
}
}
if (this._elms.color) {
this._elms.color.forEach((item, i) => {
let colorPicker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.color || undefined,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.color = c
},//点击确认按钮事件回调
clear: () => {
this.color = ''
},//点击清空按钮事件回调
})
this._elms.color[i] = colorPicker
})
}
}
get angle() {
return this.options.angle
}
set angle(v) {
// console.log(v, Math.ceil(Math.abs(v / 360)), (Number(v) + Number(v) * Math.ceil(Math.abs(v / 360))) % 360)
let angle = (Number(v) + 360) % 360
angle = parseFloat(angle.toFixed(1))
this.options.angle = angle
if (v > 0 && angle === 0) {
this.options.angle = 360
}
this._elms.angle && this._elms.angle.forEach((item) => {
item.value = this.options.angle
})
this._update()
}
get scale() {
return this.options.scale
}
set scale(scale) {
this.options.scale.x = scale.x
this.options.scale.y = scale.y
if (this._elms) {
this._elms.xRange && (this._elms.xRange.value = this.options.scale.x)
this._elms.yRange && (this._elms.yRange.value = this.options.scale.y)
this._elms.xInput && (this._elms.xInput.value = this.options.scale.x)
this._elms.yInput && (this._elms.yInput.value = this.options.scale.y)
}
this._update()
}
get flipeY() {
return this.options.flipe.y
}
set flipeY(v) {
if (typeof v === "boolean") {
this.options.flipe.y = v
this._update()
} else {
console.error("参数必须为boolean")
}
}
get flipeX() {
return this.options.flipe.x
}
set flipeX(v) {
if (typeof v === "boolean") {
this.options.flipe.x = v
this._update()
} else {
console.error("参数必须为boolean")
}
}
get textValue() {
return this.options.text.value
}
set textValue(v) {
this.options.text.value = v
if(this.text) {
this.text.text = v
}
else {
GroundSvg.createText(this)
}
this._elms.textValue && this._elms.textValue.forEach((item) => {
item.value = v
})
}
get textShow() {
return this.options.text.show
}
set textShow(v) {
this.options.text.show = v
if (this.show) {
if((!this.showView || this.showView == 3)) {
this.text && (this.text.show = v)
}
else {
this.text && (this.text.show = false)
}
if (this.options.text.position) {
setTimeout(() => {
if (this.options.text.position.alt) {
this.text && (this.text.position = [this.options.text.position.lng, this.options.text.position.lat, this.options.text.position.alt])
}
else {
this.getClampToHeight({ lng: this.options.text.position.lng, lat: this.options.text.position.lat }).then((height) => {
this.text && (this.text.position = [this.options.text.position.lng, this.options.text.position.lat, height])
})
}
}, 0);
}
}
else {
this.text && (this.text.show = false)
}
this._elms.textShow && this._elms.textShow.forEach((item) => {
item.checked = v
})
}
get textColor() {
return this.options.text.color
}
set textColor(v) {
this.options.text.color = v
this.text && (this.text.color = v)
if (this._elms.textColor) {
this._elms.textColor.forEach((item, i) => {
let textColorPicker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.textColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.textColor = color
},//点击确认按钮事件回调
clear: () => {
this.textColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.textColor[i] = textColorPicker
})
}
}
get textFontSize() {
return this.options.text.fontSize
}
set textFontSize(v) {
this.options.text.fontSize = v
if(this.text) {
this.text.fontSize = v
this.text.pixelOffset = v
}
this._elms.textFontSize && this._elms.textFontSize.forEach((item) => {
item.value = v
})
}
get textScaleByDistance() {
return this.options.text.scaleByDistance
}
set textScaleByDistance(v) {
this.options.text.scaleByDistance = v
this.text && (this.text.scaleByDistance = v)
this._elms.textScaleByDistance && this._elms.textScaleByDistance.forEach((item) => {
item.checked = v
})
}
get textNear() {
return this.options.text.near
}
set textNear(v) {
let near = v
if (near > this.textFar) {
near = this.textFar
}
this.options.text.near = near
this.text && (this.text.near = near)
this._elms.textNear && this._elms.textNear.forEach((item) => {
item.value = near
})
}
get textFar() {
return this.options.text.far
}
set textFar(v) {
let far = v
if (far < this.textNear) {
far = this.textNear
}
this.options.text.far = far
this.text && (this.text.far = far)
this._elms.textFar && this._elms.textFar.forEach((item) => {
item.value = far
})
}
get attributeType() {
return this.options.attributeType
}
set attributeType(v) {
this.options.attributeType = v
this._elms.attributeType &&
this._elms.attributeType.forEach(item => {
item.value = v
})
let attributeContent = this._DialogObject._element.content.getElementsByClassName(
'attribute-content'
)
for (let i = 0; i < attributeContent.length; i++) {
if (
attributeContent[i].className.indexOf('attribute-content-' + v) > -1
) {
attributeContent[i].style.display = 'block'
} else {
attributeContent[i].style.display = 'none'
}
}
}
get attributeLink() {
return this.options.attribute.link.content
}
set attributeLink(v) {
this.options.attribute.link.content = v
if (
!this._DialogObject ||
!this._DialogObject._element ||
!this._DialogObject._element.content ||
this._DialogObject._element.content.getElementsByClassName(
'attribute-content-link'
).length == 0
) {
return
}
let table = this._DialogObject._element.content
.getElementsByClassName('attribute-content-link')[1]
.getElementsByClassName('table')[0]
let tableContent = table.getElementsByClassName('table-body')[0]
tableContent.innerHTML = ''
if (this.options.attribute.link.content.length > 0) {
table.getElementsByClassName('table-empty')[0].style.display = 'none'
} else {
table.getElementsByClassName('table-empty')[0].style.display = 'flex'
}
for (let i = 0; i < this.options.attribute.link.content.length; i++) {
let tr =
`
<div class="tr">
<div class="td">` +
this.options.attribute.link.content[i].name +
`</div>
<div class="td">` +
this.options.attribute.link.content[i].url +
`</div>
<div class="td">
<button @click="linkEdit">编辑</button>
<button @click="linkDelete">删除</button>
</div>
</div>`
let trElm = document.createRange().createContextualFragment(tr)
tableContent.appendChild(trElm)
}
let item = tableContent.getElementsByClassName('tr')
let fun = {
linkEdit: async index => {
this.attributeLink = await this.options.attribute.link.content
let table = this._DialogObject._element.content
.getElementsByClassName('attribute-content-link')[1]
.getElementsByClassName('table')[0]
let tableContent = table.getElementsByClassName('table-body')[0]
let item = tableContent.getElementsByClassName('tr')
for (let i = 0; i < item.length; i++) {
if (index === i) {
let height = item[i].offsetHeight
let html = `
<div class="td">
<input class="input" type="text">
</div>
<div class="td">
<textarea class="input link-edit" type="text"></textarea>
</div>
<div class="td">
<button @click="confirmEdit">确认</button>
<button @click="cancelEdit">取消</button>
</div>`
item[i].innerHTML = html
let textareaElm = item[i].getElementsByClassName('link-edit')[0]
textareaElm.style.height = height - 10 + 'px'
let td = item[i].getElementsByClassName('td')
td[0].getElementsByClassName(
'input'
)[0].value = this.options.attribute.link.content[index].name
td[1].getElementsByClassName(
'input'
)[0].value = this.options.attribute.link.content[index].url
let btn = item[i].getElementsByTagName('button')
for (let n = 0; n < btn.length; n++) {
if (!btn[n] || !btn[n].attributes) {
continue
}
for (let m of btn[n].attributes) {
if (m.name === '@click') {
btn[n].addEventListener('click', e => {
if (typeof fun[m.value] === 'function') {
fun[m.value](
{
name: td[0].getElementsByClassName('input')[0].value,
url: td[1].getElementsByClassName('input')[0].value
},
i
)
}
})
btn[n].attributes.removeNamedItem(m.name)
break
}
}
}
break
}
}
},
linkDelete: i => {
this.options.attribute.link.content.splice(i, 1)
this.attributeLink = this.options.attribute.link.content
},
confirmEdit: (value, i) => {
let name = value.name && value.name.replace(/\s/g, '')
let url = value.url && value.url.replace(/\s/g, '')
if (name && url) {
this.options.attribute.link.content[i] = value
} else {
window.ELEMENT &&
window.ELEMENT.Message({
message: '名称或链接不能为空!',
type: 'warning',
duration: 1500
})
}
this.attributeLink = this.options.attribute.link.content
},
cancelEdit: () => {
this.attributeLink = this.options.attribute.link.content
},
fileSelect: (value, i) => {
let fileElm = item[i].getElementsByClassName('file-select')[0]
fileElm.click()
fileElm.removeEventListener('change', fileSelect)
fileElm.addEventListener('change', fileSelect)
}
}
let fileSelect = event => {
if (event.target.value) {
let td = item[
event.target.getAttribute('index')
].getElementsByClassName('td')
td[1].getElementsByClassName('input')[0].value = event.target.value
event.target.value = null
}
}
for (let i = 0; i < item.length; i++) {
let btn = item[i].getElementsByTagName('button')
for (let n = 0; n < btn.length; n++) {
if (!btn[n] || !btn[n].attributes) {
continue
}
for (let m of btn[n].attributes) {
if (m.name === '@click') {
btn[n].addEventListener('click', e => {
if (typeof fun[m.value] === 'function') {
fun[m.value](i)
}
})
btn[n].attributes.removeNamedItem(m.name)
break
}
}
}
}
}
init() {
let url = this.replaceHost(this.options.url, this.options.host)
syncData(this.sdk, this.options.id)
this.hierarchys = []
this.originalOptions = this.deepCopyObj(this.options)
let geometryArray = []
const loader = new SVGLoader();
loader.load(url, (data) => {
if (!this.sdk || !this.sdk.viewer || !this.sdk.viewer.entities) {
return
}
data.xml.style.width = '0'
data.xml.style.height = '0'
document.body.appendChild(data.xml)
for (const path of data.paths) {
const fillColor = path.userData.style.fill;
let style = window.getComputedStyle(path.userData.node)
if (style.strokeWidth) {
path.userData.style.strokeWidth = Number(style.strokeWidth.replace(/[a-zA-Z]/g, ''))
}
if (fillColor !== undefined && fillColor !== 'none') {
const shapes = SVGLoader.createShapes(path);
for (const shape of shapes) {
const geometry = new THREE.ShapeGeometry(shape);
const mesh = new THREE.Mesh(geometry);
geometryArray.push({
geometry: mesh.geometry,
color: fillColor
})
}
}
const strokeColor = path.userData.style.stroke;
if (strokeColor !== undefined && strokeColor !== 'none') {
for (const subPath of path.subPaths) {
const geometry = SVGLoader.pointsToStroke(subPath.getPoints(), path.userData.style);
if (geometry) {
const mesh = new THREE.Mesh(geometry);
geometryArray.push({
geometry: mesh.geometry,
color: strokeColor
})
}
}
}
}
document.body.removeChild(data.xml)
let min = 0
let max = 0
let geojson
for (let key = 0; key < geometryArray.length; key++) {
let geometry = geometryArray[key].geometry;
if (!geometry || !geometry.attributes || !geometry.attributes.position) {
continue
}
let array = geometry.attributes.position.array
for (let i = 0; i < array.length; i++) {
if (min > array[i]) {
min = array[i]
}
if (max < array[i]) {
max = array[i]
}
}
}
min = Math.abs(min)
max = Math.abs(max)
if (min > max) {
max = min
}
let max2 = max
max = max * (10 / 3) * 100
let scale = (4000 / max) / 5
max2 = max2 * scale
for (let key = 0; key < geometryArray.length; key++) {
geometryArray[key].geometry.scale(scale, scale, 1)
geometryArray[key].geometry.rotateX(THREE.MathUtils.degToRad(180))
}
let jsCode = `
let geometryArray = e.data.options.geometryArray
let max2 = e.data.options.max2
for (let key = 0; key < geometryArray.length; key++) {
let feature
let positions = []
let position = []
let geometry = geometryArray[key].geometry;
let array = geometry.attributes.position.array
for (let i = 0; i < array.length; i += 3) {
let x = array[i] - (max2 / 2)
let y = array[i + 1] + (max2 / 2)
position.push([x, y, array[i + 1]])
}
if (geometry.index && geometry.index.array) {
let index = geometry.index.array
for (let i = 0; i < index.length; i += 3) {
positions.push([position[index[i]], position[index[i + 1]], position[index[i + 2]]])
}
}
else {
for (let i = 0; i < position.length; i += 3) {
positions.push([position[i], position[i + 1], position[i + 2]])
}
}
let polygons = []
// 组合多边形
for (let i = 0; i < positions.length; i++) {
let polygon = turf.polygon([[
...positions[i],
positions[i][0]
]]);
polygons.push(polygon)
if (feature) {
feature = turf.union(feature, polygon);
}
else {
feature = polygon
}
}
feature.properties.color = geometryArray[key].color
features.push(feature)
}
`
this._worker.postMessage({ code: jsCode, options: { geometryArray: geometryArray, max2: max2 } });
this._worker.onmessage = (event) => {
if (!this.sdk || !this.sdk.viewer || !this.sdk.viewer.entities) {
return
}
let features = event.data
geojson = turf.featureCollection(features)
this.geojson = JSON.parse(JSON.stringify(geojson))
// 计算边界框
let bbox = turf.bbox(geojson);
let width = Math.abs(bbox[2] - bbox[0])
let height = Math.abs(bbox[3] - bbox[1])
// 获取最小正方形
let square = turf.square(bbox);
// 控制点界限
square[0] = square[0] + this.options.position.lng - (width / 5)
square[1] = square[1] + this.options.position.lat - (height / 5)
square[2] = square[2] + this.options.position.lng + (width / 5)
square[3] = square[3] + this.options.position.lat + (height / 5)
this.bbox = square
this.geojson.features.forEach(item => {
let array = []
let geojson = JSON.parse(JSON.stringify(item))
geojson.properties.directionDistance = []
if (geojson.geometry.type === 'MultiPolygon') {
for (let i = 0; i < geojson.geometry.coordinates.length; i++) {
let array = []
for (let m = 0; m < geojson.geometry.coordinates[i].length; m++) {
let array2 = []
for (let n = 0; n < geojson.geometry.coordinates[i][m].length; n++) {
let point1 = turf.point([0, geojson.geometry.coordinates[i][m][n][1]])
let point2 = turf.point([...geojson.geometry.coordinates[i][m][n]])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle = turf.rhumbBearing(point1, point2);
array2.push(
{
origin: geojson.geometry.coordinates[i][m][n],
distance: distance,
angle: angle
}
)
}
array.push(array2)
}
geojson.properties.directionDistance.push(array)
}
}
else {
for (let i = 0; i < geojson.geometry.coordinates.length; i++) {
let array = []
for (let m = 0; m < geojson.geometry.coordinates[i].length; m++) {
let point1 = turf.point([0, geojson.geometry.coordinates[i][m][1]])
let point2 = turf.point([...geojson.geometry.coordinates[i][m]])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle = turf.rhumbBearing(point1, point2);
array.push(
{
origin: geojson.geometry.coordinates[i][m],
distance: distance,
angle: angle
}
)
}
geojson.properties.directionDistance.push(array)
}
}
if (geojson.geometry.type === 'MultiPolygon') {
for (let i = 0; i < geojson.geometry.coordinates.length; i++) {
let hierarchy = this.getHierarchyPolygon(geojson, i)
array.push(hierarchy)
}
}
else {
let hierarchy = this.getHierarchyPolygon(geojson)
array.push(hierarchy)
}
this.hierarchys.push(array)
});
this.entity = new Cesium.EntityCollection()
syncSplitData(this.sdk, this.options.id)
let perPositionHeight = false
if (this.sdk.viewer._element.className === 'cesium-viewer 2d') {
perPositionHeight = true
}
for (let i = 0; i < this.hierarchys.length; i++) {
for (let m = 0; m < this.hierarchys[i].length; m++) {
let id = this.options.id + `-${i}_${m}}`
let oldEntity = this.sdk.viewer.entities.getById(id)
if(oldEntity) {
this.sdk.viewer.entities.remove(oldEntity)
}
let entity = this.sdk.viewer.entities.add({
id: this.options.id + `-${i}_${m}}`,
show: this.options.show,
polygon: {
hierarchy: new Cesium.CallbackProperty(() => {
let hierarchy = this.hierarchys[i][m]
let holes = []
for (let n = 0; n < hierarchy.holes.length; n++) {
holes.push({
positions: hierarchy.holes[n]
})
}
return {
positions: hierarchy.positions,
holes: holes
}
}, true),
perPositionHeight: perPositionHeight,
zIndex: this.sdk._entityZIndex,
material: new Cesium.CustomColorMaterialSource({
color: this.options.color || this.geojson.features[i].properties.color
})
},
properties: {
id: this.options.id
}
})
this.sdk._entityZIndex++
if (this.geojson.features[i].properties.color) {
entity.properties = {
id: this.options.id,
color: this.geojson.features[i].properties.color
}
}
this._entityArray.push(entity)
this.entity.add(entity)
}
}
this.loaded = true
this.#loaded = true
if (this.#loadEvent) {
this.#loadEvent()
}
this.scale = this.scale
GroundSvg.createText(this)
// GroundSvg.initText(this)
}
})
}
static async createText(that) {
if (that.options.text.position) {
let height
if (that.options.text.position.alt) {
height = that.options.text.position.alt
}
else {
height = await that.getClampToHeight({ lng: that.options.text.position.lng, lat: that.options.text.position.lat })
}
that.text = new LabelObject(that.sdk, {
id: that.options.id,
show: that.options.show ? (that.options.text.show ? that.options.text.show : false) : false,
position: [that.options.text.position.lng, that.options.text.position.lat, height],
text: that.options.text.value,
fontSize: that.options.text.fontSize,
color: that.options.text.color,
pixelOffset: that.options.text.fontSize,
backgroundColor: that.options.text.backgroundColor,
lineColor: '#ffffff00',
lineWidth: 0,
scaleByDistance: that.options.text.scaleByDistance,
backgroundColor: ['#ffffff00', '#ffffff00'],
near: that.options.text.near,
far: that.options.text.far,
})
that.text.entity.billboard.verticalOrigin = Cesium.VerticalOrigin.CENTER
// that.text.entity.billboard.horizontalOrigin = Cesium.HorizontalOrigin.LEFT
}
}
/**
* 编辑框
* @param {boolean} status=false 状态
*/
async edit(state) {
if (!this.#loaded) {
return
}
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.text && (this.options.text.position = { lng: this.text.position[0], lat: this.text.position[1], alt: this.text.position[2] })
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
let cdoptions = this.deepCopyObj(this.options)
cdoptions.host = ''
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(cdoptions)
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
},
resetCallBack: () => {
this.reset()
this.Dialog.resetCallBack && this.Dialog.resetCallBack()
},
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
closeCallBack: () => {
this._DialogObject = null
this.drag(false)
this.reset()
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
addFootElm: [
{
tagName: 'button',
className: 'flipe-over-y',
innerHTML: 'Y轴翻转',
event: [
'click',
() => {
this.flipeY = !this.flipeY
}
]
},
{
tagName: 'button',
className: 'flipe-over-x',
innerHTML: 'X轴翻转',
event: [
'click',
() => {
this.flipeX = !this.flipeX
}
]
},
{
tagName: 'button',
className: 'drag',
innerHTML: '编辑',
event: [
'click',
() => {
this.drag(!this._isdrag)
}
]
}
]
}, true)
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' ground-svg'
let contentElm = document.createElement('div');
contentElm.innerHTML = html(this)
await this._DialogObject.contentAppChild(contentElm)
this.attributeType = this.options.attributeType
// 颜色组件
let colorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.color || undefined,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.color = color
},//点击确认按钮事件回调
clear: () => {
this.color = ''
},//点击清空按钮事件回调
})
let textColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("textColor")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.textColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.textColor = color
},//点击确认按钮事件回调
clear: () => {
this.textColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let all_elm = contentElm.getElementsByTagName("*")
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
this._elms.color = [colorPicker]
this._elms.textColor = [textColorPicker]
setTimeout(async () => {
if (this.sdk && this.sdk.tabHide && Array.isArray(this.sdk.tabHide)) {
for (let m = 0; m < this.sdk.tabHide.length; m++) {
if (this.sdk.tabHide[m] === '属性信息') {
contentElm.getElementsByClassName('attribute-info')[0].style.display = 'none'
break
}
}
}
this.attributeLink = this.options.attribute.link.content
let tagData = this.attributeSelect
let attributeElm = this._DialogObject._element.content.getElementsByClassName(
'attribute-select-box'
)[0]
if (attributeElm) {
let legpObject = legp(attributeElm, '.attribute-select')
legpObject.legp_search(tagData)
let attributeSelectElm = this._DialogObject._element.content
.getElementsByClassName('attribute-select')[0]
.getElementsByTagName('input')[0]
for (let i = 0; i < tagData.length; i++) {
if (tagData[i].key === this.options.attributeType) {
attributeSelectElm.value = tagData[i].value
legpObject.legp_searchActive(tagData[i].value)
break
}
}
attributeSelectElm.addEventListener('input', () => {
for (let i = 0; i < tagData.length; i++) {
if (tagData[i].value === attributeSelectElm.value) {
this.attributeType = tagData[i].key
break
}
}
})
}
}, 0)
let xElm = contentElm.getElementsByClassName('x-scale')[0]
let yElm = contentElm.getElementsByClassName('y-scale')[0]
let xRange = xElm.getElementsByTagName('input')[0]
let xInput = xElm.getElementsByTagName('input')[1]
let yRange = yElm.getElementsByTagName('input')[0]
let yInput = yElm.getElementsByTagName('input')[1]
xRange.value = this.scale.x
xInput.value = this.scale.x
yRange.value = this.scale.y
yInput.value = this.scale.y
this._elms.xRange = xRange
this._elms.yRange = yRange
this._elms.xInput = xInput
this._elms.yInput = yInput
xRange.addEventListener('input', (e) => {
this.scale = {
x: xRange.value,
y: this.scale.y
}
})
yRange.addEventListener('input', (e) => {
this.scale = {
x: this.scale.x,
y: yRange.value
}
})
xInput.addEventListener('input', (e) => {
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))) {
this.scale = {
x: value,
y: this.scale.y
}
}
}
})
xInput.addEventListener('blur', (e) => {
let value = e.target.value
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)
}
this.scale = {
x: value,
y: this.scale.y
}
})
yInput.addEventListener('input', (e) => {
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))) {
this.scale = {
x: this.scale.x,
y: value
}
}
}
})
yInput.addEventListener('blur', (e) => {
let value = e.target.value
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)
}
this.scale = {
x: this.scale.x,
y: value
}
})
}
}
/**
* 重置
*/
reset() {
if (!this.#loaded) {
return
}
this.options = this.deepCopyObj(this.originalOptions)
this.position = this.originalOptions.position
this.name = this.originalOptions.name
this.angle = this.originalOptions.angle
this.scale = this.originalOptions.scale
this.color = this.originalOptions.color
if (this.text && !this.originalOptions.text.position) {
this.text.remove()
this.text = null
}
this.attributeLink = this.options.attribute.link.content
this.textShow = this.originalOptions.text.show
this.textValue = this.originalOptions.text.value
this.textColor = this.originalOptions.text.color
this.textFontSize = this.originalOptions.text.fontSize
this.textScaleByDistance = this.originalOptions.text.scaleByDistance
this.textNear = this.originalOptions.text.near
this.textFar = this.originalOptions.text.far
}
/**
* 拖动
* @param {boolean} status=false 状态
*/
drag(status, cd) {
if (!this.#loaded || !this.sdk || !this.sdk.viewer) {
return
}
this.ismove = false
this._isdrag = status
if (this.ScreenSpaceEventHandler) {
this.ScreenSpaceEventHandler.destroy()
this.ScreenSpaceEventHandler = null
}
if (status) {
this.ScreenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(
this.sdk.viewer.canvas
)
let width = Math.abs(this.bbox[0] - this.bbox[2])
let height = Math.abs(this.bbox[1] - this.bbox[3])
this.ScreenSpaceEventHandler.setInputAction(async (movement) => {
if (this.pickPoint) {
let sCartesian = this.pickPoint.position.getValue()
let eCartesian = this.sdk.viewer.scene.pickPosition(movement.endPosition)
if (!eCartesian) {
const ray = this.sdk.viewer.camera.getPickRay(movement.endPosition);
eCartesian = this.sdk.viewer.scene.globe.pick(ray, this.sdk.viewer.scene);
}
if (!sCartesian || !eCartesian) {
return
}
let position1 = this.cartesian3Towgs84(sCartesian, this.sdk.viewer)
let position2 = this.cartesian3Towgs84(eCartesian, this.sdk.viewer)
let x = 0
let y = 0
let radians, radiansW, radiansH
let w = 3.5 * this.scale.x
let h = 3.5 * this.scale.y
let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2))
let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI)
let angleW, angleH;
if (isNaN(angle)) {
angle = 0
}
let point = turf.point([this.position.lng, this.position.lat]);
let options = { units: 'kilometers' };
let controlPoints = []
controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0 + this.options.angle, options).geometry.coordinates
controlPoints[1] = turf.destination(point, wh, 180 + angle + this.options.angle, options).geometry.coordinates
controlPoints[2] = turf.destination(point, h / 2, 180 + this.options.angle, options).geometry.coordinates
controlPoints[3] = turf.destination(point, wh, 180 - angle + this.options.angle, options).geometry.coordinates
controlPoints[4] = turf.destination(point, w / 2, 270 + this.options.angle, options).geometry.coordinates
controlPoints[5] = [this.position.lng, this.position.lat]
controlPoints[6] = turf.destination(point, w / 2, 90 + this.options.angle, options).geometry.coordinates
controlPoints[7] = turf.destination(point, wh, 360 - angle + this.options.angle, options).geometry.coordinates
controlPoints[8] = turf.destination(point, h / 2, 0 + this.options.angle, options).geometry.coordinates
controlPoints[9] = turf.destination(point, wh, 0 + angle + this.options.angle, options).geometry.coordinates
let point1 = turf.point([position1.lng, position1.lat]);
let point2 = turf.point([position2.lng, position2.lat]);
let pointC = turf.point([this.position.lng, this.position.lat]);
let bearing1 = turf.rhumbBearing(pointC, point1);
let bearing2_0 = turf.rhumbBearing(pointC, point2);
let bearing2 = (((bearing2_0 + 360) - this.angle) % 360)
let bearingH
let bearingW
// 中心点到鼠标的距离
let distance = turf.rhumbDistance(pointC, point2, options);
let flag = false
let flag2 = false
switch (this.pickPoint.id) {
case 'svg-control-points_0':
angle = bearing2_0 - bearing1
this.angle += angle
break
case 'svg-control-points_1':
case 'svg-control-points_7':
bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[4])) + 360) - this.angle) % 360)
bearingH = (((turf.rhumbBearing(pointC, turf.point(controlPoints[2])) + 360) - this.angle) % 360)
angleW = bearing2 - bearingW
angleH = bearing2 - bearingH
if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) {
angleW = angleW + 180
flag=true
}
if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) {
angleH = angleH + 180
flag2=true
}
if(flag && flag2) {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
else {
if(flag) {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
else if(flag2) {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
else {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
}
radiansW = (Math.PI / 180) * angleW
radiansH = (Math.PI / 180) * angleH
// 矩形高度
w = (Math.cos(radiansW) * distance) * 2
h = (Math.cos(radiansH) * distance) * 2
// scaleY值
this.scale.x = Math.abs(w) / 3.5
this.scale.y = Math.abs(h) / 3.5
break
case 'svg-control-points_2':
case 'svg-control-points_8':
bearingH = (((turf.rhumbBearing(pointC, turf.point(controlPoints[2])) + 360) - this.angle) % 360)
angleH = bearing2 - bearingH
if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) {
angleH = angleH + 180
this.pointEntityCollection.values[2].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[8].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
else {
this.pointEntityCollection.values[2].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[8].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
radiansH = (Math.PI / 180) * angleH
// 矩形高度
h = (Math.cos(radiansH) * distance) * 2
// scaleY值
this.scale.y = h / 3.5
break
case 'svg-control-points_3':
case 'svg-control-points_9':
bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[6])) + 360) - this.angle) % 360)
bearingH = (((turf.rhumbBearing(pointC, turf.point(controlPoints[2])) + 360) - this.angle) % 360)
angleW = bearing2 - bearingW
angleH = bearing2 - bearingH
if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) {
angleW = angleW + 180
flag=true
}
if ((angleH > -360 && angleH < -90) || (angleH < 360 && angleH > 90)) {
angleH = angleH + 180
flag2=true
}
if(flag && flag2) {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
else {
if(flag) {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
else if(flag2) {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
else {
this.pointEntityCollection.values[1].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[3].point.color = Cesium.Color.fromCssColorString('#ff0000')
this.pointEntityCollection.values[7].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[9].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
}
radiansW = (Math.PI / 180) * angleW
radiansH = (Math.PI / 180) * angleH
// 矩形高度
w = (Math.cos(radiansW) * distance) * 2
h = (Math.cos(radiansH) * distance) * 2
// scaleY值
this.scale.x = Math.abs(w) / 3.5
this.scale.y = Math.abs(h) / 3.5
break
case 'svg-control-points_4':
bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[4])) + 360) - this.angle) % 360)
angleW = bearing2 - bearingW
if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) {
angleW = angleW + 180
this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
else {
this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
radiansW = (Math.PI / 180) * angleW
// 矩形宽度
w = (Math.cos(radiansW) * distance) * 2
// scaleY值
this.scale.x = w / 3.5
break
case 'svg-control-points_5':
if (position2.lat > 83.5) {
position2.lat = 83.5
}
if (position2.lat < -83.5) {
position2.lat = -83.5
}
this.position = { lng: position2.lng, lat: position2.lat }
let cx = position2.lng - position1.lng
let cy = position2.lat - position1.lat
this.bbox[0] = this.bbox[0] + cx
this.bbox[1] = this.bbox[1] + cy
this.bbox[2] = this.bbox[2] + cx
this.bbox[3] = this.bbox[3] + cy
break
case 'svg-control-points_6':
bearingW = (((turf.rhumbBearing(pointC, turf.point(controlPoints[6])) + 360) - this.angle) % 360)
angleW = bearing2 - bearingW
if ((angleW > -360 && angleW < -90) || (angleW < 360 && angleW > 90)) {
angleW = angleW + 180
this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
else {
this.pointEntityCollection.values[4].point.color = Cesium.Color.fromCssColorString('#00ff0a')
this.pointEntityCollection.values[6].point.color = Cesium.Color.fromCssColorString('#ff0000')
}
radiansW = (Math.PI / 180) * angleW
// 矩形高度
w = (Math.cos(radiansW) * distance) * 2
this.scale.x = w / 3.5
break
default:
}
// let radians = (Math.PI / 180) * this.options.angle
// x = x*Math.cos(radians)
// y = y*Math.cos(radians)
// let bbox = turf.bbox(geojson);
// let square = turf.square(bbox);
x = x / (width / 2) * 100
y = y / (height / 2) * 100
let scale = { ...this.scale }
scale.x = scale.x + x
scale.y = scale.y - y
// let pt = turf.point(this.center);
// let destination1 = turf.rhumbDestination(pt, 220, 45, { units: 'kilometers' });
// let destination2 = turf.rhumbDestination(pt, 220, 225, { units: 'kilometers' });
// width = Math.abs(destination2.geometry.coordinates[0] - destination1.geometry.coordinates[0])
// height = Math.abs(destination2.geometry.coordinates[1] - destination1.geometry.coordinates[1])
if (scale.y > 200) {
scale.y = 200
}
if (scale.y < 0.001) {
scale.y = 0.001
}
if (scale.x > 200) {
scale.x = 200
}
if (scale.x < 0.001) {
scale.x = 0.001
}
this.scale = { ...scale }
}
else {
let pickedObjectArray = this.sdk.viewer.scene.drillPick(movement.endPosition);
let pickPoint
for (let i = 0; i < pickedObjectArray.length; i++) {
let pickedObject = pickedObjectArray[i]
if (pickedObject && pickedObject.primitive && pickedObject.primitive._id &&
(pickedObject.primitive._id.id && pickedObject.primitive._id.id.indexOf('svg-control-points_') !== -1)
) {
pickPoint = pickedObject.primitive._id
break
}
}
for (let i = 0; i < this.pointEntityCollection.values.length; i++) {
if (pickPoint && this.pointEntityCollection.values[i].id === pickPoint.id) {
pickPoint.point.color = Cesium.Color.fromCssColorString('#ffff00')
}
else {
switch (this.pointEntityCollection.values[i].id) {
case 'svg-control-points_5':
this.pointEntityCollection.values[i].point.color = Cesium.Color.fromCssColorString('#ffff00')
break
case 'svg-control-points_0':
this.pointEntityCollection.values[i].point.color = Cesium.Color.fromCssColorString('#ff0000')
break
default:
this.pointEntityCollection.values[i].point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
}
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
this.ScreenSpaceEventHandler.setInputAction((movement) => {
let pickedObjectArray = this.sdk.viewer.scene.drillPick(movement.position);
for (let i = 0; i < pickedObjectArray.length; i++) {
let pickedObject = pickedObjectArray[i]
if (pickedObject && pickedObject.primitive && pickedObject.primitive._id && pickedObject.primitive._id.objectId === this.options.id &&
(pickedObject.primitive._id.id && pickedObject.primitive._id.id.indexOf('svg-control-points_') !== -1)
) {
YJ.Global.CameraController(this.sdk, false)
this.pickPoint = pickedObject.primitive._id
this.pickPoint.point.color = Cesium.Color.fromCssColorString('#ff0000')
break
}
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN)
this.ScreenSpaceEventHandler.setInputAction((movement) => {
if (this.pickPoint) {
YJ.Global.CameraController(this.sdk, true)
switch (this.pickPoint.id) {
case 'svg-control-points_4':
this.pickPoint.point.color = Cesium.Color.fromCssColorString('#ffff00')
break
case 'svg-control-points_9':
this.pickPoint.point.color = Cesium.Color.fromCssColorString('#ff0000')
break
default:
this.pickPoint.point.color = Cesium.Color.fromCssColorString('#00ff0a')
}
this.pickPoint = null
}
}, Cesium.ScreenSpaceEventType.LEFT_UP)
this.ScreenSpaceEventHandler.setInputAction((movement) => {
this.drag(false)
if (!this._DialogObject) {
cd && cd(this.options)
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
}
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
this.pointEntityCollection = new Cesium.EntityCollection()
let w = 3.5 * this.scale.x
let h = 3.5 * this.scale.y
let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2))
let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI)
if (isNaN(angle)) {
angle = 0
}
let point = turf.point([this.position.lng, this.position.lat]);
let options = { units: 'kilometers' };
let controlPoints = []
controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0, options).geometry.coordinates
controlPoints[1] = turf.destination(point, wh, 180 + angle, options).geometry.coordinates
controlPoints[2] = turf.destination(point, h / 2, 180, options).geometry.coordinates
controlPoints[3] = turf.destination(point, wh, 180 - angle, options).geometry.coordinates
controlPoints[4] = turf.destination(point, w / 2, 270, options).geometry.coordinates
controlPoints[5] = [this.position.lng, this.position.lat]
controlPoints[6] = turf.destination(point, w / 2, 90, options).geometry.coordinates
controlPoints[7] = turf.destination(point, wh, 360 - angle, options).geometry.coordinates
controlPoints[8] = turf.destination(point, h / 2, 0, options).geometry.coordinates
controlPoints[9] = turf.destination(point, wh, 0 + angle, options).geometry.coordinates
this.controlPoints = controlPoints
if(!this.sdk || !this.sdk.viewer) {
return
}
for (let i = 0; i < this.controlPoints.length; i++) {
let color = '#00ff0a'
if (i === 5) {
color = '#ffff00'
}
if (i === 0) {
color = '#ff0000'
}
let entity = this.sdk.viewer.entities.getOrCreateEntity('svg-control-points_' + i)
entity.show = true
entity.objectId = this.options.id
entity.position = new Cesium.CallbackProperty(() => {
return Cesium.Cartesian3.fromDegrees(...this.controlPoints[i])
})
entity.point = new Cesium.PointGraphics({
color: Cesium.Color.fromCssColorString(color), // 点的颜色
pixelSize: 10, // 点的大小
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
scaleByDistance: new Cesium.NearFarScalar(0.0, 1.0, 1.0e10, 1.0),
disableDepthTestDistance: Number.POSITIVE_INFINITY // 不应用深度测试
})
this.pointEntityCollection.add(entity)
}
this._update()
}
else {
for (let i = 0; i < this.controlPoints.length; i++) {
let entity = this.sdk.viewer.entities.getById('svg-control-points_' + i)
if (entity && (entity.objectId === this.options.id)) {
entity.show = false
}
}
}
}
getHierarchyPolygon(geojson, key) {
if (!geojson) {
return
}
let hierarchy = {}
let holes = []
let directionDistance = geojson.properties.directionDistance
if (key !== undefined) {
directionDistance = geojson.properties.directionDistance[key]
}
for (let i = 0; i < directionDistance.length; i++) {
let positions = []
for (let m = 0; m < directionDistance[i].length; m++) {
let lng = this.options.position.lng
let lat = directionDistance[i][m].origin[1] + this.options.position.lat
if (lat > 90) {
lng += 180
}
let origin = [lng, lat]
let pt = turf.point(origin);
let destination = turf.rhumbDestination(pt, directionDistance[i][m].distance, directionDistance[i][m].angle, { units: 'kilometers' });
let coordinates = [...destination.geometry.coordinates]
// 二维模式下设置高度
coordinates[2] = 10
positions.push(Cesium.Cartesian3.fromDegrees(...coordinates))
}
if (i === 0) {
hierarchy.positions = positions
}
else {
holes.push(positions)
}
}
hierarchy.holes = holes
return hierarchy
}
_updateGeojson(data, x, y) {
if (!this.#loaded) {
return
}
let width = Math.abs(this.bbox[0] - this.bbox[2])
let height = Math.abs(this.bbox[1] - this.bbox[3])
if (typeof data[0] === 'object') {
for (let i = 0; i < data.length; i++) {
this._updateGeojson(data[i], x, y)
}
}
else {
for (let i = 0; i < data.length; i += 2) {
data[i] = data[i] + ((data[i] / (width / 2)) * x)
}
for (let i = 1; i < data.length; i += 2) {
data[i] = data[i] - ((data[i] / (height / 2)) * y)
}
}
}
_update() {
if (!this.#loaded) {
return
}
let point = turf.point([this.position.lng, this.position.lat]);
let options = { units: 'kilometers' };
let interimBbox = [...this.bbox]
let width = Math.abs(interimBbox[2] - interimBbox[0])
let height = Math.abs(interimBbox[3] - interimBbox[1])
let x = ((width / 2) * this.options.scale.x) / 100 - (width / 2)
let y = (height / 2) * (-(this.options.scale.y)) / 100 + (height / 2)
interimBbox[0] = interimBbox[0] - x
interimBbox[1] = interimBbox[1] + y
interimBbox[2] = interimBbox[2] + x
interimBbox[3] = interimBbox[3] - y
let interim
if (interimBbox[0] > interimBbox[2]) {
interim = interimBbox[0]
interimBbox[0] = interimBbox[2]
interimBbox[2] = interim
}
if (interimBbox[1] > interimBbox[3]) {
interim = interimBbox[1]
interimBbox[1] = interimBbox[3]
interimBbox[3] = interim
}
let hierarchys = []
let geojson = JSON.parse(JSON.stringify(this.geojson))
const recursion = (data) => {
for (let i = 0; i < data.length; i++) {
if (typeof data[i] === 'number') {
if (this.options.flipe.x && i === 1) {
data[i] = -data[i]
}
if (this.options.flipe.y && i === 0) {
data[i] = -data[i]
}
}
else {
recursion(data[i])
}
}
}
for (let i = 0; i < geojson.features.length; i++) {
recursion(geojson.features[i].geometry.coordinates)
}
geojson.features.forEach(item => {
let array = []
let feature = JSON.parse(JSON.stringify(item))
this._updateGeojson(feature.geometry.coordinates, x, y)
feature = turf.transformRotate(feature, this.angle, { pivot: [0, 0] });
let directionDistance = []
if (feature.geometry.type === 'MultiPolygon') {
for (let i = 0; i < feature.geometry.coordinates.length; i++) {
let array = []
for (let m = 0; m < feature.geometry.coordinates[i].length; m++) {
let array2 = []
for (let n = 0; n < feature.geometry.coordinates[i][m].length; n++) {
let point1 = turf.point([0, feature.geometry.coordinates[i][m][n][1]])
let point2 = turf.point([...feature.geometry.coordinates[i][m][n]])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle2 = turf.rhumbBearing(point1, point2);
array2.push(
{
origin: feature.geometry.coordinates[i][m][n],
distance: distance,
angle: angle2
}
)
}
array.push(array2)
}
directionDistance.push(array)
}
}
else {
for (let i = 0; i < feature.geometry.coordinates.length; i++) {
let array = []
for (let m = 0; m < feature.geometry.coordinates[i].length; m++) {
let array2 = []
let point1 = turf.point([0, feature.geometry.coordinates[i][m][1]])
let point2 = turf.point([...feature.geometry.coordinates[i][m]])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle2 = turf.rhumbBearing(point1, point2);
array.push({
origin: feature.geometry.coordinates[i][m],
distance: distance,
angle: angle2
})
}
directionDistance.push(array)
}
}
feature.properties.directionDistance = directionDistance
// this.bbox = [...interimBbox]
let w = 3.5 * this.scale.x
let h = 3.5 * this.scale.y
let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2))
let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI)
if (isNaN(angle)) {
angle = 0
}
let controlPoints = []
controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0 + this.options.angle, options).geometry.coordinates
controlPoints[1] = turf.destination(point, wh, 180 + angle + this.options.angle, options).geometry.coordinates
controlPoints[2] = turf.destination(point, h / 2, 180 + this.options.angle, options).geometry.coordinates
controlPoints[3] = turf.destination(point, wh, 180 - angle + this.options.angle, options).geometry.coordinates
controlPoints[4] = turf.destination(point, w / 2, 270 + this.options.angle, options).geometry.coordinates
controlPoints[5] = [this.position.lng, this.position.lat]
controlPoints[6] = turf.destination(point, w / 2, 90 + this.options.angle, options).geometry.coordinates
controlPoints[7] = turf.destination(point, wh, 360 - angle + this.options.angle, options).geometry.coordinates
controlPoints[8] = turf.destination(point, h / 2, 0 + this.options.angle, options).geometry.coordinates
controlPoints[9] = turf.destination(point, wh, 0 + angle + this.options.angle, options).geometry.coordinates
let points = turf.points(controlPoints);
controlPoints = []
for (let i = 0; i < points.features.length; i++) {
controlPoints.push(points.features[i].geometry.coordinates)
}
this.controlPoints = controlPoints
if (feature.geometry.type === 'MultiPolygon') {
for (let i = 0; i < feature.geometry.coordinates.length; i++) {
let hierarchy = this.getHierarchyPolygon(feature, i)
array.push(hierarchy)
}
}
else {
let hierarchy = this.getHierarchyPolygon(feature)
array.push(hierarchy)
}
hierarchys.push(array)
})
this.hierarchys = [...hierarchys]
if (!this.entity) {
return
}
if (this._DialogObject || this._isdrag) {
let k = 0
for (let i = 0; i < this.hierarchys.length; i++) {
for (let m = 0; m < this.hierarchys[i].length; m++) {
if (this.entity.values[k].polygon.hierarchy.isConstant) {
this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => {
let hierarchy = this.hierarchys[i][m]
let holes = []
for (let n = 0; n < hierarchy.holes.length; n++) {
holes.push({
positions: hierarchy.holes[n]
})
}
return {
positions: hierarchy.positions,
holes: holes
}
}, false)
}
k++
}
}
}
else {
let k = 0
for (let i = 0; i < this.hierarchys.length; i++) {
for (let m = 0; m < this.hierarchys[i].length; m++) {
// if (!this.entity.values[k].polygon.hierarchy.isConstant) {
this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => {
let hierarchy = this.hierarchys[i][m]
let holes = []
for (let n = 0; n < hierarchy.holes.length; n++) {
holes.push({
positions: hierarchy.holes[n]
})
}
return {
positions: hierarchy.positions,
holes: holes
}
}, !this.ismove)
// }
k++
}
}
}
if (this.textObject && this.textObject.geojson) {
let textHierarchys = []
let textGeojson = JSON.parse(JSON.stringify(this.textObject.geojson))
const recursion2 = (data) => {
for (let i = 0; i < data.length; i++) {
if (typeof data[i] === 'number') {
if (this.textObject.flipe.x && i === 1) {
data[i] = -data[i]
}
if (this.textObject.flipe.y && i === 0) {
data[i] = -data[i]
}
}
else {
recursion2(data[i])
}
}
}
for (let i = 0; i < textGeojson.features.length; i++) {
recursion(textGeojson.features[i].geometry.coordinates)
}
textGeojson.features.forEach(item => {
let array = []
let feature = JSON.parse(JSON.stringify(item))
this._updateGeojson(feature.geometry.coordinates, x, y)
feature = turf.transformRotate(feature, this.angle, { pivot: [0, 0] });
let directionDistance = []
if (feature.geometry.type === 'MultiPolygon') {
for (let i = 0; i < feature.geometry.coordinates.length; i++) {
let array = []
for (let m = 0; m < feature.geometry.coordinates[i].length; m++) {
let array2 = []
for (let n = 0; n < feature.geometry.coordinates[i][m].length; n++) {
let point1 = turf.point([0, feature.geometry.coordinates[i][m][n][1]])
let point2 = turf.point([...feature.geometry.coordinates[i][m][n]])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle2 = turf.rhumbBearing(point1, point2);
array2.push(
{
origin: feature.geometry.coordinates[i][m][n],
distance: distance,
angle: angle2
}
)
}
array.push(array2)
}
directionDistance.push(array)
}
}
else {
for (let i = 0; i < feature.geometry.coordinates.length; i++) {
let array = []
for (let m = 0; m < feature.geometry.coordinates[i].length; m++) {
let array2 = []
let point1 = turf.point([0, feature.geometry.coordinates[i][m][1]])
let point2 = turf.point([...feature.geometry.coordinates[i][m]])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle2 = turf.rhumbBearing(point1, point2);
array.push({
origin: feature.geometry.coordinates[i][m],
distance: distance,
angle: angle2
})
}
directionDistance.push(array)
}
}
feature.properties.directionDistance = directionDistance
// this.bbox = [...interimBbox]
let w = 3.5 * this.scale.x
let h = 3.5 * this.scale.y
let wh = Math.sqrt(((w / 2) ** 2) + ((h / 2) ** 2))
let angle = Math.atan((w / 2) / (h / 2)) * (180 / Math.PI)
if (isNaN(angle)) {
angle = 0
}
let controlPoints = []
controlPoints[0] = turf.destination(point, h / 2 * 1.5, 0 + this.options.angle, options).geometry.coordinates
controlPoints[1] = turf.destination(point, wh, 180 + angle + this.options.angle, options).geometry.coordinates
controlPoints[2] = turf.destination(point, h / 2, 180 + this.options.angle, options).geometry.coordinates
controlPoints[3] = turf.destination(point, wh, 180 - angle + this.options.angle, options).geometry.coordinates
controlPoints[4] = turf.destination(point, w / 2, 270 + this.options.angle, options).geometry.coordinates
controlPoints[5] = [this.position.lng, this.position.lat]
controlPoints[6] = turf.destination(point, w / 2, 90 + this.options.angle, options).geometry.coordinates
controlPoints[7] = turf.destination(point, wh, 360 - angle + this.options.angle, options).geometry.coordinates
controlPoints[8] = turf.destination(point, h / 2, 0 + this.options.angle, options).geometry.coordinates
controlPoints[9] = turf.destination(point, wh, 0 + angle + this.options.angle, options).geometry.coordinates
let points = turf.points(controlPoints);
controlPoints = []
for (let i = 0; i < points.features.length; i++) {
controlPoints.push(points.features[i].geometry.coordinates)
}
this.controlPoints = controlPoints
if (feature.geometry.type === 'MultiPolygon') {
for (let i = 0; i < feature.geometry.coordinates.length; i++) {
let hierarchy = this.getHierarchyPolygon(feature, i)
array.push(hierarchy)
}
}
else {
let hierarchy = this.getHierarchyPolygon(feature)
array.push(hierarchy)
}
textHierarchys.push(array)
})
this.textObject.hierarchys = [...textHierarchys]
// if (this._DialogObject || this._isdrag) {
// let k = 0
// for (let i = 0; i < this.textObject.hierarchys.length; i++) {
// for (let m = 0; m < this.textObject.hierarchys[i].length; m++) {
// if (this.entity.values[k].polygon.hierarchy.isConstant) {
// this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => {
// let hierarchy = this.textObject.hierarchys[i][m]
// let holes = []
// for (let n = 0; n < hierarchy.holes.length; n++) {
// holes.push({
// positions: hierarchy.holes[n]
// })
// }
// return {
// positions: hierarchy.positions,
// holes: holes
// }
// }, false)
// }
// k++
// }
// }
// }
// else {
// let k = 0
// for (let i = 0; i < this.textObject.hierarchys.length; i++) {
// for (let m = 0; m < this.textObject.hierarchys[i].length; m++) {
// // if (!this.entity.values[k].polygon.hierarchy.isConstant) {
// this.entity.values[k].polygon.hierarchy = new Cesium.CallbackProperty(() => {
// let hierarchy = this.textObject.hierarchys[i][m]
// let holes = []
// for (let n = 0; n < hierarchy.holes.length; n++) {
// holes.push({
// positions: hierarchy.holes[n]
// })
// }
// return {
// positions: hierarchy.positions,
// holes: holes
// }
// }, !this.ismove)
// // }
// k++
// }
// }
// }
}
}
textPosPick() {
let Draw = new DrawPoint(this.sdk)
Draw.start(async (a, position) => {
let point1 = turf.point([this.position.lng, this.position.lat])
let point2 = turf.point([position.lng, position.lat])
let distance = turf.distance(point1, point2, { units: 'kilometers' });
let angle = turf.rhumbBearing(point1, point2);
this._textToCenter = {
distance: distance,
angle: angle
}
this.options.text.position = position
if (this.text) {
this.text.position = [position.lng, position.lat, position.alt]
}
else {
GroundSvg.createText(this)
}
})
}
load(callback) {
if (this.#loaded) {
callback();
}
else {
this.#loadEvent = callback
}
}
async remove() {
this._worker.onmessage = (event) => {}
await this.sdk.removeIncetance(this.options.id)
if (!this.entity) {
return
}
this.drag(false)
if(!this.sdk || !this.sdk.viewer) {
return
}
this.sdk.viewer.entities.remove(this.entity)
this.text && this.text.remove()
for (let i = this.entity.values.length; i >= 0; i--) {
this.sdk.viewer.entities.remove(this.entity.values[i])
}
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
await syncData(this.sdk, this.options.id)
}
_addLink() {
if (
this._DialogObject._element.content.getElementsByClassName('link_add')[0]
.value
) {
this.options.attribute.link.content.push({
name: '链接',
url: this._DialogObject._element.content.getElementsByClassName(
'link_add'
)[0].value
})
this._DialogObject._element.content.getElementsByClassName(
'link_add'
)[0].value = ''
this.attributeLink = this.options.attribute.link.content
} else {
this.Dialog.clickAddLink && this.Dialog.clickAddLink()
}
}
addAttributeLink(link) {
this.options.attribute.link.content.push({
name: '链接',
url: link
})
this.attributeLink = this.options.attribute.link.content
}
/**
* 打开富文本框
*/
openRichTextEditor(e) {
// var ue = UE.getEditor('app');
richText.open(
this.options.id,
this.options.name,
this.options.richTextContent
)
richText.primaryCallBack = content => {
this.options.richTextContent = content
}
}
setPosition(v) {
if (v) {
this.ismove = true
let position = {}
position.lng = v.position.lng
position.lat = v.position.lat
this.position = position
}
else {
this.ismove = false
}
this._update()
}
async flyTo(options = {}) {
if (this._error) {
return
}
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 = { ...this.options.position }
// 如果没有高度值,则获取紧贴高度计算
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 array = []
for (let i = 0; i < this.controlPoints.length; i++) {
let height = await this.getClampToHeight({lng: this.controlPoints[i][0], lat: this.controlPoints[i][1]})
let cartesian = Cesium.Cartesian3.fromDegrees(this.controlPoints[i][0], this.controlPoints[i][1], height)
array.push(cartesian.x, cartesian.y, cartesian.z)
}
let BoundingSphere = Cesium.BoundingSphere.fromVertices(array)
this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, {
offset: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-60.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
}
export default GroundSvg