之前用openlayers
開發(fā)二維地圖的時候,繪制點、線惨好、面、圓义辕、矩形、橢圓是基本的功能寓盗,所以在cesium
地圖中也可以加入這些功能灌砖。將常用的繪制功能進(jìn)行了封裝,繪制點傀蚌、線基显、面比較簡單,創(chuàng)建Entity
實例善炫,傳入對應(yīng)的坐標(biāo)就可以繪制出來撩幽,具體的代碼將在最后貼出來。下面主要界面下圓、矩形窜醉、橢圓的繪制思路宪萄。平臺還在努力開發(fā)中,可以先預(yù)覽下效果榨惰。cgis
1.繪制圓
繪制圓需要借助turf.js
這個框架拜英,圓繪制的原理其實就是繪制多邊形,繪制步驟如下所示:
1.點擊地圖琅催,記錄點擊的位置作為圓心居凶,記為A點。
2.移動鼠標(biāo)藤抡,再點擊地圖排监,記錄該點作為圓弧上的點,記為B點杰捂。
3.使用turf.distance
計算AB兩點的距離,可以求出圓的半徑棋蚌。
4.使用turf.circle
繪制一個360份的圓嫁佳,既可求出360個點。
5.用這360個點繪制一個多邊形谷暮。
createCirclePoints(point){
let startPoint = this.points[0];
let startLon = parseFloat(startPoint.longitude);
let startLat = parseFloat(startPoint.latitude);
let endLon = parseFloat(point.longitude);
let endLat = parseFloat(point.latitude);
if(startLon === endLon && startLat === endLat)return;
let clickPoint = [endLon,endLat];
let distanceOptions = {units: 'kilometers'};
let distance = turf.distance( [startLon,startLat],clickPoint, distanceOptions);
let options = {steps: 360, units: 'kilometers', properties: {foo: 'bar'}};
let circleFeatures = turf.circle([startLon,startLat], distance, options);
let coordinates = circleFeatures.geometry.coordinates[0];
let points = [];
coordinates.forEach(item => {
points.push({longitude:item[0],latitude:item[1]});
});
return points;
}
2.繪制矩形
繪制矩形比較簡單蒿往,通過兩點就可以繪制一個矩形,繪制步驟如下所示:
1.點擊地圖湿弦,記錄點擊的位置作為左上角瓤漏,記為A點。
2.移動鼠標(biāo)颊埃,再點擊地圖蔬充,記錄該點作為右下角,記為B點班利。
3.根據(jù)A點和B的經(jīng)緯度坐標(biāo)分別求出右上角和左下角的坐標(biāo)饥漫。
4.將4個點繪制成一個多邊形。
createRectanglePoints(point){
let startPoint = this.points[0];
let points = [startPoint];
let startLon = startPoint.longitude;
let startLat = startPoint.latitude;
let endLon = point.longitude;
let endLat = point.latitude;
if(startLon === endLon && startLat === endLat)return;
points.push({longitude:endLon,latitude:startLat});
points.push({longitude:endLon,latitude:endLat});
points.push({longitude:startLon,latitude:endLat});
return points;
}
3.繪橢圓
繪制橢圓也需要借助turf.js
這個框架罗标,橢圓繪制的原理跟圓類似庸队,只是多了一個Y軸上的半徑,繪制步驟如下所示:
1.點擊地圖闯割,記錄點擊的位置作為圓心彻消,記為A點。
2.移動鼠標(biāo)宙拉,再點擊地圖宾尚,記錄該點作為圓弧上的點,記為B點鼓黔。
3.使用turf.distance
計算AB兩點的距離央勒,可以求出圓的半徑不见,做為X軸上的半徑。
4.根據(jù)X軸的半徑計算Y軸的半徑崔步,只需將Y軸上的半徑設(shè)置成小于X軸的半徑就行了稳吮。
5.使用turf.ellipse
繪制一個360份的橢圓,既可求出360個點井濒。
6.用這360個點繪制一個多邊形灶似。
createEllipsePoints(point){
let startPoint = this.points[0];
let startLon = parseFloat(startPoint.longitude);
let startLat = parseFloat(startPoint.latitude);
let endLon = parseFloat(point.longitude);
let endLat = parseFloat(point.latitude);
let center = [startLon,startLat];
if(startLon === endLon && startLat === endLat)return;
let endPoint = [endLon,endLat];
let distanceOptions = {units: 'kilometers'};
let xSemiAxis = turf.distance(center,endPoint, distanceOptions);
let ySemiAxis = xSemiAxis - xSemiAxis * 0.2;
let ellipse = turf.ellipse(center, xSemiAxis, ySemiAxis,{
steps:360
});
let coordinates = ellipse.geometry.coordinates[0];
let points = [];
coordinates.forEach(item => {
points.push({longitude:item[0],latitude:item[1]});
});
return points;
}
為了方便使用,將繪制基本圖形的代碼全部進(jìn)行了封裝:
import * as Cesium from '@/Cesium/Source/Cesium';
import Cgis3DEvent from '@/cgis3d/core/Event';
import * as turf from '@turf/turf'
class DrawTool {
constructor(){
this.entities = [];
this.tempEntities = [];
this.commandDict = {
CLEAR:this.clear,
POINT:this.drawPoint,
LINE:this.drawLine,
POLYGON:this.drawPolygon,
CIRCLE:this.drawCircle,
RECTANGLE:this.drawRectangle,
ELLIPSE:this.drawEllipse
};
this.commandDictTemp = {
LINE:this.drawTempLine,
POLYGON:this.drawTempPolygon,
RECTANGLE:this.drawTempRectangle,
CIRCLE:this.drawTempCircle,
ELLIPSE:this.drawTempEllipse
}
this.type = null;
this.points = [];
}
command(type){
if(type === 'CLEAR'){
this.clear();
}else{
this.type = type;
this.addEvent();
this.startDraw();
}
}
clear(){
this.entities.forEach(entity => {
cgis3d.viewer.entities.remove(entity);
})
}
clearTempEntities(){
this.tempEntities.forEach(entity => {
cgis3d.viewer.entities.remove(entity);
})
}
drawPoint(position){
let entity = new Cesium.Entity({
position:new Cesium.Cartesian3.fromDegrees(parseFloat(position.longitude), parseFloat(position.latitude)),
point:new Cesium.PointGraphics({
pixelSize:20,
heightReference:20,
color:Cesium.Color.RED,
outlineColor:Cesium.Color.BLUE
})
});
this.entities.push(entity);
cgis3d.viewer.entities.add(entity);
this.endDraw();
}
drawLine(point){
this.clear();
this.points.push(point);
if(this.points.length < 2){
return;
}
this.clearTempEntities();
let line = this.createLine(this.points);
cgis3d.viewer.entities.add(line);
this.entities.push(line);
}
drawTempLine(point){
this.clearTempEntities();
if(this.points.length < 1){
return;
}
let line = this.createLine([this.points[this.points.length -1],point]);
cgis3d.viewer.entities.add(line);
this.tempEntities.push(line);
}
createLine(points){
let positions = [];
points.forEach(item => {
positions.push(new Cesium.Cartesian3.fromDegrees(parseFloat(item.longitude), parseFloat(item.latitude)));
});
let line = new Cesium.Entity({
polyline:new Cesium.PolylineGraphics({
positions : positions,
material:Cesium.Color.RED.withAlpha(0.5),
width:5,
})
});
return line;
}
drawPolygon(point){
this.clear();
this.points.push(point);
if(this.points.length < 3){
this.drawTempLine(point);
return;
}
this.clearTempEntities();
let polygon = this.createPolygon(this.points);
cgis3d.viewer.entities.add(polygon);
this.entities.push(polygon);
}
drawTempPolygon(point){
this.clearTempEntities();
if(this.points.length <= 2){
this.drawTempLine(point);
return;
}
let points = [].concat(this.points);
points.push(point);
let polygon = this.createPolygon(points);
cgis3d.viewer.entities.add(polygon);
this.tempEntities.push(polygon);
}
createPolygon(points){
points = [].concat(points);
points.push(points[0]);
let positions = [];
points.forEach(item => {
positions.push(new Cesium.Cartesian3.fromDegrees(parseFloat(item.longitude), parseFloat(item.latitude)));
});
let polygon = new Cesium.Entity({
name:'多邊形',
description:"這是描述信息",
polygon:new Cesium.PolygonGraphics({
hierarchy : new Cesium.PolygonHierarchy(positions),
material:Cesium.Color.RED.withAlpha(0.5),
outline:true,
outlineColor:Cesium.Color.BLUE,
outlineWidth:5,
})
});
return polygon;
}
drawCircle(point){
this.clear();
if(this.points.length < 1){
this.points.push(point);
return;
}else{
let points = this.createCirclePoints(point);
if(!points)return;
this.points = [].concat(points)
}
this.clearTempEntities();
let polygon = this.createPolygon(this.points);
cgis3d.viewer.entities.add(polygon);
this.entities.push(polygon);
this.endDraw();
}
drawTempCircle(point){
this.clearTempEntities();
if(this.points.length < 1){
return;
}else{
let points = this.createCirclePoints(point);
if(!points)return;
let polygon = this.createPolygon([].concat(points));
cgis3d.viewer.entities.add(polygon);
this.tempEntities.push(polygon);
}
}
createCirclePoints(point){
let startPoint = this.points[0];
let startLon = parseFloat(startPoint.longitude);
let startLat = parseFloat(startPoint.latitude);
let endLon = parseFloat(point.longitude);
let endLat = parseFloat(point.latitude);
if(startLon === endLon && startLat === endLat)return;
let clickPoint = [endLon,endLat];
let distanceOptions = {units: 'kilometers'};
let distance = turf.distance( [startLon,startLat],clickPoint, distanceOptions);
let options = {steps: 360, units: 'kilometers', properties: {foo: 'bar'}};
let circleFeatures = turf.circle([startLon,startLat], distance, options);
let coordinates = circleFeatures.geometry.coordinates[0];
let points = [];
coordinates.forEach(item => {
points.push({longitude:item[0],latitude:item[1]});
});
return points;
}
drawRectangle(point){
this.clear();
if(this.points.length < 1){
this.points.push(point);
return;
}else{
let points = this.createRectanglePoints(point);
if(!points)return;
this.points = [].concat(points)
}
this.clearTempEntities();
let polygon = this.createPolygon(this.points);
cgis3d.viewer.entities.add(polygon);
this.entities.push(polygon);
this.endDraw();
}
drawTempRectangle(point){
this.clearTempEntities();
if(this.points.length < 1){
return;
}else{
let points = this.createRectanglePoints(point);
if(!points)return;
let polygon = this.createPolygon([].concat(points));
cgis3d.viewer.entities.add(polygon);
this.tempEntities.push(polygon);
}
}
createRectanglePoints(point){
let startPoint = this.points[0];
let points = [startPoint];
let startLon = startPoint.longitude;
let startLat = startPoint.latitude;
let endLon = point.longitude;
let endLat = point.latitude;
if(startLon === endLon && startLat === endLat)return;
points.push({longitude:endLon,latitude:startLat});
points.push({longitude:endLon,latitude:endLat});
points.push({longitude:startLon,latitude:endLat});
return points;
}
drawEllipse(point){
this.clear();
if(this.points.length < 1){
this.points.push(point);
return;
}else{
let points = this.createEllipsePoints(point);
if(!points)return;
this.points = [].concat(points)
}
this.clearTempEntities();
let polygon = this.createPolygon(this.points);
cgis3d.viewer.entities.add(polygon);
this.entities.push(polygon);
this.endDraw();
}
drawTempEllipse(point){
this.clearTempEntities();
if(this.points.length < 1){
return;
}else{
let points = this.createEllipsePoints(point);
if(!points)return;
let polygon = this.createPolygon([].concat(points));
cgis3d.viewer.entities.add(polygon);
this.tempEntities.push(polygon);
}
}
createEllipsePoints(point){
let startPoint = this.points[0];
let startLon = parseFloat(startPoint.longitude);
let startLat = parseFloat(startPoint.latitude);
let endLon = parseFloat(point.longitude);
let endLat = parseFloat(point.latitude);
let center = [startLon,startLat];
if(startLon === endLon && startLat === endLat)return;
let endPoint = [endLon,endLat];
let distanceOptions = {units: 'kilometers'};
let xSemiAxis = turf.distance(center,endPoint, distanceOptions);
let ySemiAxis = xSemiAxis - xSemiAxis * 0.2;
let ellipse = turf.ellipse(center, xSemiAxis, ySemiAxis,{
steps:360
});
let coordinates = ellipse.geometry.coordinates[0];
let points = [];
coordinates.forEach(item => {
points.push({longitude:item[0],latitude:item[1]});
});
return points;
}
addEvent(){
DrawTool.cgs3dEvent = DrawTool.cgs3dEvent || new Cgis3DEvent(cgis3d.viewer);
DrawTool.cgs3dEvent.on(Cgis3DEvent.LEFT_CLICK,this.leftClickHandler.bind(this));
DrawTool.cgs3dEvent.on(Cgis3DEvent.LEFT_DOUBLE_CLICK,this.leftDoubleClickHandler.bind(this));
DrawTool.cgs3dEvent.on(Cgis3DEvent.MOUSE_MOVE,this.mouseMoveHandler.bind(this));
}
removeEvent(){
DrawTool.cgs3dEvent.off(Cgis3DEvent.LEFT_CLICK,this.leftClickHandler);
DrawTool.cgs3dEvent.off(Cgis3DEvent.LEFT_DOUBLE_CLICK,this.leftDoubleClickHandler);
DrawTool.cgs3dEvent.off(Cgis3DEvent.MOUSE_MOVE,this.mouseMoveHandler);
}
leftClickHandler(movement){
movement.endPosition = movement.endPosition || movement.position;
const result = DrawTool.cgs3dEvent.getLocationInfo(movement);
if(result){
let fn = this.commandDict[this.type];
if(fn instanceof Function){
fn.call(this,result);
}
}
}
mouseMoveHandler(movement){
movement.endPosition = movement.endPosition || movement.position;
const result = DrawTool.cgs3dEvent.getLocationInfo(movement);
if(result){
let fn = this.commandDictTemp[this.type];
if(fn instanceof Function){
fn.call(this,result);
}
}
}
startDraw(){
this.clear();
this.points = [];
window.document.body.style.cursor = 'crosshair'
}
endDraw(){
window.document.body.style.cursor = 'default'
this.removeEvent();
this.clearTempEntities()
}
leftDoubleClickHandler(){
this.endDraw();
}
}
export default new DrawTool();