1404 lines
45 KiB
JavaScript
1404 lines
45 KiB
JavaScript
/**
|
||
* @name: index
|
||
* @author: Administrator
|
||
* @date: 2022-06-09 16:46
|
||
* @description:index
|
||
* @update: 2022-06-09 16:46
|
||
*/
|
||
import md5 from 'js-md5'
|
||
import { Proj } from './proj'
|
||
import { open as projConvertOpen, close as projConvertClose } from './projConvert'
|
||
import { open as projectionConvertOpen, close as projectionConvertClose } from './projectionConvert'
|
||
import { setActiveViewer, closeRotateAround, closeViewFollow } from '../Global/global'
|
||
import FlowPictureMaterialProperty from '../Obj/Materail/FlowPictureMaterialProperty'
|
||
|
||
class Tools {
|
||
/**
|
||
* @constructor
|
||
* @desc 工具类
|
||
* */
|
||
constructor(sdk, options) {
|
||
this.sdk = sdk
|
||
if (this.sdk) {
|
||
this.name_map = this.sdk.proj.name_map
|
||
this.epsg_map = this.sdk.proj.epsg_map
|
||
this.convert = this.sdk.proj.convert
|
||
this.getAllProjection = this.sdk.proj.getAllProjection
|
||
this.projectionIsExists = this.sdk.proj.projectionIsExists
|
||
this.degreesToDMS = this.sdk.proj.degreesToDMS
|
||
this.dmsToDecimal = this.sdk.proj.dmsToDecimal
|
||
}
|
||
|
||
this.options = { ...options }
|
||
}
|
||
|
||
get POST() {
|
||
return 'POST'
|
||
}
|
||
|
||
get GET() {
|
||
return 'GET'
|
||
}
|
||
|
||
|
||
static _md5(text) {
|
||
return md5(text).toUpperCase()
|
||
}
|
||
|
||
|
||
/**
|
||
* @description 将角度转换为弧度
|
||
* @method degreesToRadians
|
||
* @param degrees {number} 弧度制
|
||
* @return radians {number}
|
||
* @memberOf Tools
|
||
* @example let radians = tool.degreesToRadians(20)
|
||
* */
|
||
degreesToRadians(degrees) {
|
||
return turf.degreesToRadians(Number(degrees)) // 1.0471975511965976
|
||
}
|
||
|
||
/**
|
||
* @description 将弧度转换为角度
|
||
* @method radiansToDegrees
|
||
* @param radians {number} 弧度制
|
||
* @return degrees {number}
|
||
* @memberOf Tools
|
||
|
||
* @example let degrees = tool.radiansToDegrees(2)
|
||
* */
|
||
radiansToDegrees(radians) {
|
||
return turf.radiansToDegrees(Number(radians)) // 1.0471975511965976
|
||
}
|
||
|
||
/**
|
||
* @desc 随机字符串
|
||
* @function randomString
|
||
* @memberOf extra
|
||
* @param {number} [e=32] 字符串长度
|
||
* @returns {string} str 字符串
|
||
* @memberOf Tools
|
||
* @example let strings=tool.randomString()
|
||
* */
|
||
randomString(e) {
|
||
/* e = e || 32
|
||
var t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678',
|
||
a = t.length,
|
||
n = ''
|
||
for (let i = 0; i < e; i++) n += t.charAt(Math.floor(Math.random() * a))*/
|
||
return Cesium.createGuid()
|
||
}
|
||
|
||
getSourceRootPath() {
|
||
let sdkName = 'YJEarth.min.js'
|
||
let scripts = document.querySelectorAll('script')
|
||
let prefix = ''
|
||
scripts.forEach((item) => {
|
||
if (item.src && item.src.indexOf(sdkName) > -1) {
|
||
let arr = item.src.split('/')
|
||
arr.pop()
|
||
prefix = arr.join('/')
|
||
}
|
||
})
|
||
return prefix
|
||
}
|
||
|
||
/**@description 笛卡尔坐标转经纬度
|
||
* @method cartesian3Towgs84
|
||
* @param cartesian {Cesium.Cartesian3} 笛卡尔坐标
|
||
* @param viewer
|
||
* @param cartesian.x {number}
|
||
* @param cartesian.y {number}
|
||
* @param cartesian.z {number}
|
||
* @memberOf Tools
|
||
* @return {object} wgs84 返回wgs84坐标
|
||
* */
|
||
cartesian3Towgs84(cartesian, viewer) {
|
||
var ellipsoid = viewer.scene.globe.ellipsoid
|
||
var cartesian3 = new Cesium.Cartesian3(
|
||
cartesian.x,
|
||
cartesian.y,
|
||
cartesian.z
|
||
)
|
||
var cartographic = ellipsoid.cartesianToCartographic(cartesian3)
|
||
var lat = Cesium.Math.toDegrees(cartographic.latitude)
|
||
var lng = Cesium.Math.toDegrees(cartographic.longitude)
|
||
var alt = cartographic.height < 0 ? 0 : cartographic.height
|
||
// var alt = cartographic.height
|
||
return {
|
||
lng: lng,
|
||
lat: lat,
|
||
alt: alt,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @desc 计算多线段长度
|
||
* @method computeDistance
|
||
* @memberOf Tools
|
||
*@param positions {Array.<{lng:number, lat:number,alt:number}>}坐标数组
|
||
* @param [fractionDigits=2] 保留小数点位数
|
||
* @param [ground=true] 是否贴地
|
||
* */
|
||
async computeDistance(positions = [], fractionDigits = 2, type = '空间长度') {
|
||
if (positions.length < 2) {
|
||
return 0
|
||
} else {
|
||
let length = 0
|
||
switch (type) {
|
||
case '空间长度':
|
||
for (let i = 0; i < positions.length - 1; i++) {
|
||
const position1 = Cesium.Cartesian3.fromDegrees(positions[i].lng, positions[i].lat, positions[i].alt);
|
||
const position2 = Cesium.Cartesian3.fromDegrees(positions[i + 1].lng, positions[i + 1].lat, positions[i + 1].alt);
|
||
const distance = Cesium.Cartesian3.distance(position1, position2);
|
||
length = length + distance
|
||
}
|
||
break
|
||
case '投影长度':
|
||
for (let i = 0; i < positions.length - 1; i++) {
|
||
const position1 = Cesium.Cartesian3.fromDegrees(positions[i].lng, positions[i].lat, 0);
|
||
const position2 = Cesium.Cartesian3.fromDegrees(positions[i + 1].lng, positions[i + 1].lat, 0);
|
||
const distance = Cesium.Cartesian3.distance(position1, position2);
|
||
length = length + distance
|
||
}
|
||
break
|
||
case '地表长度':
|
||
let meters
|
||
let lineString2 = []
|
||
positions.forEach((item) => {
|
||
lineString2.push([item.lng, item.lat, item.alt])
|
||
})
|
||
let line2 = turf.lineString(lineString2)
|
||
let d = turf.length(line2) * 1000
|
||
meters = d > 20 ? d / 20 : d
|
||
|
||
let res = this.chunkLine(positions, meters)
|
||
let coordinates = []
|
||
res.forEach((Feature, index) => {
|
||
if (index === 0) {
|
||
coordinates = [...Feature.geometry.coordinates]
|
||
} else {
|
||
coordinates.push(Feature.geometry.coordinates[1])
|
||
}
|
||
})
|
||
let arr = []
|
||
for (const item of coordinates) {
|
||
const index = coordinates.indexOf(item);
|
||
let r = await this.sampleHeight({ lng: item[0], lat: item[1], alt: 0 }, index)
|
||
r.position.alt = r.position.alt < 0 ? 0 : r.position.alt
|
||
arr.push(r)
|
||
}
|
||
let l = arr.length - 1
|
||
for (let i = 0; i < arr.length - 1; i++) {
|
||
const position1 = Cesium.Cartesian3.fromDegrees(arr[i].position.lng, arr[i].position.lat, 0);
|
||
const position2 = Cesium.Cartesian3.fromDegrees(arr[i + 1].position.lng, arr[i + 1].position.lat, 0);
|
||
const distance = Cesium.Cartesian3.distance(position1, position2);
|
||
length = length + distance
|
||
}
|
||
break
|
||
default:
|
||
break;
|
||
}
|
||
return length.toFixed(fractionDigits)
|
||
}
|
||
}
|
||
|
||
computeDistance2(positions = [], fractionDigits = 2, ground = true) {
|
||
if (positions.length < 2) {
|
||
return 0
|
||
} else {
|
||
let length = 0
|
||
if (ground) {
|
||
let lineString = []
|
||
positions.forEach((item) => {
|
||
lineString.push([item.lng, item.lat, item.alt])
|
||
})
|
||
let line = turf.lineString(lineString)
|
||
length = turf.length(line) * 1000
|
||
}
|
||
else {
|
||
for (let i = 0; i < positions.length - 1; i++) {
|
||
const position1 = Cesium.Cartesian3.fromDegrees(positions[i].lng, positions[i].lat, positions[i].alt);
|
||
const position2 = Cesium.Cartesian3.fromDegrees(positions[i + 1].lng, positions[i + 1].lat, positions[i + 1].alt);
|
||
const distance = Cesium.Cartesian3.distance(position1, position2);
|
||
length = length + distance
|
||
}
|
||
}
|
||
return length.toFixed(fractionDigits)
|
||
}
|
||
}
|
||
|
||
async sampleHeight(p1, index) {
|
||
let p2 = await this.sampleHeightMostDetailed([p1])
|
||
p1.alt = p2[0].height
|
||
return { position: p1, index }
|
||
}
|
||
|
||
/**@description 计算多边形面积
|
||
* @method computeArea
|
||
* @memberOf Tools
|
||
* @param positions {Array.<{lng:number, lat:number,alt:number}>}
|
||
* @param [fractionDigits=2] {number} 精确到小数点多少位
|
||
* @return {number} 面积
|
||
* */
|
||
computeArea(positions, fractionDigits = 2) {
|
||
if (positions.length < 3) {
|
||
return 0
|
||
} else {
|
||
let p = []
|
||
positions.forEach((item) => {
|
||
p.push([item.lng, item.lat])
|
||
})
|
||
p.push(p[0])
|
||
let polygon = turf.polygon([p])
|
||
let triangles = turf.tesselate(polygon);
|
||
|
||
return Number(turf.area(triangles).toFixed(fractionDigits))
|
||
}
|
||
}
|
||
|
||
computeSignedArea(viewer, path) {
|
||
let _this = this
|
||
let fromDegreesArray = []
|
||
let fromDegreesArray2 = []
|
||
for (let i = 0; i < path.length; i++) {
|
||
fromDegreesArray.push(path[i].lng, path[i].lat)
|
||
fromDegreesArray2.push([path[i].lng, path[i].lat])
|
||
}
|
||
let line = turf.lineString(fromDegreesArray2);
|
||
let bbox = turf.bbox(line);
|
||
let longRadians = Cesium.Math.toRadians(bbox[2] - bbox[0]);
|
||
let latRadians = Cesium.Math.toRadians(bbox[3] - bbox[1]);
|
||
let granularity
|
||
if (longRadians > latRadians) {
|
||
granularity = longRadians / 10
|
||
}
|
||
else {
|
||
granularity = latRadians / 10
|
||
}
|
||
|
||
// let granularity = Math.PI / Math.pow(2, 11);
|
||
// granularity = granularity / 1250;
|
||
let polygonGeometry = new Cesium.PolygonGeometry.fromPositions({
|
||
positions: Cesium.Cartesian3.fromDegreesArray(fromDegreesArray),
|
||
vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
|
||
granularity: granularity,
|
||
});
|
||
//创建自定义平面几何体
|
||
let geom = new Cesium.PolygonGeometry.createGeometry(polygonGeometry);
|
||
if (!geom || !geom.attributes || !geom.attributes.position) {
|
||
return 0
|
||
}
|
||
const indices = geom.indices; //获取顶点索引数据
|
||
const positions = geom.attributes.position.values;
|
||
function returnPosition(position, index) {
|
||
let pos3 = new Cesium.Cartesian3(
|
||
positions[index * 3],
|
||
positions[index * 3 + 1],
|
||
positions[index * 3 + 2]
|
||
);
|
||
let position1 = viewer.scene.clampToHeight(pos3) || pos3
|
||
// let pos84 = await _this.cartesian3Towgs84(position1, viewer)
|
||
// let height = 0
|
||
// try {
|
||
// let position2 = await Cesium.sampleTerrainMostDetailed(
|
||
// viewer.scene.terrainProvider,
|
||
// [Cesium.Cartographic.fromCartesian(pos3)]
|
||
// )
|
||
// height = position2[0].height
|
||
// } catch (error) {
|
||
// height = 0
|
||
// }
|
||
// if (height > pos84.alt) {
|
||
// pos84.alt = height
|
||
// }
|
||
return position1
|
||
}
|
||
|
||
let area = 0
|
||
for (let index = 0; index < indices.length; index += 3) {
|
||
const pos0 = returnPosition(positions, indices[index]);
|
||
const pos1 = returnPosition(positions, indices[index + 1]);
|
||
const pos2 = returnPosition(positions, indices[index + 2]);
|
||
// let entity = viewer.entities.add({
|
||
// name: "三角面",
|
||
// polygon: {
|
||
// hierarchy: [pos0, pos1, pos2],
|
||
// perPositionHeight: true,
|
||
// material: Cesium.Color.fromRandom(),
|
||
// outline: true,
|
||
// outlineColor: Cesium.Color.BLACK,
|
||
// },
|
||
// });
|
||
|
||
let v0 = Cesium.Cartesian3.subtract(pos0, pos1, new Cesium.Cartesian3())
|
||
let v1 = Cesium.Cartesian3.subtract(pos2, pos1, new Cesium.Cartesian3())
|
||
let cross = Cesium.Cartesian3.cross(v0, v1, v0);
|
||
area = (area + Cesium.Cartesian3.magnitude(cross) * 0.5)
|
||
}
|
||
return Number(area.toFixed(2))
|
||
}
|
||
|
||
/**
|
||
* @desc 创建圆
|
||
*@method createCircle
|
||
* @param point {object} 圆心坐标
|
||
* @param point.lng {number} 经度
|
||
* @param point.lat {number} 纬度
|
||
* @param radius {number} 半径 单位:米
|
||
* @param [options]
|
||
* @param [options.steps=360] {number} 段数
|
||
* @memberOf Tools
|
||
|
||
* */
|
||
createCircle(point, radius = 1, options = { steps: 360 }) {
|
||
if (Number(radius) <= 0) {
|
||
radius = 0.01
|
||
}
|
||
var center = [Number(point.lng), Number(point.lat)]
|
||
let coordinates = turf.circle(center, radius / 1000, options).geometry
|
||
.coordinates[0]
|
||
let positions = []
|
||
coordinates.forEach((item) => {
|
||
positions = positions.concat(item)
|
||
})
|
||
return positions
|
||
}
|
||
|
||
/**
|
||
* @desc 创建椭圆
|
||
*@method createEllipse
|
||
* @param point {object} 圆心坐标
|
||
* @param point.lng {number} 经度
|
||
* @param point.lat {number} 纬度
|
||
* @param [options]
|
||
* @param [options.granularity=0.1] {number} 椭圆上点之间的角度
|
||
* @param [options.semiMinorAxis=10] {number} 短半轴长度 单位:米
|
||
* @param [options.semiMajorAxis=20] {number} 长半轴长度 单位:米
|
||
* @param [options.bearing=0] {number} 椭圆旋转角度 单位:米
|
||
* @memberOf Tools
|
||
|
||
* */
|
||
createEllipse(point, options = { granularity: 0.1, semiMinorAxis: 10, semiMajorAxis: 20, bearing: 0, height: 0 }) {
|
||
if (!options.granularity) {
|
||
options.granularity = 0.1
|
||
}
|
||
if (!options.height) {
|
||
options.height = 0
|
||
}
|
||
if (!options.semiMinorAxis) {
|
||
options.semiMinorAxis = 0.00001
|
||
}
|
||
if (!options.semiMajorAxis) {
|
||
options.semiMajorAxis = 0.00001
|
||
}
|
||
let ellipseGeometry = new Cesium.EllipseOutlineGeometry({
|
||
center: Cesium.Cartesian3.fromDegrees(Number(point.lng), Number(point.lat)),
|
||
semiMajorAxis: Number(options.semiMajorAxis),
|
||
semiMinorAxis: Number(options.semiMinorAxis),
|
||
height: Number(options.height),
|
||
granularity: Cesium.Math.toRadians(options.granularity),
|
||
rotation: Cesium.Math.toRadians(options.bearing),
|
||
})
|
||
let ellipse = Cesium.EllipseOutlineGeometry.createGeometry(ellipseGeometry)
|
||
if (!ellipse || !ellipse.attributes || !ellipse.attributes.position) {
|
||
return []
|
||
}
|
||
const ellipsePositions = ellipse.attributes.position.values;
|
||
let positions = []
|
||
for (let i = 0; i < ellipsePositions.length; i += 3) {
|
||
let pos = new Cesium.Cartesian3(
|
||
ellipsePositions[i],
|
||
ellipsePositions[i + 1],
|
||
ellipsePositions[i + 2]
|
||
)
|
||
positions.push(pos)
|
||
}
|
||
return positions
|
||
}
|
||
|
||
/*计算2点的恒相线夹角*/
|
||
rhumbBearing(p1, p2) {
|
||
var point1 = turf.point([p1.lng, p1.lat],);
|
||
var point2 = turf.point([p2.lng, p2.lat],);
|
||
return turf.rhumbBearing(point1, point2);
|
||
}
|
||
|
||
|
||
computeCenter(positions = []) {
|
||
let arr = []
|
||
positions.forEach((item) => {
|
||
arr.push(turf.point([item.lng, item.lat]))
|
||
})
|
||
var features = turf.featureCollection(arr)
|
||
|
||
var coordinates = turf.center(features).geometry.coordinates
|
||
return {
|
||
lng: coordinates[0],
|
||
lat: coordinates[1],
|
||
}
|
||
}
|
||
|
||
//计算2点的中心点
|
||
computeMidpoint(point1, point2) {
|
||
let p1 = turf.point([point1.lng, point1.lat])
|
||
let p2 = turf.point([point2.lng, point2.lat])
|
||
var center = turf.midpoint(p1, p2).geometry.coordinates
|
||
return { lng: center[0], lat: center[1] }
|
||
}
|
||
|
||
//计算
|
||
computeAttackArrow(positions = []) {
|
||
return this.computeArrow(positions, 0)
|
||
}
|
||
|
||
//计算钳击箭头
|
||
computePincerArrow(positions = []) {
|
||
return this.computeArrow(positions)
|
||
}
|
||
|
||
//计算攻击箭头
|
||
computeArrow(positions = [], type = 1) {
|
||
if (positions.length < 3) {
|
||
return []
|
||
} else {
|
||
var lnglatArr = []
|
||
// if(positions.every(pos => Number(pos.lng) >= 0) || positions.every(pos => Number(pos.lng) <= 0)) {
|
||
// for (var i = 0; i < positions.length; i++) {
|
||
// lnglatArr.push([positions[i].lng, positions[i].lat])
|
||
// }
|
||
// }
|
||
// else {
|
||
// for (var i = 0; i < positions.length; i++) {
|
||
// if(positions[i].lng<0) {
|
||
// lnglatArr.push([positions[i].lng+360, positions[i].lat])
|
||
// }
|
||
// else {
|
||
// lnglatArr.push([positions[i].lng, positions[i].lat])
|
||
// }
|
||
// }
|
||
// }
|
||
for (var i = 0; i < positions.length; i++) {
|
||
lnglatArr.push([positions[i].lng, positions[i].lat])
|
||
}
|
||
var res
|
||
if (type) {
|
||
res = xp.algorithm.doubleArrow(lnglatArr)
|
||
} else {
|
||
res = xp.algorithm.tailedAttackArrow(lnglatArr)
|
||
}
|
||
var index = JSON.stringify(res.polygonalPoint).indexOf('null')
|
||
var returnData = []
|
||
if (index === -1) returnData = res.polygonalPoint
|
||
return returnData
|
||
}
|
||
}
|
||
|
||
// 计算集结地
|
||
computeAssemble(positions = [], is84 = false) {
|
||
if (positions.length < 2) {
|
||
return []
|
||
} else {
|
||
let points = positions.length;
|
||
let pnts = new Array();
|
||
positions.forEach((item) => {
|
||
pnts.push([item.lng, item.lat]);
|
||
});
|
||
//console.log("pnts6666",pnts);
|
||
// pnts.push(tailPoint);
|
||
// pnts.push(headerPoint);
|
||
|
||
if (pnts.length === 2) {
|
||
let mid = P.PlotUtils.mid(pnts[0], pnts[1])
|
||
//let d = utils.MathDistance(pnts[0], mid) / 0.9
|
||
let d = P.PlotUtils.distance(pnts[0], mid) / 0.9
|
||
//console.log("d",d);
|
||
let pnt = P.PlotUtils.getThirdPoint(pnts[0], mid, P.Constants.HALF_PI, d, true)
|
||
pnts = [pnts[0], pnt, pnts[1]];
|
||
//console.log("pnt",pnt);
|
||
//createPoint(Cesium.Cartesian3.fromDegrees(pnt[0], pnt[1]));
|
||
}
|
||
let mid = P.PlotUtils.mid(pnts[0], pnts[2])
|
||
pnts.push(mid, pnts[0], pnts[1])
|
||
|
||
let [normals, pnt1, pnt2, pnt3, result, result2] = [[], undefined, undefined, undefined, [], []]
|
||
for (let i = 0; i < pnts.length - 2; i++) {
|
||
pnt1 = pnts[i]
|
||
pnt2 = pnts[i + 1]
|
||
pnt3 = pnts[i + 2]
|
||
let normalPoints = P.PlotUtils.getBisectorNormals(0.4, pnt1, pnt2, pnt3)
|
||
normals = normals.concat(normalPoints)
|
||
}
|
||
let count = normals.length
|
||
normals = [normals[count - 1]].concat(normals.slice(0, count - 1))
|
||
for (let i = 0; i < pnts.length - 2; i++) {
|
||
pnt1 = pnts[i]
|
||
pnt2 = pnts[i + 1]
|
||
result = result.concat([...pnt1])
|
||
for (let t = 0; t <= P.Constants.FITTING_COUNT; t++) {
|
||
let pnt = P.PlotUtils.getCubicValue(t / P.Constants.FITTING_COUNT, pnt1, normals[i * 2], normals[i * 2 + 1], pnt2)
|
||
result = result.concat([...pnt])
|
||
}
|
||
result = result.concat([...pnt2])
|
||
}
|
||
if (is84) {
|
||
return result
|
||
}
|
||
else {
|
||
return Cesium.Cartesian3.fromDegreesArray(result)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 计算直线箭头
|
||
computeStraightArrow(positions = [], is84 = false) {
|
||
if (positions.length < 2) {
|
||
return []
|
||
}
|
||
let point1 = [positions[0].lng, positions[0].lat]
|
||
let point2 = [positions[1].lng, positions[1].lat]
|
||
if (positions[0].lng === positions[1].lng && positions[0].lat === positions[1].lat) {
|
||
if (is84) {
|
||
return [positions[0], positions[0], positions[0]]
|
||
}
|
||
else {
|
||
let cartesian3 = Cesium.Cartesian3.fromDegrees(positions[0].lng, positions[0].lat)
|
||
return [cartesian3, cartesian3, cartesian3]
|
||
}
|
||
}
|
||
let lnglatArr = []
|
||
for (let i = 0; i < positions.length; i++) {
|
||
lnglatArr.push([positions[i].lng, positions[i].lat])
|
||
}
|
||
|
||
let res
|
||
res = xp.algorithm.fineArrow(point1, point2)
|
||
if (is84) {
|
||
let pos84 = []
|
||
for (let i = 0; i < res.length; i++) {
|
||
let pos = this.cartesian3Towgs84(res[i], this.sdk.viewer)
|
||
pos84.push(pos.lng, pos.lat)
|
||
}
|
||
return pos84
|
||
}
|
||
return res
|
||
}
|
||
|
||
getMaterial(color = '#2ab0c2', type = 0, entity = null, newParam = {}) {
|
||
let material = ''
|
||
let arr = {
|
||
'7': 10,
|
||
'8': 3,
|
||
'9': 4,
|
||
'10': 4,
|
||
'11': 4,
|
||
'12': 2
|
||
}
|
||
if (entity) {
|
||
arr[type + ''] ? (entity.polyline.width = entity.polyline.oriWidth + arr[type + '']) : (entity.polyline.width = entity.polyline.oriWidth)
|
||
}
|
||
|
||
switch (Number(type)) {
|
||
|
||
case 1: //虚线
|
||
material = new Cesium.PolylineDashMaterialProperty({
|
||
color: Cesium.Color.fromCssColorString(color),
|
||
dashLength: 10, //短划线长度
|
||
})
|
||
break
|
||
case 2: //泛光
|
||
material = new Cesium.PolylineGlowMaterialProperty({
|
||
glowPower: 0.2,
|
||
color: Cesium.Color.fromCssColorString(color),
|
||
})
|
||
break
|
||
case 3: //尾迹光线
|
||
material = new Cesium.PolylineFlowMaterialProperty({
|
||
color: color,
|
||
speed: newParam.rotate ? newParam.speed : 0 - newParam.speed,
|
||
rotate: newParam.rotate
|
||
})
|
||
break
|
||
case 4: //多尾迹光线
|
||
material = new Cesium.PolylineFlowMultMaterialProperty({
|
||
color: color,
|
||
speed: newParam.rotate ? newParam.speed : 0 - newParam.speed,
|
||
rotate: newParam.rotate
|
||
})
|
||
break
|
||
case 5: //普通流动虚线
|
||
// material = new Cesium.FlowDashedLineFlowMaterialProperty({
|
||
// color: color,
|
||
// uType: 0,
|
||
// speed: newParam.rotate ? newParam.speed : 0 - newParam.speed,
|
||
// // dashSize: newParam.dashSize,
|
||
// space: newParam.space,
|
||
// scale: 1.0
|
||
// })
|
||
// break
|
||
case 6: //流动虚线2
|
||
let that = this
|
||
|
||
material = new Cesium.FlowDashedLineFlowMaterialProperty({
|
||
color: color,
|
||
uType: type == 5 ? 0 : 1,
|
||
speed: newParam.rotate ? newParam.speed : 0 - newParam.speed,
|
||
// dashSize: newParam.dashSize,
|
||
space: newParam.space,
|
||
scale: new Cesium.CallbackProperty(function () {
|
||
var oriPositions = entity.polyline.positions.getValue();
|
||
|
||
if (!Cesium.defined(oriPositions)) {
|
||
return 1.0;
|
||
}
|
||
var distance = 0;
|
||
for (var i = 0; i < oriPositions.length - 1; ++i) {
|
||
distance += Cesium.Cartesian3.distance(oriPositions[i], oriPositions[i + 1]);
|
||
}
|
||
//屏幕坐标
|
||
let point1 = new Cesium.Cartesian2(0, that.sdk.viewer.canvas.clientHeight)
|
||
let point2 = new Cesium.Cartesian2(that.sdk.viewer.canvas.clientWidth / 2, that.sdk.viewer.canvas.clientHeight)
|
||
var cartesian1 = that.sdk.viewer.scene.pickPosition(point1)
|
||
var cartesian2 = that.sdk.viewer.scene.pickPosition(point2)
|
||
|
||
var distance2 = Cesium.Cartesian3.distance(cartesian1, cartesian2);
|
||
|
||
let repeatX = distance2 * 2 / distance
|
||
|
||
return repeatX;
|
||
})
|
||
})
|
||
|
||
break
|
||
case 7: //流动箭头1
|
||
case 8: //流动箭头2
|
||
case 9: //流动箭头3
|
||
case 10: //流动箭头4
|
||
case 11: //流动箭头5
|
||
case 12: //流动箭头6
|
||
let param = {
|
||
color: color,
|
||
image: this.getSourceRootPath() + `/img/arrow/${type - 6}.png`,
|
||
space: newParam.space,
|
||
speed: newParam.speed
|
||
}
|
||
|
||
param.speed = newParam.rotate ? param.speed : 0 - param.speed
|
||
|
||
this.getFlowTexture(this, param, entity)
|
||
|
||
break
|
||
default:
|
||
material = Cesium.Color.fromCssColorString(color)
|
||
break
|
||
}
|
||
return material
|
||
}
|
||
|
||
getFlowTexture(that, options, entity) {
|
||
|
||
const canvasEle = document.createElement('canvas');
|
||
const ctx = canvasEle.getContext('2d')
|
||
const myImg = new Image()
|
||
// myImg.src = that.getSourceRootPath() + '/img/arrow/1.png'
|
||
myImg.src = options.image
|
||
myImg.onload = function () {
|
||
options.space = Math.max(0.1, options.space);
|
||
if (options.speed > 0 || options.speed == 0) {
|
||
canvasEle.width = myImg.width * (options.space + 1)
|
||
canvasEle.height = myImg.height
|
||
ctx.drawImage(myImg, myImg.width * (options.space / 2), 0)
|
||
} else {
|
||
ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
|
||
canvasEle.width = myImg.width * (options.space + 1)
|
||
canvasEle.height = myImg.height
|
||
ctx.save(); // 保存当前状态
|
||
ctx.translate(canvasEle.width / 2, canvasEle.height / 2); // 移动原点至中心
|
||
ctx.rotate(Math.PI); // (弧度制)
|
||
ctx.translate(-canvasEle.width / 2, -canvasEle.height / 2); // 移回原点
|
||
ctx.drawImage(myImg, myImg.width * (options.space / 2), 0)
|
||
ctx.restore(); // 恢复状态
|
||
}
|
||
|
||
// let repeat = getRepeat()
|
||
// }, false)
|
||
// entity.polyline.material.oriRepeat = that.getSceenLine(entity, options, canvasEle)
|
||
// entity.polyline.material.oriSpeed = undefined
|
||
let beforeSpeed = 0, repeat = 0
|
||
entity.polyline.material = new Cesium.LineTextureMaterialProperty(
|
||
{
|
||
color: options.color,
|
||
image: canvasEle,
|
||
speed: options.speed,
|
||
repeat: new Cesium.CallbackProperty(function () {
|
||
var positionProperty = entity.polyline.positions;
|
||
var positions = positionProperty.getValue(that.sdk.viewer.clock.currentTime);
|
||
|
||
if (!Cesium.defined(positions)) {
|
||
return new Cesium.Cartesian2(1.0, 1.0);
|
||
// return 1.0;
|
||
}
|
||
|
||
var distance = 0;
|
||
for (var i = 0; i < positions.length - 1; ++i) {
|
||
distance += Cesium.Cartesian3.distance(positions[i], positions[i + 1]);
|
||
}
|
||
|
||
var repeatX = distance / entity.polyline.width.getValue();
|
||
// 根据地图缩放程度调整repeatX
|
||
var cameraHeight = that.sdk.viewer.camera.positionCartographic.height;
|
||
var boundingSphere = new Cesium.BoundingSphere(
|
||
new Cesium.Cartesian3(-1000000, 0, 0), // 中心点坐标
|
||
500000 // 半径(距离)
|
||
);
|
||
|
||
// 获取绘图缓冲区的宽度和高度(通常是屏幕的分辨率)
|
||
var drawingBufferWidth = that.sdk.viewer.canvas.clientWidth;
|
||
var drawingBufferHeight = that.sdk.viewer.canvas.clientHeight;
|
||
|
||
// 使用 getPixelSize 方法获取包围球在屏幕上的像素大小
|
||
var groundResolution = that.sdk.viewer.scene.camera.getPixelSize(boundingSphere, drawingBufferWidth, drawingBufferHeight)
|
||
let result
|
||
if (groundResolution > 700) {
|
||
repeatX *= groundResolution / cameraHeight / (options.space * (canvasEle.width / canvasEle.height * 5) + 1);
|
||
// if (entity.polyline.material.oriRepeat) {
|
||
let speed = repeatX / entity.polyline.oriRepeat
|
||
entity.polyline.oriSpeed = speed
|
||
entity.polyline.oriRepeatX = repeatX
|
||
// } else {
|
||
// entity.polyline.material.oriRepeat = repeatX
|
||
// }
|
||
beforeSpeed = speed
|
||
repeat = repeatX
|
||
result = new Cesium.Cartesian2(repeatX, speed || 1.0)
|
||
} else {
|
||
result = new Cesium.Cartesian2(repeat || entity.polyline.oriRepeatX, beforeSpeed || entity.polyline.oriSpeed)
|
||
}
|
||
|
||
return result;
|
||
// return repeatX;
|
||
})
|
||
}
|
||
)
|
||
let oriRepeat = that.getSceenLine(entity, options, canvasEle)
|
||
oriRepeat && (entity.polyline.oriRepeat = oriRepeat)
|
||
}
|
||
}
|
||
/**获取当前满屏横线速度 */
|
||
getSceenLine(entity, options, canvasEle) {
|
||
let point1 = new Cesium.Cartesian2(0, this.sdk.viewer.canvas.clientHeight)
|
||
let point2 = new Cesium.Cartesian2(this.sdk.viewer.canvas.clientWidth / 2, this.sdk.viewer.canvas.clientHeight)
|
||
var cartesian1 = this.sdk.viewer.scene.pickPosition(point1)
|
||
var cartesian2 = this.sdk.viewer.scene.pickPosition(point2)
|
||
|
||
var distance = Cesium.Cartesian3.distance(cartesian1, cartesian2);
|
||
|
||
var repeatX = distance / entity.polyline.width.getValue();
|
||
// 根据地图缩放程度调整repeatX
|
||
var cameraHeight = this.sdk.viewer.camera.positionCartographic.height;
|
||
var boundingSphere = new Cesium.BoundingSphere(
|
||
new Cesium.Cartesian3(-1000000, 0, 0), // 中心点坐标
|
||
500000 // 半径(距离)
|
||
);
|
||
|
||
// 获取绘图缓冲区的宽度和高度(通常是屏幕的分辨率)
|
||
var drawingBufferWidth = this.sdk.viewer.canvas.clientWidth;
|
||
var drawingBufferHeight = this.sdk.viewer.canvas.clientHeight;
|
||
|
||
// 使用 getPixelSize 方法获取包围球在屏幕上的像素大小
|
||
var groundResolution = this.sdk.viewer.scene.camera.getPixelSize(boundingSphere, drawingBufferWidth, drawingBufferHeight)
|
||
// repeatX *= groundResolution / cameraHeight / ((myImg.width / myImg.height * 5) + 1);
|
||
if (groundResolution > 700) {
|
||
repeatX *= groundResolution / cameraHeight / (options.space * (canvasEle.width / canvasEle.height * 5) + 1);
|
||
} else {
|
||
repeatX = undefined;
|
||
}
|
||
|
||
return repeatX
|
||
}
|
||
|
||
/*创建直箭头图片*/
|
||
create_arrow1_picture(color) {
|
||
let canvas = new fabric.Canvas('canvas')
|
||
canvas.width = 150
|
||
canvas.height = 75
|
||
let w_offset = 35
|
||
let h_offset = 20
|
||
let fill = color
|
||
let polygon = new fabric.Polygon(
|
||
[
|
||
{ x: canvas.width, y: canvas.height / 2 }, //箭头右边顶点
|
||
{ x: canvas.width - w_offset, y: canvas.height }, //顺时针
|
||
{ x: canvas.width - w_offset, y: canvas.height - h_offset }, //
|
||
{ x: canvas.width / 2, y: canvas.height - h_offset }, //
|
||
{ x: canvas.width / 2, y: h_offset }, //
|
||
{ x: canvas.width - w_offset, y: h_offset }, //
|
||
{ x: canvas.width - w_offset, y: 0 }, //
|
||
],
|
||
{
|
||
fill,
|
||
}
|
||
)
|
||
canvas.add(polygon)
|
||
|
||
return canvas.toDataURL()
|
||
}
|
||
|
||
/*创建箭头图片*/
|
||
|
||
create_arrow2_picture(color) {
|
||
let canvas = new fabric.Canvas('canvas')
|
||
canvas.width = 75
|
||
canvas.height = 75
|
||
let w_offset1 = 35
|
||
let w_offset2 = 40
|
||
let fill = color
|
||
let polygon = new fabric.Polygon(
|
||
[
|
||
{ x: canvas.width, y: canvas.height / 2 },
|
||
{ x: canvas.width - w_offset1, y: canvas.height },
|
||
{ x: canvas.width - w_offset1 - w_offset2, y: canvas.height },
|
||
{ x: canvas.width - w_offset2, y: canvas.height / 2 },
|
||
{ x: canvas.width - w_offset1 - w_offset2, y: 0 },
|
||
{ x: canvas.width - w_offset1, y: 0 },
|
||
],
|
||
{
|
||
fill,
|
||
}
|
||
)
|
||
canvas.add(polygon)
|
||
|
||
return canvas.toDataURL()
|
||
}
|
||
|
||
sampleHeightMostDetailed(positions) {
|
||
let cartesians = []
|
||
positions.forEach((item) => {
|
||
cartesians.push(new Cesium.Cartographic.fromDegrees(item.lng, item.lat))
|
||
})
|
||
return this.sdk.viewer.scene.sampleHeightMostDetailed(cartesians)
|
||
}
|
||
|
||
flyHome(duration = 3) {
|
||
setActiveViewer(0)
|
||
closeRotateAround(this.sdk)
|
||
closeViewFollow(this.sdk)
|
||
|
||
if (this.sdk.viewer.CAMERA_DEFAULT_VIEW_RECTANGLE) {
|
||
let destination = this.sdk.viewer.CAMERA_DEFAULT_VIEW_RECTANGLE.destination
|
||
let orientation = this.sdk.viewer.CAMERA_DEFAULT_VIEW_RECTANGLE.orientation
|
||
this.sdk.viewer.camera.flyTo({
|
||
destination: Cesium.Cartesian3.fromDegrees(destination.lng, destination.lat, destination.alt),
|
||
orientation: {
|
||
heading: Cesium.Math.toRadians(orientation.heading || 0),
|
||
pitch: Cesium.Math.toRadians(orientation.pitch || 0),
|
||
roll: Cesium.Math.toRadians(orientation.roll || 0)
|
||
},
|
||
duration: duration
|
||
})
|
||
}
|
||
else {
|
||
this.sdk.viewer.camera.flyHome(duration)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @description 设置拾取操作启停
|
||
* @method setPickStatus
|
||
* @param [status=true] {boolean}
|
||
* @memberOf Tools
|
||
* */
|
||
setPickStatus(status = true) {
|
||
// YJ.getEarth().interaction.picking.enabled = status
|
||
}
|
||
|
||
/**
|
||
* @description 创建点缓冲区 返回缓冲区坐标
|
||
* @method create_point_buffer
|
||
* @param point {object} 坐标参数
|
||
* @param [radius=5] {number} 缓冲距离 (单位:米)
|
||
* @param option
|
||
* @param point.lng {number} 经度
|
||
* @param point.lat {number} 纬度
|
||
* @memberOf Tools
|
||
* @returns {Array} 返回缓冲区坐标数组
|
||
*/
|
||
create_point_buffer(point, radius = 5, option = { steps: 10 }) {
|
||
let p = turf.point([Number(point.lng), Number(point.lat)])
|
||
let buffered = turf.buffer(p, Number(radius) / 1000, option)
|
||
return buffered.geometry.coordinates
|
||
}
|
||
|
||
/**
|
||
* @description 创建线缓冲区 返回缓冲区坐标
|
||
* @method create_line_buffer
|
||
* @param points {Array.<lng:"",lat:"">} 坐标参数
|
||
* @param [radius=5] {number} 缓冲距离 (单位:米)
|
||
* @memberOf Tools
|
||
* @returns {Array} 返回缓冲区坐标数组
|
||
* @example let points = [{lng:"",lat:""},{lng:"",lat:""},{lng:"",lat:""}]
|
||
* let radius = 10
|
||
* let area_buffer = sdk.create_line_buffer(points,radius)
|
||
* */
|
||
create_line_buffer(points, radius = 5) {
|
||
if (points.length === 1) {
|
||
return this.create_point_buffer(points[0], radius)
|
||
} else if (points.length === 0) {
|
||
return false
|
||
} else {
|
||
let arr = []
|
||
points.forEach((point) => {
|
||
arr.push([Number(point.lng), Number(point.lat)])
|
||
})
|
||
let line = turf.lineString(arr)
|
||
let buffered = turf.buffer(line, Number(radius) / 1000)
|
||
return buffered.geometry.coordinates
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @description 创建面缓冲区 返回缓冲区坐标
|
||
* @method create_area_buffer
|
||
* @param points {Array.<lng:"",lat:"">} 坐标参数
|
||
* @param [radius=5] {number} 缓冲距离 (单位:米)
|
||
* @memberOf Tools
|
||
* @returns {Array} 返回缓冲区坐标数组
|
||
* @example let points = [{lng:"",lat:""},{lng:"",lat:""},{lng:"",lat:""}]
|
||
* let radius = 10
|
||
* let area_buffer = sdk.create_area_buffer(points,radius)
|
||
* */
|
||
create_area_buffer(points, radius = 5) {
|
||
if (points.length === 1) {
|
||
return this.create_point_buffer(points[0], radius)
|
||
} else if (points.length === 0) {
|
||
return false
|
||
} else if (points.length === 2) {
|
||
return this.create_line_buffer(points, radius)
|
||
} else {
|
||
let arr = []
|
||
points.forEach((point) => {
|
||
arr.push([Number(point.lng), Number(point.lat)])
|
||
})
|
||
arr.push(arr[0])
|
||
let poly = turf.polygon([arr])
|
||
let buffered = turf.buffer(poly, Number(radius) / 1000)
|
||
return buffered.geometry.coordinates
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @desc 计算多点范围
|
||
* @method cal_envelope
|
||
* @memberOf Tools
|
||
* */
|
||
cal_envelope(points = []) {
|
||
if (points.length < 2) {
|
||
console.error('坐标数量不能少于2个')
|
||
} else {
|
||
let arr = []
|
||
points.forEach((p) => {
|
||
arr.push(turf.point([p.lng, p.lat]))
|
||
})
|
||
let features = turf.featureCollection(arr)
|
||
return turf.envelope(features).geometry.coordinates[0]
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @desc 按指定距离分段
|
||
* @method chunkLine
|
||
* @param positions {Array}
|
||
* @param meters
|
||
* @memberOf Tools
|
||
* */
|
||
chunkLine(positions = [], meters = 1000) {
|
||
if (positions.length < 2) {
|
||
return []
|
||
} else {
|
||
let arr = []
|
||
positions.forEach((it) => {
|
||
arr.push([it.lng, it.lat])
|
||
})
|
||
let line = turf.lineString(arr)
|
||
|
||
let chunk = turf.lineChunk(line, meters / 1000)
|
||
let __map = new Map()
|
||
chunk.features.forEach((value) => {
|
||
value.geometry.coordinates.forEach((value1) => {
|
||
let key = value1.join(',')
|
||
let val = { lng: value1[0], lat: value1[1] }
|
||
__map.set(key, val)
|
||
})
|
||
})
|
||
return chunk.features
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @desc 标注以sinx的半个周期的形式弹跳
|
||
* */
|
||
billboardAnimation(viewer, { id, offset = 10, times = 3 }) {
|
||
let entity = viewer.entities.getById(id)
|
||
if (entity) {
|
||
let pi = Math.PI
|
||
let tt = 60
|
||
let of = pi / tt
|
||
|
||
let h = 0
|
||
let src_p = this.cartesian3Towgs84(entity.position.getValue(), viewer)
|
||
// let height = src_p.alt
|
||
// entity.position = new Cesium.CallbackProperty(() => {
|
||
// let height = offset * Math.sin(h) + src_p.alt
|
||
// h += of
|
||
// return Cesium.Cartesian3.fromDegrees(src_p.lng, src_p.lat, height)
|
||
// }, false)
|
||
let ti = setInterval(() => {
|
||
h += of
|
||
let height = offset * Math.sin(h) + src_p.alt
|
||
if (h > pi) h = 0
|
||
entity.position = Cesium.Cartesian3.fromDegrees(
|
||
src_p.lng,
|
||
src_p.lat,
|
||
height
|
||
)
|
||
}, 30)
|
||
setTimeout(() => {
|
||
clearInterval(ti)
|
||
entity.position = Cesium.Cartesian3.fromDegrees(
|
||
src_p.lng,
|
||
src_p.lat,
|
||
src_p.alt
|
||
)
|
||
}, 3000)
|
||
}
|
||
}
|
||
|
||
/**@desc 绘制扇形
|
||
* @method sector
|
||
* @memberOf Tools*/
|
||
calSector(
|
||
center = {},
|
||
radius = 100,
|
||
bearing1 = 25,
|
||
bearing2 = 45,
|
||
steps = 360,
|
||
is84 = false
|
||
) {
|
||
let c = turf.point([center.lng, center.lat])
|
||
let coordinates = turf.sector(c, radius / 1000, bearing1, bearing2, { steps: steps })
|
||
.geometry.coordinates
|
||
let positions = []
|
||
coordinates.forEach((array) => {
|
||
array.forEach((item) => {
|
||
let pos
|
||
if (is84) {
|
||
pos = {
|
||
lng: item[0],
|
||
lat: item[1],
|
||
}
|
||
}
|
||
else {
|
||
pos = Cesium.Cartesian3.fromDegrees(item[0], item[1])
|
||
}
|
||
positions.push(pos)
|
||
})
|
||
})
|
||
return positions
|
||
}
|
||
|
||
/**
|
||
* @desc获取紧贴高度
|
||
* @param position 坐标
|
||
*/
|
||
async getClampToHeight(position, objectsToExclude = []) {
|
||
if (!this.sdk || !this.sdk.viewer) {
|
||
return 0
|
||
}
|
||
let pos3 = new Cesium.Cartesian3.fromDegrees(position.lng, position.lat);
|
||
let position1
|
||
try {
|
||
position1 = await this.sdk.viewer.scene.clampToHeight(pos3, objectsToExclude) || pos3
|
||
} catch (error) {
|
||
position1 = pos3
|
||
}
|
||
let height1 = await this.cartesian3Towgs84(position1, this.sdk.viewer).alt
|
||
let height2 = 0
|
||
try {
|
||
if (this.sdk.viewer.scene.terrainProvider.availability) {
|
||
let position2 = await Cesium.sampleTerrainMostDetailed(
|
||
this.sdk.viewer.scene.terrainProvider,
|
||
[Cesium.Cartographic.fromDegrees(position.lng, position.lat)]
|
||
)
|
||
position2[0].height && (height2 = position2[0].height)
|
||
}
|
||
} catch (error) {
|
||
height2 = 0
|
||
}
|
||
if (height1 > height2) {
|
||
return Number(height1.toFixed(2))
|
||
}
|
||
else {
|
||
return Number(height2.toFixed(2))
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @desc 深拷贝对象
|
||
* */
|
||
deepCopyObj(obj) {
|
||
let newobj = null;
|
||
//判断是否需要继续进行递归
|
||
if (typeof (obj) == 'object' && obj !== null) {
|
||
newobj = obj instanceof Array ? [] : {}; //进行下一层递归克隆
|
||
for (let i in obj) {
|
||
if (i != 'earth' && i != 'Dialog')
|
||
newobj[i] = this.deepCopyObj(obj[i])
|
||
} //如果不是对象直接赋值
|
||
} else newobj = obj;
|
||
return newobj;
|
||
}
|
||
|
||
/**
|
||
* @desc 度分秒转换
|
||
* */
|
||
projConvert(status = false, closeCallBack = () => { }) {
|
||
if (status) {
|
||
projConvertOpen(this.sdk, closeCallBack)
|
||
}
|
||
else {
|
||
projConvertClose()
|
||
}
|
||
}
|
||
/**
|
||
* @desc 投影转换
|
||
* */
|
||
projectionConvert(status = false, closeCallBack = () => { }) {
|
||
if (status) {
|
||
projectionConvertOpen(this.sdk, closeCallBack)
|
||
}
|
||
else {
|
||
projectionConvertClose()
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @desc 导出excel
|
||
*/
|
||
// 导出属性
|
||
exportExcel(data) {
|
||
let label = '<Row>'
|
||
for (let key in data[0]) {
|
||
label += `<Cell><Data ss:Type="String">${key}</Data></Cell>`
|
||
}
|
||
label += '</Row>'
|
||
let url = 'data:application/vnd.ms-excel;base64,',
|
||
tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
|
||
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
|
||
+ '<Styles>'
|
||
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
|
||
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
|
||
+ '</Styles>'
|
||
+ '{worksheets}</Workbook>'
|
||
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="120"/><ss:Column ss:Width="240"/>{rows}</Table></Worksheet>'
|
||
, tmplCellXML = '<Cell><Data ss:Type="{nameType}">{data}</Data></Cell>'
|
||
, base64 = function (s) {
|
||
return window.btoa(unescape(encodeURIComponent(s)))
|
||
}
|
||
, format = function (s, c) {
|
||
return s.replace(/{(\w+)}/g, function (m, p) {
|
||
return c[p];
|
||
})
|
||
}
|
||
|
||
let ctx = "";
|
||
let workbookXML = "";
|
||
let worksheetsXML = "";
|
||
let rowsXML = "";
|
||
|
||
let pil = 0;
|
||
for (let i = 0; i < data.length; i++) {
|
||
if (i == 0) {
|
||
rowsXML += label
|
||
}
|
||
rowsXML += '<Row>';
|
||
for (let key in data[i]) {
|
||
ctx = {
|
||
nameType: 'String',
|
||
data: data[i][key]
|
||
};
|
||
rowsXML += format(tmplCellXML, ctx);
|
||
}
|
||
rowsXML += '</Row>';
|
||
if (i > 0 && (i / 60000) % 1 === 0) {
|
||
pil++;
|
||
ctx = { rows: rowsXML, nameWS: 'Sheet' + i };
|
||
worksheetsXML += format(tmplWorksheetXML, ctx);
|
||
rowsXML = "";
|
||
rowsXML += label
|
||
}
|
||
}
|
||
ctx = { rows: rowsXML, nameWS: 'Sheet' };
|
||
worksheetsXML += format(tmplWorksheetXML, ctx);
|
||
rowsXML = "";
|
||
ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
|
||
workbookXML = format(tmplWorkbookXML, ctx);
|
||
let link = document.createElement("A");
|
||
link.href = url + base64(workbookXML);
|
||
link.download = "矢量数据导出.xls"
|
||
link.target = '_blank';
|
||
document.body.appendChild(link);
|
||
link.click();
|
||
document.body.removeChild(link);
|
||
}
|
||
|
||
/**
|
||
* @desc Gzip解压
|
||
*/
|
||
decompressGzip(compressedData) {
|
||
let decompressedData = pako.inflate(compressedData);
|
||
// 将解压缩后的数据转换为字符串
|
||
let decompressedString = new TextDecoder().decode(decompressedData);
|
||
return decompressedString
|
||
}
|
||
|
||
/**
|
||
* @desc cmyk转rbg
|
||
* @param {*} color
|
||
* @returns
|
||
*/
|
||
cmykToRgb(color) {
|
||
let { c, m, y, k } = color
|
||
let rgb = { r: 0, g: 0, b: 0 };
|
||
rgb.c = c / 100;
|
||
rgb.m = m / 100;
|
||
rgb.y = y / 100;
|
||
rgb.k = k / 100;
|
||
rgb.r = 1 - Math.min(1, rgb.c * (1 - rgb.k) + rgb.k);
|
||
rgb.g = 1 - Math.min(1, rgb.m * (1 - rgb.k) + rgb.k);
|
||
rgb.b = 1 - Math.min(1, rgb.y * (1 - rgb.k) + rgb.k);
|
||
rgb.r = Math.round(rgb.r * 255);
|
||
rgb.g = Math.round(rgb.g * 255)
|
||
rgb.b = Math.round(rgb.b * 255);
|
||
return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
|
||
}
|
||
|
||
convertPxToRem(sdk, selector) {
|
||
const htmlFontSize = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
||
let list = []
|
||
let elementList = []
|
||
if (selector) {
|
||
list = document.getElementById(sdk.div_id).querySelectorAll(selector)
|
||
for (let i = 0; i < list.length; i++) {
|
||
elementList.push(list[i], ...list[i].querySelectorAll('*'))
|
||
}
|
||
}
|
||
else {
|
||
elementList = document.getElementById(sdk.div_id).querySelectorAll('*');
|
||
}
|
||
elementList.forEach(element => {
|
||
const style = element.style;
|
||
const rules = Array.from(style).filter(prop => {
|
||
return typeof prop === 'string' && prop.endsWith('px');
|
||
});
|
||
|
||
rules.forEach(prop => {
|
||
const pxValue = parseFloat(style[prop]);
|
||
const remValue = pxValue / htmlFontSize;
|
||
element.style[prop] = `${remValue}rem`;
|
||
});
|
||
});
|
||
}
|
||
|
||
isConvex(arr = []) {
|
||
const { length } = arr
|
||
let pre = 0,
|
||
curr = 0
|
||
for (let i = 0; i < length; ++i) {
|
||
let dx1 = arr[(i + 1) % length].lng - arr[i].lng
|
||
let dx2 = arr[(i + 2) % length].lng - arr[(i + 1) % length].lng
|
||
let dy1 = arr[(i + 1) % length].lat - arr[i].lat
|
||
let dy2 = arr[(i + 2) % length].lat - arr[(i + 1) % length].lat
|
||
curr = dx1 * dy2 - dx2 * dy1
|
||
if (curr != 0) {
|
||
if ((curr > 0 && pre < 0) || (curr < 0 && pre > 0)) return false
|
||
else pre = curr
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
getDateTimeString() {
|
||
// 创建一个表示当前时间的 Date 对象
|
||
const now = new Date();
|
||
// 获取年份
|
||
const year = now.getFullYear();
|
||
// 获取月份(从 0 开始,所以要加 1),并将其转换为两位字符串,不足两位在前面补零
|
||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||
// 获取日期,并将其转换为两位字符串,不足两位在前面补零
|
||
const day = String(now.getDate()).padStart(2, '0');
|
||
// 获取小时,并将其转换为两位字符串,不足两位在前面补零
|
||
const hours = String(now.getHours()).padStart(2, '0');
|
||
// 获取分钟,并将其转换为两位字符串,不足两位在前面补零
|
||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||
// 获取秒,并将其转换为两位字符串,不足两位在前面补零
|
||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||
// 获取毫秒,并将其转换为三位字符串,不足三位在前面补零
|
||
const milliseconds = String(now.getMilliseconds()).padStart(3, '0');
|
||
// 将年、月、日、时、分、秒、毫秒拼接成所需的字符串
|
||
return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`;
|
||
}
|
||
|
||
replaceHost(url, host) {
|
||
let newUrl = url
|
||
if (!url || !host) {
|
||
return url
|
||
}
|
||
try {
|
||
if (!url.startsWith("http")) {
|
||
//说明是本地的json,在磁盘中存在的
|
||
if (!url.includes(":")) {
|
||
if (this.options.host) {
|
||
let o = new URL(url, this.options.host)
|
||
newUrl = o.href
|
||
}
|
||
}
|
||
return newUrl
|
||
}
|
||
else {
|
||
// 移除可能的用户名:密码前缀
|
||
const authRegex = /^[^@]+@/;
|
||
if (authRegex.test(url)) {
|
||
url = url.replace(authRegex, '');
|
||
}
|
||
|
||
// 添加协议前缀(如果没有)
|
||
if (!/^[a-z]+:\/\//i.test(url)) {
|
||
url = 'http://' + url;
|
||
}
|
||
|
||
const parsedUrl = new URL(url);
|
||
const parsedUrl2 = new URL(host);
|
||
let hostname = parsedUrl.hostname;
|
||
let port = parsedUrl.port;
|
||
|
||
// 处理IPv6地址(如果有括号)
|
||
if (hostname.startsWith('[') && hostname.endsWith(']')) {
|
||
hostname = hostname.slice(1, -1);
|
||
}
|
||
if ((hostname === 'localhost' || hostname === '127.0.0.1') && parseInt(port, 10) !== 55110) {
|
||
parsedUrl.port = parsedUrl2.port
|
||
parsedUrl.protocol = parsedUrl2.protocol
|
||
newUrl = parsedUrl.toString()
|
||
}
|
||
return newUrl
|
||
}
|
||
} catch (error) {
|
||
return newUrl
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|
||
export default Tools
|