之前在用超图的进行现在开发,现在用原生的Cesium之后发现量算工具还是个小麻烦。。。关于距离,面积,高度网上都有例子了,但是现在有个角度测量的需求,就自己写了一下。这个是在正北方向做一条辅助线,然后求与正北方向的夹角,过几天做自己画两条线夹角的。
———tool工具类:
———— graphic.js
const radiansPerDegree = Math.PI / 180.0;//角度转化为弧度(rad)
const degreesPerRadian = 180.0 / Math.PI;//弧度转化为角度
const color=Cesium.Color.fromCssColorString('rgba(247,224,32,0.6)')
const pointStyle={
pixelSize: 8,
color:color
}
const labelStyle={
font: '36px sans-serif',
fillColor: Cesium.Color.WHITE,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// outlineWidth: 2,
showBackground:true,
scale:0.5,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(20, -20),
heightReference: Cesium.HeightReference.NONE
}
const AngleGraphic=(function(){
function _(viewer,options){
this.viewer = viewer
viewer.scene.postProcessStages.fxaa.enabled = false;
this.options = {
polyline: options
}
this.positions = options.positions || [];
this.entity = this._init();
this.idDestroyed=false
this._depthTestAgainstTerrain=this.viewer.scene.globe.depthTestAgainstTerrain,
this.nodes=[]
}
_.prototype._init = function () {
this.viewer.scene.globe.depthTestAgainstTerrain=true
const _self = this;
const _update = function () {
return _self.positions;
};
//实时更新polyline.positions
this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
const entity = this.viewer.entities.add(this.options);
return entity
}
_.prototype.remove = function () {
this.viewer.entities.remove(this.entity)
if(this.tmpPolyline){
this.viewer.entities.remove(this.tmpPolyline)
}
for(let p of this.nodes){
this.viewer.entities.remove(p)
}
}
_.prototype.pushNode=function(cartesian){
this.positions.push(cartesian)
const p=this.viewer.entities.add({
position:cartesian,
point:pointStyle
})
this.nodes.push(p)
}
_.prototype.popNode=function(){
this.positions.pop()
const p=this.nodes.pop()
this.viewer.entities.remove(p)
}
_.prototype.destroy=function(){
this.options={
}
this.positions=[]
this.entity=undefined
this.viewer=undefined
this.idDestroyed=true
this.tmpPolyline=undefined
}
_.prototype.stopEdit=function(){
this.viewer.scene.globe.depthTestAgainstTerrain=this._depthTestAgainstTerrain
this.options.label = this.createLabel()
this.options.polyline.positions=this.positions
this.options.position=this.positions[this.positions.length-1]
this.remove()
this.tmpPolyline=this.createAssitGraphic()
this.entity=this.viewer.entities.add(this.options)
}
/**
* 创建辅助线
*/
_.prototype.createAssitGraphic=function(){
if(this.positions.length!==2){
return
}
const startC=Cesium.Cartographic.fromCartesian(this.positions[0])
console.log(startC);
const distance = this.getDistance();
console.log(distance);//单位m
// const endC=Cesium.Cartographic.fromCartesian(this.positions[1])
const tmp=Cesium.Cartesian3.fromRadians(
startC.longitude,
startC.latitude+distance/111000*radiansPerDegree,
startC.height
)
const pts=[this.positions[0],tmp]
return this.viewer.entities.add({
polyline:{
positions:pts,
material:new Cesium.PolylineDashMaterialProperty({
color:color}),
width:10
}
})
}
_.prototype.getDistance = function () {
let distance = 0;
const positions = this.positions
for (let i = 0; i < positions.length - 1; i++) {
let point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
let point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
/**根据经纬度计算出距离**/
let geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(point1cartographic, point2cartographic);
let s = geodesic.surfaceDistance;
//console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
//返回两点之间的距离
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
distance = distance + s;
}
return distance.toFixed(2);
}
_.prototype.createLabel = function () {
const label = labelStyle
label.text='角度'+this.getAngle().toFixed(2)+'°'
+'长度'+this.getDistance()+'米'
return label
}
_.prototype.getAngle=function(){
if(this.positions.length!==2){
return 'Nan'
}
const startC=Cesium.Cartographic.fromCartesian(this.positions[0])
const endC=Cesium.Cartographic.fromCartesian(this.positions[1])
const distance = this.getDistance();
if(startC&&endC){
const l = parseFloat(this.getDistance())//边长
const topPoint=Cesium.Cartesian3.fromRadians(//北上点的Cartesian3
Cesium.Cartographic.fromCartesian(this.positions[0]).longitude,
Cesium.Cartographic.fromCartesian(this.positions[0]).latitude+distance/111000*radiansPerDegree,
Cesium.Cartographic.fromCartesian(this.positions[0]).height
)
const newPoint =Cesium.Cartesian3.fromRadians(
Cesium.Cartographic.fromCartesian(this.positions[1]).longitude,
Cesium.Cartographic.fromCartesian(this.positions[1]).latitude,
Cesium.Cartographic.fromCartesian(this.positions[1]).height
)
const d = Cesium.Cartesian3.distance(topPoint,newPoint);
console.log(Math.acos((2*l*l-d*d)/(2*l*l)))
console.log(l)
console.log(d)
return Cesium.Cartographic.fromCartesian(this.positions[1]).longitude>Cesium.Cartographic.fromCartesian(this.positions[0]).longitude?
Math.acos((2*l*l-d*d)/(2*l*l))*degreesPerRadian:-Math.acos((2*l*l-d*d)/(2*l*l))*degreesPerRadian
}else{
return 'NaN'
}
}
return _
})();
export AngleGraphic
调用方法
这里只附带了部分方法,其他的可以看这个博主的:
github地址
toggleClick(mode) {
if(!viewer){
this.init(window.viewer)
}
this.mode=mode
if (window.graphicManager) {
this.stopDraw();
return;
}
this.tipVisible(true);
this.curMeasureStatus = "结束测量";
const color = Cesium.Color.fromCssColorString("rgba(247,224,32,1)");
window.graphicManager = new AngleGraphic(viewer, {
positions: this.positions,
material: color,
width: 3
});
this.updateTipText("请单击地图确定起点.");
}
init(cesiumViewer) {
const self = this;
viewer=cesiumViewer;
console.log(viewer);
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
const tooltip = this.createTip();
this.tipVisible(false);
handler.setInputAction(e => {
if (!Cesium.defined(window.graphicManager)) {
return;
}
const pixel = e.position;
const ray = viewer.camera.getPickRay(pixel);
const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
//高度和角度只需要一条线段
if (self.mode === "height"||self.mode === "angle") {
......