基于Vue+Three.js实现三维油藏模型解析与可视化交互切割操作

最近为了实现油藏模型的解析与三维可视化操作,对three.js和eclipse绘制的三维油藏模型格式解析进行了研究,实现了三维油藏模型可视化及简单交互操作。主要实现了三维油藏模型构建、解析加载和三维可视化交互,并根据油藏属性(如孔隙度PORO)等进行层位显示,同时支持按照X/Y/Z轴切割显示,以及任意多边形、任意点的切割显示,具体如下,供大家参考。

一、基于Theejs实现油藏模型的三维可视化效果图
二、主要核心代码

主要基于Vue或HTML+Three.js,实现了三维油藏模型解析加载、三维显示、油藏属性填充显示、可视化交互操作,以及三维空间的多种切割交互及显示等。以下主要是第一幅效果图的三维可视化交互代码,代码如下。

复制代码
<script>  
    // 模拟的油藏模型(来自grid-4layer.grdecl)  
    const reservoirData = {  
        nx: 50,  
        ny: 50,  
        nz: 4,  
        layers: [  
            {  
                name: '底层油藏',  
                depth: [0, 8],  
                porosity: 0.15,  
                color: '#8B4513'  
            },  
            {  
                name: '主力油层',  
                depth: [8, 14],  
                porosity: 0.22,  
                color: '#D2691E'  
            },  
            {  
                name: '顶层油藏',  
                depth: [14, 23],  
                porosity: 0.40,  
                color: '#397235'  
            },  
            {  
                name: '盖层',  
                depth: [24, 29],  
                porosity: 0.12,  
                color: '#DEB887'  
            }  
        ],  
        porosityData: {  
            // 简化的油藏孔隙度数据,实际来自文件  
            layer0: Array(2500).fill(0).map(() => 0.15 + Math.random() * 0.03),  
            layer1: Array(2500).fill(0).map(() => 0.19 + Math.random() * 0.06),  
            layer2: Array(2500).fill(0).map(() => 0.30 + Math.random() * 0.06),  
            layer3: Array(2500).fill(0).map(() => 0.10 + Math.random() * 0.05)  
        }  
    };  
  
    // 场景设置  
    let scene, camera, renderer, controls;  
    let reservoirLayers = [];  
    let porosityMode = false;  
  
    function init() {  
        // 创建场景  
        scene = new THREE.Scene();  
        scene.background = new THREE.Color('#b7c0ce');  
  
        // 创建相机  
        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);  
        camera.position.set(50, 30, 50);  
        camera.lookAt(0, 0, 0);  
  
        // 创建渲染器  
        renderer = new THREE.WebGLRenderer({ antialias: true });  
        renderer.setSize(window.innerWidth, window.innerHeight);  
        document.getElementById('container').appendChild(renderer.domElement);  
  
        // 添加轨道控制器  
        controls = new THREE.OrbitControls(camera, renderer.domElement);  
        controls.enableDamping = true;  
  
        // 添加环境光源  
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);  
        scene.add(ambientLight);  
        // 添加平行光源  
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.4);  
        directionalLight.position.set(50, 100, 50);  
        scene.add(directionalLight);  
  
        // 添加参考网格  
        const gridHelper = new THREE.GridHelper(200, 50, '#444444', '#6e6c6c');  
        scene.add(gridHelper);  
  
        // 添加坐标轴  
        const axesHelper = new THREE.AxesHelper(50);  
        scene.add(axesHelper);  
  
        // 创建油藏模型  
        createReservoirModel();  
  
        // 处理窗口大小变化  
        window.addEventListener('resize', onWindowResize, false);  
  
        // 开始渲染循环  
        animate();  
    }  
  
    // 创建油藏模型  
    function createReservoirModel() {  
        reservoirData.layers.forEach((layer, index) => {  
            const height = layer.depth[1] - layer.depth[0];  
            const geometry = createLayerGeometry(height, index);  
            // 创建材质  
            let material;  
            if (porosityMode) {  
                // 利用孔隙度值创建纹理  
                material = createPorosityMaterial(layer, index);  
            } else {  
                // 利用默认颜色创建纹理  
                material = new THREE.MeshPhongMaterial({  
                    color: layer.color,  
                    side: THREE.DoubleSide,  
                    transparent: true,  
                    opacity: 0.7  
                });  
            }  
  
            const mesh = new THREE.Mesh(geometry, material);  
            mesh.position.y = layer.depth[0] + height / 2;  
            mesh.userData = { layerName: layer.name, layerIndex: index };  
            scene.add(mesh);  
            reservoirLayers.push(mesh);  
        });  
    }  
  
    // 创建层几何体  
    function createLayerGeometry(height, seed) {  
        const geometry = new THREE.BoxGeometry(reservoirData.nx, height, reservoirData.ny, reservoirData.nx, 4, reservoirData.ny);  
        const positions = geometry.attributes.position;  
        const vector = new THREE.Vector3();  
  
        for (let i = 0; i < positions.count; i++) {  
            vector.fromBufferAttribute(positions, i);  
            const freq = 0.08 + seed * 0.01;  
            const amp = 0.5 + seed * 0.2;  
            const noise = Math.sin(vector.x * freq) * Math.cos(vector.z * freq) * amp +  
                Math.sin(vector.x * freq * 2) * 0.2;  
  
            if (vector.y > 0) {  
                vector.y += noise;  
            } else {  
                vector.y += noise * 0.3;  
            }  
            positions.setXYZ(i, vector.x, vector.y, vector.z);  
        }  
  
        geometry.computeVertexNormals();  
        return geometry;  
    }
    // 处理窗口大小变化  
    function onWindowResize() {  
        camera.aspect = window.innerWidth / window.innerHeight;  
        camera.updateProjectionMatrix();  
        renderer.setSize(window.innerWidth, window.innerHeight);  
    }  
  
    // 渲染循环  
    function animate() {  
        requestAnimationFrame(animate);  
        controls.update();  
        renderer.render(scene, camera);  
    }  
  
    // 初始化  
    init();  
</script>
相关推荐
前端那点事1 小时前
Vue插槽用法全解析(Vue2+Vue3适配)| 组件复用必备
vue.js
Ruihong1 小时前
Vue v-on 在 React 中 VuReact 会如何实现?
vue.js·react.js·面试
|晴 天|2 小时前
实现草稿自动保存功能:5秒无操作自动保存
前端·vue.js·typescript
广师大-Wzx4 小时前
JavaWeb:前端部分
java·前端·javascript·css·vue.js·前端框架·html
M ? A4 小时前
你的 Vue v-memo 与 v-once,VuReact 会编译成什么样的 React 代码?
前端·javascript·vue.js·经验分享·react.js·面试·vureact
吴声子夜歌4 小时前
Vue3——过度和动画效果
前端·vue.js·es6
zopple5 小时前
前端三剑客 vs Vue.js:核心区别解析
前端·javascript·vue.js
胡志辉的博客5 小时前
本地明明好好的,怎么一上线就跨域了?把同源策略、前后端分工和 CORS 一次讲明白
前端·javascript·vue.js·reactjs·nextjs·跨域
|晴 天|5 小时前
文章系列管理系统:拖拽排序与进度追踪
前端·vue.js·typescript
jiayong235 小时前
第 17 课:任务选择与批量操作
开发语言·前端·javascript·vue.js·学习