美文网首页
Cesium基本图形绘制

Cesium基本图形绘制

作者: 写前端的大叔 | 来源:发表于2021-06-13 20:55 被阅读0次

    之前用openlayers开发二维地图的时候,绘制线矩形椭圆是基本的功能,所以在cesium地图中也可以加入这些功能。将常用的绘制功能进行了封装,绘制线比较简单,创建Entity实例,传入对应的坐标就可以绘制出来,具体的代码将在最后贴出来。下面主要界面下矩形椭圆的绘制思路。平台还在努力开发中,可以先预览下效果。cgis

    1.绘制圆

    绘制圆需要借助turf.js这个框架,圆绘制的原理其实就是绘制多边形,绘制步骤如下所示:

    1.点击地图,记录点击的位置作为圆心,记为A点。
    2.移动鼠标,再点击地图,记录该点作为圆弧上的点,记为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.移动鼠标,再点击地图,记录该点作为右下角,记为B点。
    3.根据A点和B的经纬度坐标分别求出右上角和左下角的坐标。
    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.移动鼠标,再点击地图,记录该点作为圆弧上的点,记为B点。
    3.使用turf.distance计算AB两点的距离,可以求出圆的半径,做为X轴上的半径。
    4.根据X轴的半径计算Y轴的半径,只需将Y轴上的半径设置成小于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;
        }
    

    为了方便使用,将绘制基本图形的代码全部进行了封装:

    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();
    

    相关文章

      网友评论

          本文标题:Cesium基本图形绘制

          本文链接:https://www.haomeiwen.com/subject/vcjysltx.html