如何基于GeoToolKit/INT实现矢量流线的聚集动画效果示例

      继续在上一篇文章的基础上,利用相同的数据处理方法统一了不同年代地层的数据格式(目前js解析支持的格式有ZMap、TS、XYZ和XYZA等),本文主要基于GeoToolKit/INT组件,针对地质研究经常在二维等值线基础上模拟计算地层中物体流动的模拟仿真可视化诉求,主要在ContourShape背景上,绘制矢量流线和SymbolShape的动画显示,最终实现了某个时期地层的物体流动的矢量流线动画效果,仿真油气的聚集过程的二维可视化,包括前端、后端设计等内容。详细效果如下。

1.前端设计与相关技术:主要采用VUE+JS+GeotoolKit.JS,充分利用VUE的组件化设计思想,以及GeotoolKit.JS的ContourShape、Polyline和SymbolShape组件结合实现。具体前端代码如下,示例效果详见第3部分。

vue组件

<script>
import {ContourPlot} from './vectorstreamline.js';
let contourPlot = null;
const SOURCE_DATA_FILE = 'src/demos/contour/contourplot/data/2018_T28.dat';
export default {
    name: 'ContourPlotDemo',
    components: {IntSnackbar, IntContourToolbar, IntPrintDialog, JsonForms},
    data: function () {
        return {
            showDismissibleAlert: false,
            showPrintDialog: false,
            propertiesDialogData: null,
            propertiesDialogActive: false,
            schema: null,
            uischema: Object.freeze(contourSchema),
            materialRenderers: Object.freeze(materialRenderers),
            ajv: null
        };
    },
    destroyed () {
        this._file = null;
        contourPlot.dispose();
        window.removeEventListener('resize', this.onResize);
    },
    updated () {
        if (!this.componentDidResize) {
            this.onResize();
            this.componentDidResize = true;
        }
    },
    mounted () {
        contourPlot = new ContourPlot({
            'host': this.$refs.host,
            'canvas': this.$refs.plot,
            'ondataload': this.onDataLoad,
            'onchangerubberband': this.onChangeRubberBand
        });
        this.setShowDismissibleAlert(false);
        this.setToolbarEnabled(false);
        this._file = this.$refs.file;
        this._file.addEventListener('change', this.onFileChange);
        contourPlot.loadDataSource(SOURCE_DATA_FILE);
        window.addEventListener('resize', this.onResize);
    },
    methods: {
        onResize () {
            contourPlot.resize();
            this.componentDidResize = false;
            this.$forceUpdate();
        },
        onChangeRubberBand (sender) {
            this.$refs.toolbar.setRubberBand(sender.isEnabled());
        },
        onFileChange (event) {
            this.setToolbarEnabled(true);
            contourPlot.loadFile(event.target)
                .then(this.setShowDismissibleAlert.bind(this, false))
                .catch(this.setShowDismissibleAlert.bind(this, true));
        },
        //绘制矢量流线动画效果
        vectorStreamline () {
            //console.log('in vectorStreamline');
            contourPlot.drawVectorStreamLine(this);
        }
}
</script>

基于二维等值线,用于解析绘制矢量线和动画的js组件(vectorstreamline.js),关于矢量流线数据的计算,后续我会专门写相应的内容分享相关方法。

import {ContourShape} from '@int/geotoolkit/contour/shapes/ContourShape';
import {Polyline} from "@int/geotoolkit/scene/shapes/Polyline";
import {Path} from '@int/geotoolkit/scene/shapes/Path';
import {KnownColors} from "@int/geotoolkit/util/ColorUtil";
import {SymbolShape} from "@int/geotoolkit/scene/shapes/SymbolShape";
import {AnchorType} from "@int/geotoolkit/util/AnchorType";
import {SquarePainter} from "@int/geotoolkit/scene/shapes/painters/SquarePainter";
import {AnimationFill} from "@int/geotoolkit/animation/AnimationFill";
const DEFAULT_CROSS_HAIR_COLOR = 'red';
export class ContourPlot {
    constructor (options) {
        TextMetrics.setCacheLimit(512);
        this._host = options.host;
        this._canvas = options.canvas;
        this._onDataLoad = options.ondataload;
        this._onChangeRB = options.onchangerubberband;
        this._contour = null;
        this._vectorstream=null;
        // Create model to hold the contour shape
        this._contourModel = new Group()
            .setVerticalFlip(true)
            .setCache(new ViewCache());
        // Initialize default properties
        this._numberOfLevels = 20;
        this._showFills = true;
        // Create annotated node model
        this._annotatedNodeModel = new Group()
            .setBounds(new Rect(0, 0, this._canvas.clientWidth, this._canvas.clientHeight))
            .addChild(this._contourModel)
            .setScaleScrollStrategy(new RestrictScaleStrategy({
                'minscale': 1E-3,
                'maxscale': 1E3
            }));
        this._layer = [];
    }
    //绘制矢量流线图动画
    drawVectorStreamLine(obj){
        console.log('drawVectorStreamLine');
        //删除上一次绘制的矢量流线和动画方块,注意,之前在哪里加上child,后续就在哪里removeChild。
        this._vectorstream=this._contour.getRoot();
        if(this._vectorstream.children.length>1){
            for(let i=this._vectorstream.children.length-1;i>0;i--){
                // console.log(i+'='+this._vectorstream.getChild(i));
                this._vectorstream.removeChild(this._vectorstream.getChild(i));
            }
        }
        //1.曲线1路径(曲线路径来自于矢量流线计算得到的数据)
        let pathX1=[280, 390, 400, 410, 490,510,1830];
        let pathY1=[280, 420, 430, 440, 480,430,280];
        const line=this.createLines(pathX1,pathY1);//构建曲线子对象1
        //2.曲线2路径(曲线路径来自于矢量流线计算得到的数据)
        pathX1=[800, 490,1000,1300];
        pathY1=[220, 480, 520,80];
        const line2=this.createLines(pathX1,pathY1);//构建曲线子对象2
        //3.运动方块1 路径(路径来自于曲线1路径)
        pathX1=[260, 390, 400, 410, 485];
        pathY1=[270, 420, 430, 440, 480];
        const rec =this.createRecRun(pathX1,pathY1);//构建运动方块子对象1
        //4.运动方块2 路径(路径来自于曲线2路径)
        let pathX2=[1830, 510,495];
        let pathY2=[280, 430,475];
        const rec2 =this.createRecRun(pathX2,pathY2);//构建运动方块子对象2
        //5.运动方块3 路径(路径来自于曲线1路径)
        pathX2=[800, 495];
        pathY2=[220, 480];
        const rec3 =this.createRecRun(pathX2,pathY2);//构建运动方块子对象3
        //6.运动方块4 路径(路径来自于曲线2路径)
        pathX2=[1300,1000, 495];
        pathY2=[80, 520,485];
        const rec4 =this.createRecRun(pathX2,pathY2);//构建运动方块子对象3
        //增加对象
        this._vectorstream.addChild(line);
        this._vectorstream.addChild(line2);
        this._vectorstream.addChild(rec);
        this._vectorstream.addChild(rec2);
        this._vectorstream.addChild(rec3);
        this._vectorstream.addChild(rec4);
    }
    //构建曲线
    createLines(pathlistX,pathlistY){
        //曲线方式(可以是Polyline,Path或Spline等
        const path = new Polyline({
        'x': pathlistX,//[38, 39, 40, 41, 48,51,53]
        'y': pathlistY,//[41, 42, 43, 44, 42,43,45]
        'linestyle': {
            'color': KnownColors.DarkGreen,
            'width': 4
        }
        });
        return path;
    }
    //构建动画方块
    createRecRun(pathlistX,pathlistY){
        const symbolShape=new SymbolShape(20, 15, 15, 15, AnchorType.Center, false, SquarePainter);
        symbolShape.setFillStyle(new FillStyle(KnownColors.DarkRed));
        symbolShape.setLineStyle(new LineStyle(KnownColors.DarkGreen, 1));
        //设置symbolShape动画的各种属性
        //屏幕横向:x(左小右大),纵向:y(下小上大)
        symbolShape.setAnimationStyle([
            {
                'attributeName': 'x',
                'duration': 2000,
                // 'repeatCount': Infinity,     //多次循环设置
                'fill':AnimationFill.Freeze,    //运行到最后位置冻结
                // 'function': Functions.NoEasing,
                'values':pathlistX
             }, 
             {
                'attributeName': 'y',
                'duration': 2000,
                 // 'repeatCount': Infinity,
                 // 'function': Functions.NoEasing,
                'fill':AnimationFill.Freeze,
                'values': pathlistY 
            }
        ]);
      return symbolShape;
}
}

2.后端设计与相关技术:主要采用NodeJS的微服务接口实现。为了便于js解析地层和矢量流数据。代码详见上一篇文章,后端代码、服务方式和调用方式和数据文件格式类似。

3.矢量流线和动画显示示例效果(不同色标)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/34863.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Quiz 14_2-2: Using Web Services | Python for Everybody 配套练习_解题记录

文章目录 Python for Everybody课程简介Quiz 14_2-2: Using Web Services单选题&#xff08;1-15&#xff09;操作题Autograder 1: Extract Data from JSONAutograder 2: Calling a JSON API Python for Everybody 课程简介 Python for Everybody 零基础程序设计&#xff08;P…

NSS [NSSCTF 2022 Spring Recruit]ezgame

NSS [NSSCTF 2022 Spring Recruit]ezgame 前端小游戏&#xff0c;乐。

Spring源码整体脉络介绍及源码编译

需完成的任务 类------------------------------------------BeanFactory----------------------------------------->Bean【BeanFactory调用getBean()生产出来的】 BeanFactory Spring顶层核心接口&#xff0c;使用了简单工厂模式【根据名字&#xff0c;生产出不同的Bean…

C#:AES的加密解密,用于明文加密

大白话理解&#xff1a;将明眼能看到的字符给用另一种读不懂的语言给翻译&#xff0c;就像是摩斯密码……就像base64加密&#xff0c;都有异曲同工之妙。 建一个新的类&#xff08;这里放了aes加密解密的方法&#xff09; public static class AesPassword{/// <summary&g…

大屏项目也不难

项目环境搭建 使用create-vue初始化项目 npm init vuelatest准备utils模块 业务背景&#xff1a;大屏项目属于后台项目的一个子项目&#xff0c;用户的token是共享的 后台项目 - token - cookie 大屏项目要以同样的方式把token获取到&#xff0c;然后拼接到axios的请求头中…

rain-nowcasting-using-deep-learning github:使用深度学习进行临近降水预报

来源 github地址 是什么 本资料库旨在阐述 "在应用于降雨预报的深度学习模型中合并雷达雨量图像和风速预测 "&#xff08; “Merging radar rain images and wind predictions in a deep learning model applied to rain nowcasting”&#xff09;一文中提出的深度…

群晖NAS搭建WebDV服务手机ES文件浏览器远程访问

文章目录 1. 安装启用WebDAV2. 安装cpolar3. 配置公网访问地址4. 公网测试连接5. 固定连接公网地址 转载自cpolar极点云文章&#xff1a;群晖NAS搭建WebDAV服务手机ES文件浏览器远程访问 有时候我们想通过移动设备访问群晖NAS 中的文件,以满足特殊需求,我们在群辉中开启WebDav服…

蓝桥杯专题-试题版含答案-【字母统计】【计算球体积】【16进制的简单运算】【C小加随机数】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

JUC--CompletableFuture下

对计算速度进行选用 import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit;public class Test4 {public static void main(String[] args) {CompletableFuture<String> a CompletableFuture.supplyAsync(() -> {try { TimeUnit.SE…

详解JAVA Socket

目录 1.概述 2.使用 3.使用场景 3.1.web server中的网络通信 3.2.长连接 3.3.性能问题 1.概述 什么是网络通信&#xff1a; 就像打电话一样&#xff0c;两点间要通信&#xff0c;两点间就必须有连接&#xff0c;为了实现任意两个节点之间的通信&#xff0c;我们就必须采…

第三十九章Java成员方法的声明和调用

声明成员方法可以定义类的行为&#xff0c;行为表示一个对象能够做的事情或者能够从一个对象取得的信息。类的各种功能操作都是用方法来实现的&#xff0c;属性只不过提供了相应的数据。一个完整的方法通常包括方法名称、方法主体、方法参数和方法返回值类型&#xff0c;其结构…

C# PaddleInference 文字检测(只检测不识别)

效果 项目 Demo下载 代码 using OpenCvSharp.Extensions; using OpenCvSharp; using Sdcb.PaddleInference.Native; using Sdcb.PaddleInference; using System; using System.Collections.Generic; using System.Data; using System.Drawing; using System.Linq; using Sys…

phar协议文件包含

实验目的 通过本实验&#xff0c;了解php封装伪协议&#xff0c;掌握phar协议文件包含的用法 实验环境 操作机&#xff1a;kali 靶机&#xff1a;Windows 2007 实验地址&#xff1a;http://靶机ip/exp/include2/phar/phar1/ 用户名&#xff1a;college 密码&#xff1a;360C…

Vue :在 VSCode 中安装 yarn 并用 yarn 工具来控制 Vue 项目的详细过程

Ⅰ、 Yarn 工具简介&#xff1a; 1、什么是 yarn 工具: Yarn 是 facebook 发布的一款取代 npm 的资源包管理工具&#xff0c;是一个快速、可靠、安全的依赖管理工具&#xff0c;一款新的 JavaScript 资源包管理工具(吐槽下&#xff1a;最大的弊端是&#xff0c;要通过 npm 来…

在blender中使用python程序化建模

blender中&#xff0c;所有可以在Blender软件中的手动操作&#xff0c;基本都可以通过Python API 完成 那么就可以用这个完成程序化生成 下面我给出一个简单的方块建模程序&#xff1a; 在scripting中&#xff0c;可以添加file&#xff0c;然后向场景中心放置一个正方体 首…

RK3588平台开发系列讲解(Camera篇)OV569摄像头调试

文章目录 一、摄像头识别检测二、查看摄像头支持的格式三、摄像头采集格式查询四、摄像头采集格式查询沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要讲解OV569摄像头调试。 OV5695 是一种图像传感器,用于摄像头设备。要进行 OV5695 摄像头的调试,通常涉…

100种思维模型之能力圈思维模型-91

芒格说&#xff1a; “ 一个人在一生中可以真正得到的真见卓识仍然非常有限&#xff0c;所以正确的决策必须局限在自己的 ‘ 能力圈’ 以内。 ” 巴菲特说&#xff1a; “对你的 能力圈 来说&#xff0c;最重要的不是能力圈的范围大小&#xff0c;而是你如何能够 确定能…

Django核心

安装django pip install django # pip install django3.1.6创建django项目 在一个项目中可以包含多个应用程序。 django-admin startapp app_name #创建一个应用程序 django-admin startproject project_name #创建一个项目运行django项目 python manage.py runserver 80…

2. PS基本操作

因为网页美工大部分效果图都是利用PS ( Photoshop )来做的,所以以后我们大部分切图工作都是在PS里面完成 ●文件—>打开&#xff1a;可以打开我们要测量的图片 ●CtrlR : 可以打开标尺&#xff0c;或者视图—>标尺 ●右击标尺&#xff0c;把里面的单位改为像素 ●Ctrl加号…

Spring Boot实战:拦截器和监听器的应用指南

当使用Spring Boot时&#xff0c;我们可以通过拦截器&#xff08;Interceptor&#xff09;和监听器&#xff08;Listener&#xff09;来实现对请求和响应的处理。拦截器和监听器提供了一种可插拔的机制&#xff0c;用于在请求处理过程中进行自定义操作&#xff0c;例如记录日志…