class MeasureAngle {
_state = new Map();
_layers = null;
_handler = null;
constructor(viewer) {
this._viewer = viewer;
}
getNormal(startPoint, _temp) {
const { _viewer } = this;
let zero = new Cesium.Cartographic(0.0, 1.5708, 0.0);
zero = _viewer.scene.globe.ellipsoid.cartographicToCartesian(zero);
let pot = Cesium.Cartesian3.subtract(zero, startPoint, new Cesium.Cartesian3());
var dir = Cesium.Cartesian3.normalize(pot, new Cesium.Cartesian3());
var ray = new Cesium.Ray(startPoint, dir);
let distance = Math.abs(startPoint.y - _temp.y);
let np = Cesium.Ray.getPoint(ray, distance);
return [startPoint, np];
}
draw() {
const { _viewer } = this;
const _handler = new Cesium.ScreenSpaceEventHandler(_viewer.scene.canvas);
const _layers = this._setLayers();
const _polylineEntity = this._polylineEntity();
const _positions = this._setPositions(_polylineEntity);
const _labelEntity = this._labelEntity();
_layers.entities.add(_polylineEntity);
_layers.entities.add(_labelEntity);
let _currentPoint = null;
let _dottedLine = null;
_handler.setInputAction((e) => {
const position = _viewer.camera.pickEllipsoid(e.position);
let _temp = _viewer.camera.pickEllipsoid(new Cesium.Cartesian2(e.position.x, e.position.y - 100));
if(!position || !_temp) return;
if(_positions.length === 0) _positions.push(position.clone());
_positions.push(position);
const _ps = this.getNormal(position, _temp);
_dottedLine = this._dottedLine(_ps);
_layers.entities.add(_dottedLine);
_currentPoint = this._addPoint(position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
_handler.setInputAction((e) => {
const position = _viewer.camera.pickEllipsoid(e.endPosition);
if(position && _positions.length > 0) _positions.splice(_positions.length - 1, 1, position);
if(_positions.length === 0) {
_labelEntity.label.text = "点击左键绘制第一个点。";
}else if(_positions.length > 0) {
_labelEntity.label.text = "点击左键绘制下一个点,点击右键结束。";
}
if(position) {
_labelEntity.show = true;
_labelEntity.position = position;
}else {
_labelEntity.show = false;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
_handler.setInputAction((e) => {
if(_positions.length === 1 && _currentPoint && _dottedLine) {
_layers.entities.remove(_currentPoint)
_layers.entities.remove(_dottedLine)
};
_layers.entities.remove(_labelEntity);
this._handler.destroy();
this._handler = null;
_currentPoint = null;
_dottedLine = null;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
this._handler = _handler;
this._layers = _layers;
}
clear() {
const { _viewer } = this;
if(this._handler) {
this._handler.destroy();
this._handler = null;
}
if(this._layers) {
_viewer.dataSources.remove(this._layers);
_viewer.entities.remove(this._layers)
this._layers = null;
}
this._state.clear();
}
_dottedLine(positions) {
return new Cesium.Entity({
polyline: {
positions,
material: new Cesium.PolylineDashMaterialProperty({
color: Cesium.Color.YELLOW,
dashLength: 12.0,
}),
width: 2
}
})
}
_addPoint(position, distance) {
const { _viewer } = this;
const point = this._pointEntity(position, distance);
this._layers.entities.add(point);
return point;
}
_setPositions(_polylineEntity) {
const { _state } = this;
_state.set(_polylineEntity.id, []);
const positions = _state.get(_polylineEntity.id);
_polylineEntity.polyline.positions = new Cesium.CallbackProperty(() => {
return positions;
}, false)
return positions;
}
_setLayers() {
const { _viewer } = this;
let _layers = null;
if(!this._layers) {
_layers = new Cesium.CustomDataSource("distanceLayers");
_viewer.dataSources.add(_layers);
}else {
_layers = this._layers;
}
return _layers;
}
_polylineEntity() {
return new Cesium.Entity({
name: "折线",
polyline: {
material: Cesium.Color.YELLOW,
width: 2
}
})
}
_pointEntity(position, text) {
return new Cesium.Entity({
name: "点",
position,
label: {
text,
showBackground: true,
font: '10px sans-serif',
pixelOffset: new Cesium.Cartesian2(0, -50)
},
point: {
pixelSize: 8,
color: Cesium.Color.YELLOW,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK
}
})
}
_labelEntity(position, text) {
return new Cesium.Entity({
name: "点",
position,
label: {
text,
showBackground: true,
font: '10px sans-serif',
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
},
})
}
}
function cartesian3ToWgs84(cartesian3) {
const cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(cartesian3);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
return { longitude, latitude, height };
}
function courseAngle(lng_a, lat_a, lng_b, lat_b) {
//以a点为原点建立局部坐标系(东方向为y轴,北方向为x轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵
// const localToWorld_Matrix = Cesium.Transforms.northEastDownToFixedFrame(
// new Cesium.Cartesian3.fromDegrees(lng_a, lat_a)
// );
//以a点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵
const localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(
new Cesium.Cartesian3.fromDegrees(lng_a, lat_a)
);
//求世界坐标到局部坐标的变换矩阵
const worldToLocal_Matrix = Cesium.Matrix4.inverse(
localToWorld_Matrix,
new Cesium.Matrix4()
);
//a点在局部坐标的位置,其实就是局部坐标原点
const localPosition_A = Cesium.Matrix4.multiplyByPoint(
worldToLocal_Matrix,
new Cesium.Cartesian3.fromDegrees(lng_a, lat_a),
new Cesium.Cartesian3()
);
//B点在以A点为原点的局部的坐标位置
const localPosition_B = Cesium.Matrix4.multiplyByPoint(
worldToLocal_Matrix,
new Cesium.Cartesian3.fromDegrees(lng_b, lat_b),
new Cesium.Cartesian3()
);
//弧度
// const angle = Math.atan2(
// localPosition_B.y - localPosition_A.y,
// localPosition_B.x - localPosition_A.x
// );
//弧度
const angle = Math.atan2(
localPosition_B.x - localPosition_A.x,
localPosition_B.y - localPosition_A.y
);
//角度
let theta = angle * (180 / Math.PI);
if (theta < 0) {
theta = theta + 360;
}
return theta;
}
class MeasureArea {
_state = new Map();
_layers = null;
_handler = null;
constructor(viewer) {
this._viewer = viewer;
}
draw() {
const { _viewer } = this;
const _handler = new Cesium.ScreenSpaceEventHandler(_viewer.scene.canvas);
const _layers = this._setLayers();
const _polygonHierarchy = new Cesium.PolygonHierarchy();
const _polygonEntity = this._polygonEntity(_polygonHierarchy);
const _positions = this._setPositions(_polygonEntity);
const _labelEntity = this._labelEntity();
const _areaLabelEntity = this._labelEntity();
_layers.entities.add(_polygonEntity);
_layers.entities.add(_labelEntity);
_layers.entities.add(_areaLabelEntity);
let _points = [];
_handler.setInputAction((e) => {
const position = _viewer.camera.pickEllipsoid(e.position);
if(!position) return;
if(_positions.length === 0) {
_positions.push(position.clone());
_polygonHierarchy.positions.push(position.clone());
}
_positions.push(position);
_polygonHierarchy.positions.push(position);
_points.push(this._addPoint(position, 0 + " m"));
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
_handler.setInputAction((e) => {
const position = _viewer.camera.pickEllipsoid(e.endPosition);
if(position && _positions.length > 0) {
_positions.splice(_positions.length - 1, 1, position);
_polygonHierarchy.positions.splice(_positions.length - 1, 1, position);
}
if(_positions.length === 0) {
_labelEntity.label.text = "点击左键绘制第一个点。";
}
if(_positions.length > 0) {
_labelEntity.label.text = "点击左键绘制下一个点,点击右键结束。";
}
if(_positions.length > 2) {
_areaLabelEntity.label.text = 0 + " ㎡";
_areaLabelEntity.position = this._getPolygonCenter(_polygonEntity.polygon);
}
if(position) {
_labelEntity.show = true;
_labelEntity.position = position;
}else {
_labelEntity.show = false;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
_handler.setInputAction((e) => {
_layers.entities.remove(_labelEntity);
if(_points.length < 3) {
_points.forEach(point => {
_layers.entities.remove(point);
});
_polygonEntity.polyline.positions = [];
_polygonHierarchy.positions = [];
}else {
_positions.pop();
_polygonHierarchy.positions.pop();
_positions.push(_positions[0]);
_polygonHierarchy.positions.push(_positions[0]);
_areaLabelEntity.position = this._getPolygonCenter(_polygonEntity.polygon);
}
this._handler.destroy();
this._handler = null;
_points = [];
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
this._handler = _handler;
this._layers = _layers;
}
clear() {
const { _viewer } = this;
if(this._handler) {
this._handler.destroy();
this._handler = null;
}
if(this._layers) {
_viewer.dataSources.remove(this._layers);
_viewer.entities.remove(this._layers)
this._layers = null;
}
this._state.clear();
}
_addPoint(position, distance) {
const { _viewer } = this;
const point = this._pointEntity(position, distance);
this._layers.entities.add(point);
return point;
}
_setPositions(_polygonEntity) {
const { _state } = this;
_state.set(_polygonEntity.id, []);
const positions = _state.get(_polygonEntity.id);
_polygonEntity.polyline.positions = new Cesium.CallbackProperty(() => {
return positions;
}, false);
return positions;
}
_setLayers() {
const { _viewer } = this;
let _layers = null;
if(!this._layers) {
_layers = new Cesium.CustomDataSource("distanceLayers");
_viewer.dataSources.add(_layers);
}else {
_layers = this._layers;
}
return _layers;
}
_polygonEntity(polygonHierarchy) {
return new Cesium.Entity({
name: "折线",
polyline: {
material: Cesium.Color.YELLOW,
width: 2
},
polygon: {
hierarchy: new Cesium.CallbackProperty(() => {
return polygonHierarchy;
}, false),
material: Cesium.Color.GREENYELLOW.withAlpha(0.5),
}
})
}
_pointEntity(position, text) {
return new Cesium.Entity({
name: "点",
position,
label: {
text,
showBackground: true,
font: '10px sans-serif',
pixelOffset: new Cesium.Cartesian2(0, -50)
},
point: {
pixelSize: 8,
color: Cesium.Color.YELLOW,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK
}
})
}
_labelEntity(position, text) {
return new Cesium.Entity({
name: "点",
position,
label: {
text,
showBackground: true,
font: '10px sans-serif',
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
},
})
}
_getPolygonCenter(polygon) {
const positions = polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;
return Cesium.BoundingSphere.fromPoints(positions).center;
}
}
class MeasureDistance {
_state = new Map();
_layers = null;
_handler = null;
constructor(viewer) {
this._viewer = viewer;
}
draw() {
const { _viewer } = this;
const _handler = new Cesium.ScreenSpaceEventHandler(_viewer.scene.canvas);
const _layers = this._setLayers();
const _polylineEntity = this._polylineEntity();
const _positions = this._setPositions(_polylineEntity);
const _labelEntity = this._labelEntity();
_layers.entities.add(_polylineEntity);
_layers.entities.add(_labelEntity);
let _currentPoint = null;
_handler.setInputAction((e) => {
const position = _viewer.camera.pickEllipsoid(e.position);
if(!position) return;
if(_positions.length === 0) _positions.push(position.clone());
_positions.push(position);
_currentPoint = this._addPoint(position, 0 + " m");
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
_handler.setInputAction((e) => {
const position = _viewer.camera.pickEllipsoid(e.endPosition);
if(position && _positions.length > 0) _positions.splice(_positions.length - 1, 1, position);
if(_positions.length === 0) {
_labelEntity.label.text = "点击左键绘制第一个点。";
}else if(_positions.length > 0) {
_labelEntity.label.text = "点击左键绘制下一个点,点击右键结束。";
}
if(position) {
_labelEntity.show = true;
_labelEntity.position = position;
}else {
_labelEntity.show = false;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
_handler.setInputAction((e) => {
if(_positions.length > 0) _positions.pop();
if(_positions.length === 1 && _currentPoint) _viewer.entities.remove(_currentPoint);
_layers.entities.remove(_labelEntity);
this._handler.destroy();
this._handler = null;
_currentPoint = null;
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
this._handler = _handler;
this._layers = _layers;
}
clear() {
const { _viewer } = this;
if(this._handler) {
this._handler.destroy();
this._handler = null;
}
if(this._layers) {
_viewer.dataSources.remove(this._layers);
_viewer.entities.remove(this._layers)
this._layers = null;
}
this._state.clear();
}
_addPoint(position, distance) {
const { _viewer } = this;
const point = this._pointEntity(position, distance);
this._layers.entities.add(point);
return point;
}
_setPositions(_polylineEntity) {
const { _state } = this;
_state.set(_polylineEntity.id, []);
const positions = _state.get(_polylineEntity.id);
_polylineEntity.polyline.positions = new Cesium.CallbackProperty(() => {
return positions;
}, false)
return positions;
}
_setLayers() {
const { _viewer } = this;
let _layers = null;
if(!this._layers) {
_layers = new Cesium.CustomDataSource("distanceLayers");
_viewer.dataSources.add(_layers);
}else {
_layers = this._layers;
}
return _layers;
}
_polylineEntity() {
return new Cesium.Entity({
name: "折线",
polyline: {
material: Cesium.Color.YELLOW,
width: 2
}
})
}
_pointEntity(position, text) {
return new Cesium.Entity({
name: "点",
position,
label: {
text,
showBackground: true,
font: '10px sans-serif',
pixelOffset: new Cesium.Cartesian2(0, -50)
},
point: {
pixelSize: 8,
color: Cesium.Color.YELLOW,
outlineWidth: 2,
outlineColor: Cesium.Color.BLACK
}
})
}
_labelEntity(position, text) {
return new Cesium.Entity({
name: "点",
position,
label: {
text,
showBackground: true,
font: '10px sans-serif',
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
},
})
}
}
var distance = new MeasureDistance(viewer);
var area = new MeasureArea(viewer);
var angle = new MeasureAngle(viewer);
网友评论