Cesium基本圖形繪制

之前用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();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瑞你,一起剝皮案震驚了整個濱河市酪惭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌者甲,老刑警劉巖春感,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異虏缸,居然都是意外死亡鲫懒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門刽辙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窥岩,“玉大人,你說我怎么就攤上這事宰缤∷桃恚” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵慨灭,是天一觀的道長朦乏。 經(jīng)常有香客問我,道長氧骤,這世上最難降的妖魔是什么集歇? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮语淘,結(jié)果婚禮上诲宇,老公的妹妹穿的比我還像新娘。我一直安慰自己惶翻,他們只是感情好姑蓝,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吕粗,像睡著了一般纺荧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天宙暇,我揣著相機(jī)與錄音输枯,去河邊找鬼。 笑死占贫,一個胖子當(dāng)著我的面吹牛桃熄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播型奥,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼瞳收,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了厢汹?” 一聲冷哼從身側(cè)響起螟深,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烫葬,沒想到半個月后界弧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡搭综,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年夹纫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片设凹。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖茅姜,靈堂內(nèi)的尸體忽然破棺而出闪朱,到底是詐尸還是另有隱情,我是刑警寧澤钻洒,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布奋姿,位于F島的核電站,受9級特大地震影響素标,放射性物質(zhì)發(fā)生泄漏称诗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一头遭、第九天 我趴在偏房一處隱蔽的房頂上張望寓免。 院中可真熱鬧,春花似錦计维、人聲如沸袜香。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜈首。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間欢策,已是汗流浹背吆寨。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留踩寇,地道東北人啄清。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像姑荷,于是被迫代替她去往敵國和親盒延。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344