cesium剖面分析

cesium剖面分析


什么是剖面分析

剖面分析是指根据指定的剖面线,输出剖面线与地形数据的表面高程沿某条线(截面)的变化,或剖面线所截的模型建筑物、地下管线等的轮廓线,通过剖面分析可以分析三维表面的高程变化情况。

实现思路

本文采用Cesium + Echarts,并基于地形数据来实现剖面分析,实现思路的具体步骤如下:

  1. 加载地形(这一步是前提条件,需要成功加载地形之后才可进行剖面分析);
  2. 在地形上选取两个高程不同的点,获取到它们的坐标数据,并将其绘制出来;
  3. 根据获取到的两个坐标点,绘制贴地线;
  4. 根据获取到的两个坐标点进行插值运算输出多个点(取样点的个数可自定义,个数越大越精确,但耗费的计算时间也越多);
  5. 根据地形获取到这些坐标点所在的高度,并将这些点存到数组;
  6. 将数组的数据渲染到Echarts图表上,形成剖面图。

实现代码

由于剖面分析这个功能比较偏向于工具,且较为独立,因此将其封装成一个独立的工具类ts文件来集成相关代码,便于后续直接导入使用。

import * as echarts from 'echarts';
import {
    Viewer,
    ScreenSpaceEventHandler,
    GroundPrimitive,
    GeometryInstance,
    CorridorGeometry,
    VertexFormat,
    ColorGeometryInstanceAttribute,
    Color,
    ClassificationType,
    ScreenSpaceEventType,
    Math,
    createWorldTerrain,
    Cartographic,
    sampleTerrainMostDetailed,
    Cartesian3,
    PointPrimitiveCollection
} from 'cesium';

/** 剖面分析 */
export default class ProfileAnalysis {

    private viewer: Viewer;

    /** 场景操作 */
    private handler: ScreenSpaceEventHandler;

    /** 用于加载图表的HTMLElement */
    private echartRef: any

    /** 点的可渲染集合 */
    private pointCollection: PointPrimitiveCollection;

    /** 贴地几何 */
    private groundPrimitive: GroundPrimitive[] | null = [];

    constructor(viewer: Viewer, echartRef: any) {
        this.viewer = viewer;
        this.handler = new ScreenSpaceEventHandler(this.viewer.scene.canvas);
        this.echartRef = echartRef;
        this.pointCollection = new PointPrimitiveCollection();
        this.viewer.scene.primitives.add(this.pointCollection)
    }

    /** 取点 */
    private positions: Cartesian3[] = [];

    /**
     * @name: start
     * @Date: 2022-09-27 17:34:15
     * @description: 开始剖面分析
     */
    public start() {
        this.handler.setInputAction((click) => {
            const ray = this.viewer.camera.getPickRay(click.position);
            const cartesian = this.viewer.scene.globe.pick(ray!, this.viewer.scene);
            console.log('取点', cartesian);
            this.pointCollection.add({
                position: cartesian,
                color: Color.YELLOW,
                pixelSize: 10
            })
            this.positions.push(cartesian!)
            const length = this.positions.length
            if (length >= 2) {
                // 绘制贴地线
                let lineInstance = new GeometryInstance({
                    geometry: new CorridorGeometry({
                        vertexFormat: VertexFormat.POSITION_ONLY,
                        positions: [this.positions[length - 1], this.positions[length - 2]],
                        width: 10
                    }),
                    attributes: {
                        color: ColorGeometryInstanceAttribute.fromColor(new Color(0.0, 1.0, 0.0, 0.5))
                    }
                })
                let groundPrimitive = new GroundPrimitive({
                    geometryInstances: lineInstance,
                    classificationType: ClassificationType.TERRAIN
                });
                this.groundPrimitive?.push(groundPrimitive)
                this.viewer.scene.primitives.add(groundPrimitive);
                // 插值运算
                this.interPoints(this.positions)
            }
        }, ScreenSpaceEventType.LEFT_CLICK)
    }

    /**
     * @name: stop
     * @Date: 2022-09-28 09:54:08
     * @description: 结束剖面分析
     */
    public stop() {
        // 清除鼠标左键单击事件
        this.handler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK);
        // 清除剖面图
        this.disposeChart();
        // 清除取点
        this.positions = [];
        // 清除插值点
        this.interData = [];
        // 清除绘制的点和线
        // this.viewer.scene.primitives.remove(this.groundPrimitive);
        for (let i = 0; i < this.groundPrimitive!.length; i++) {
            this.viewer.scene.primitives.remove(this.groundPrimitive![i]);
        }
        this.viewer.scene.primitives.remove(this.pointCollection);
    }

    /** 插值点 */
    private interData: [number, number][] = [];

    /**
     * @name: interPoints
     * @Date: 2022-09-27 17:24:02
     * @description: 坐标点插值positionsDegrees
     * @param {any} positions 坐标点数组
     * @param {number} interNumber 取样点个数
     */
    private interPoints(positions: any, interNumber: number = 10) {
        const posDegrees = [];
        for (let index = 0; index < positions.length; index++) {
            const element = positions[index];
            const ellipsoid = this.viewer.scene.globe.ellipsoid;
            const cartographic = ellipsoid.cartesianToCartographic(element);
            let x = Math.toDegrees(cartographic.longitude)
            let y = Math.toDegrees(cartographic.latitude)
            let data = { longitude: x, latitude: y }
            posDegrees.push(data);
        }
        console.log('转换成经纬度的点', posDegrees);
        let offset, x, y;
        for (let i = 0; i < interNumber; ++i) {
            offset = i / (interNumber - 1);
            // 做插值
            x = Math.lerp(posDegrees[posDegrees.length - 2].longitude, posDegrees[posDegrees.length - 1].longitude, offset);
            y = Math.lerp(posDegrees[posDegrees.length - 2].latitude, posDegrees[posDegrees.length - 1].latitude, offset);
            this.interData.push([x, y]);
        }
        console.log('插值点', this.interData);
        // 查询地图的地形高度
        const terrainProvider = createWorldTerrain({
            requestVertexNormals: true
        })
        let interDataMap = this.interData.map((d: [number, number]) => Cartographic.fromDegrees(...d))
        // 根据地形和经纬度计算出高度
        sampleTerrainMostDetailed(terrainProvider, interDataMap)
            .then(positions => {
                const heightList = positions.map((d: any) => ({
                    height: d.height,
                    longitude: Math.toDegrees(d.longitude),
                    latitude: Math.toDegrees(d.latitude)
                }))
                console.log('剖面分析结果', heightList)
                // 生成剖面图
                this.initChart(heightList)
            })
    }

    /**
     * @name: initChart
     * @Date: 2022-09-28 09:12:39
     * @description: 生成剖面图
     * @param {any} data 高程数组
     */
    private initChart(data: any) {
        console.log('生成剖面图');
        this.disposeChart();
        let myChart = echarts.init(this.echartRef, "dark");
        let labelList = []
        for (let i = 1; i <= data.length; i++) {
            labelList.push(i);
        }
        myChart.setOption({
            xAxis: {
                type: "category",
                data: labelList
            },
            tooltip: {
                trigger: "axis"
            },
            yAxis: {
                type: "value"
            },
            series: [
                {
                    data: data.map((e: any) => {
                        return e.height;
                    }),
                    type: "line",
                    smooth: true
                }
            ]
        });
        window.onresize = () => {
            myChart.resize();
        };
    }

    /**
     * @name: disposeChart
     * @Date: 2022-09-28 09:42:46
     * @description: 销毁剖面图
     */
    public disposeChart() {
        echarts.dispose(this.echartRef);
    }

}
使用方法:引入剖面分析类文件,实例化后即可使用该功能。
// 引入类文件
import ProfileAnalysis from '@utils/cesium/tools/profileAnalysis';
// 实例化,参数分别为cesium的viewer对象和渲染图表的容器dom
const profile = new ProfileAnalysis(viewer, echartsRef.value);
// 开始剖面分析
profile.start();
// 销毁剖面图
profile.disposeChart();
// 结束剖面分析
profile.stop();
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Cesium剖面分析是一种利用离子轨迹法研究材料剖面结构的分析方法。在这个过程中,通过将样品暴露于一个具有较高能量的离子束中,离子束会与样品表面的原子发生相互作用,引起剖面的改变。剖面形成过程中会发生离子在材料中的输运和沉积,从而形成一个复杂的剖面结构。 cesium剖面分析的原理是通过控制离子辐照能量、剂量和离子束的角度等参数,以及利用离子或电子束扫描进行表征和分析。具体而言,离子束轰击样品表面后,会发生离子表面相互作用、散射和快速输运等过程,从而形成剖面结构。这个过程可以通过离子束激发发射光谱(IBED)、离子退火和电子显微镜等技术进行表征和分析。 在cesium剖面分析中,常用的表征技术有二次离子质谱(SIMS)、弹性反冲离子散射(ERD)、能量分散X射线光谱(EDX)和透射电子显微镜等。这些技术可以提供样品剖面的元素分布、化学组成和晶体结构等信息,从而帮助研究人员了解材料的结构、性能和性质。 通过cesium剖面分析,可以研究材料的界面、薄膜、气敏性、杂质分布、化学反应机制等问题。这对于材料科学和表面化学的研究具有重要意义。同时,cesium剖面分析也广泛应用于半导体、光电子器件、电池、涂层材料、生物材料等领域的研究和开发中。 总之,cesium剖面分析是一种重要的材料剖面结构分析方法,可以通过离子束的辐照和相关表征技术,提供材料的剖面元素分布、化学组成和晶体结构等信息,有助于研究人员深入了解材料的结构和性能特点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Raccom

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

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

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

打赏作者

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

抵扣说明:

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

余额充值