Cesium使用鼠标动态绘制椭圆(附带绘制帮助提示语)

实现鼠标动态绘制椭圆的类EllipseDraw

实现思路是:椭圆绘制是基于矩形绘制的基础,因为椭圆长半轴和短半轴实际上就是矩形长和宽,所以核心还是绘制左上和右下两个点,然后计算出椭圆的中心店,以及长短半轴的值,以此实现动态绘制椭圆。
实现代码如下:

import CesiumByZh from "../CesiumByZh";
import GlobalListener from "../GlobalListener";

export default class EllipseDraw {
    public canvas = CesiumByZh.viewer.scene.canvas;
    public camera = CesiumByZh.viewer.scene.camera;
    public ellipsoid = CesiumByZh.viewer.scene.globe.ellipsoid;
    public viewer = CesiumByZh.viewer;
    public scene = CesiumByZh.viewer.scene;
    protected positions: any[] = [];
    protected position: any = CesiumByZh.Cesium.Cartesian3.fromDegrees(103, 30, 100);
    protected dragIconLight: string = "./Images/circle_red.png";
    protected shapeEntity: any;
    protected okHandler: any;
    protected cancelHandler: any;
    protected handler: any;
    protected modifyHandler: any;
    protected mousePosition: any[] = [];
    protected result: any;
    public pointEntityArray: any[] = [];

    beginDraw() {
        this.handler = new CesiumByZh.Cesium.ScreenSpaceEventHandler(this.canvas);
        this.handler.setInputAction((event: any) => {
            let position = event.position;
            if (!CesiumByZh.Cesium.defined(position)) {
                return;
            }
            let ray = this.camera.getPickRay(position);
            if (!CesiumByZh.Cesium.defined(ray)) {
                return;
            }
            let cartesian = this.scene.globe.pick(ray, this.scene);
            if (!CesiumByZh.Cesium.defined(cartesian)) {
                return;
            }
            let num = this.positions.length;
            if (num == 0) {
                this.positions.push(cartesian);
                this.createTemporaryShape();
            }
            this.positions.push(cartesian);
            this.pointEntityArray.push(this._createPoint(cartesian));
            if (num > 1) {
                this.positions.pop();
            }
        }, CesiumByZh.Cesium.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.setInputAction((event: any) => {
            let position = event.endPosition;
            if (!CesiumByZh.Cesium.defined(position)) {
                return;
            }
            let ray = this.camera.getPickRay(position);
            if (!CesiumByZh.Cesium.defined(ray)) {
                return;
            }
            let cartesian = this.scene.globe.pick(ray, this.scene);
            if (!CesiumByZh.Cesium.defined(cartesian)) {
                return;
            }
            if (this.positions.length == 0) {
                GlobalListener.getInstance().runTipsCallback(['单击开始绘制,右键取消']);
                return
            } else {
                GlobalListener.getInstance().runTipsCallback(['单击完成绘制,右键回退']);
            }
            this.positions.pop();
            this.positions.push(cartesian);
        }, CesiumByZh.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.setInputAction((movement: any) => {
            if (this.positions.length == 0) {
                //重新开始绘制
            } else {
                if (this.positions.length == 2) {
                    this.positions = [];
                    if (this.shapeEntity != null) {
                        CesiumByZh.viewer.entities.remove(this.shapeEntity);
                        this.shapeEntity = null;
                    }
                } else {
                    this.positions.splice(this.positions.length - 2, 1);
                }
                CesiumByZh.viewer.entities.remove(this.pointEntityArray[this.pointEntityArray.length - 1]);
                this.pointEntityArray.pop();
            }
        }, CesiumByZh.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    }

    _createPoint(cartesian: any) {
        let point = CesiumByZh.viewer.entities.add({
            position: cartesian,
            billboard: {
                image: this.dragIconLight,
                eyeOffset: new CesiumByZh.Cesium.ConstantProperty(new CesiumByZh.Cesium.Cartesian3(0, 0, -500)),
                heightReference: CesiumByZh.Cesium.HeightReference.CLAMP_TO_GROUND
            }
        });
        return point;
    }

    //创建实体
    createTemporaryShape() {
        let outlineDynamicPositions = new CesiumByZh.Cesium.CallbackProperty(() => {
            if (this.positions.length > 1) {
                let rect = CesiumByZh.Cesium.Rectangle.fromCartesianArray(this.positions);
                let arr = [rect.west, rect.north, rect.east, rect.north, rect.east, rect.south, rect.west, rect.south, rect.west, rect.north];
                return CesiumByZh.Cesium.Cartesian3.fromRadiansArray(arr);
            } else {
                return null;
            }
        }, false);
        this.shapeEntity = CesiumByZh.viewer.entities.add({
            canSelect: false,
            position: new CesiumByZh.Cesium.CallbackProperty(() => {
                if (this.positions.length > 1) {
                    let posi = [this.positions[0], this.positions[1]];
                    return this._computeEllipsePosition(posi);
                } else {
                    return null;
                }
            }, false),
            ellipse: {
                height: undefined,
                semiMajorAxis: new CesiumByZh.Cesium.CallbackProperty(() => {
                    if (this.positions.length > 1) {
                        let posi = [this.positions[0], this.positions[1]];
                        let dis = this._computeEllipseRadius3D(posi);
                        if (dis) {
                            if (dis.chang < 100) {
                                return null
                            } else {
                                return Number(dis.chang / 2);
                            }
                        } else {
                            return null;
                        }
                    } else {
                        return null;
                    }
                }, false),
                semiMinorAxis: new CesiumByZh.Cesium.CallbackProperty(() => {
                    if (this.positions.length > 1) {
                        let posi = [this.positions[0], this.positions[1]];
                        let dis = this._computeEllipseRadius3D(posi);
                        if (dis) {
                            if (dis.duan < 100) {
                                return null
                            } else {
                                return Number(dis.duan / 2);
                            }
                        } else {
                            return null;
                        }
                    } else {
                        return null;
                    }
                }, false),
                material: CesiumByZh.Cesium.Color.fromCssColorString('#F60').withAlpha(0.5),
            },
            polyline: {
                positions: outlineDynamicPositions,
                clampToGround: true,
                width: 2,
                material: CesiumByZh.Cesium.Color.fromCssColorString('#F60').withAlpha(0.5),
            }
        });
    }

    //通过矩形的对角顶点计算矩形的中心点位置(也可用于计算椭圆的圆心)
    _computeEllipsePosition(positions: any[]) {
        let c1: any = positions[0];
        let c2: any = positions[1];
        let c3: any = {};
        c3.x = (c1.x + c2.x) / 2;
        c3.y = (c1.y + c2.y) / 2;
        c3.z = (c1.z + c2.z) / 2;
        return c3;
    }

    //通过矩形的对角顶点计算矩形长宽(也可用于计算椭圆的长半轴和短半轴,为计算的长宽的一半)
    _computeEllipseRadius3D(positions: any[]) {
        let rect = CesiumByZh.Cesium.Rectangle.fromCartesianArray(positions);
        //console.log('rect',rect);
        let arr = [rect.west, rect.north, rect.east, rect.north, rect.east, rect.south, rect.west, rect.south, rect.west, rect.north];
        let outlinePositions = CesiumByZh.Cesium.Cartesian3.fromRadiansArray(arr);
        let c1 = outlinePositions[0];
        let c2 = outlinePositions[1];
        let c3 = outlinePositions[3];
        let x = Math.pow(c1.x - c2.x, 2);
        let y = Math.pow(c1.y - c2.y, 2);
        let z = Math.pow(c1.z - c2.z, 2);
        let dis = Math.sqrt(x + y + z);
        let x1 = Math.pow(c1.x - c3.x, 2);
        let y1 = Math.pow(c1.y - c3.y, 2);
        let z1 = Math.pow(c1.z - c3.z, 2);
        let dis1 = Math.sqrt(x1 + y1 + z1);
        let p: any = {};
        if (dis >= dis1) {
            p.chang = dis;
            p.duan = dis1;
            p.rotation = 0;
        } else {
            p.chang = dis1;
            p.duan = dis;
            p.rotation = 90;
        }
        return p;
    }
}
抱歉,作为AI言模型,我不能提供代码。但我可以给你一些思路和建议。要在cesium使用鼠标动态绘制曲线,你需要以下步骤: 1. 监听鼠标点击事件,获取鼠标在地球上的位置。 2. 将鼠标点击的位置转换成笛卡尔坐标系。 3. 将笛卡尔坐标系转换成经纬度坐标系。 4. 将经纬度坐标系转换成cesium中的Cartesian3坐标系。 5. 将Cartesian3坐标系坐标添加到cesium的Entity对象中,以便可以动态绘制曲线。 6. 使用cesium的PolylineGraphics对象设置曲线的样式、颜色等属性。 以下是一个示例代码片段,仅供参考: ```javascript var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); var linePositions = []; handler.setInputAction(function (click) { // 获取鼠标点击位置的笛卡尔坐标系 var cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid); if (cartesian) { // 将笛卡尔坐标系转换成经纬度坐标系 var cartographic = Cesium.Cartographic.fromCartesian(cartesian); // 将经纬度坐标系转换成cesium的Cartesian3坐标系 var position = Cesium.Cartesian3.fromDegrees(cartographic.longitude, cartographic.latitude, cartographic.height); linePositions.push(position); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); var entity = viewer.entities.add({ polyline: { positions: linePositions, width: 5, material: Cesium.Color.RED } }); ``` 这段代码监听了鼠标左键点击事件,获取鼠标点击位置的坐标系,并将其添加到linePositions数组中。然后使用这个数组创建了一个PolylineGraphics对象,设置了线条的颜色和宽度,并将其添加到了cesium的Entity对象中,以便可以动态绘制曲线。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sannianerban12138

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值