基于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>
相关推荐
豆包程序员2 小时前
Nodejs+vue+ElementUI框架的养老院老年人健康服务系统的设计与实现
前端·vue.js·elementui
心.c2 小时前
从输入 URL 到页面展示的完整过程
前端·javascript·vue.js·js
斌味代码3 小时前
Vue3源码解读(一):响应式系统 reactive/ref 核心原理图解(2026最新版)
前端·javascript·vue.js
小茴香3533 小时前
拖拽实现(原生JS+Vue)
前端·javascript·vue.js·typescript
风之舞_yjf3 小时前
Vue基础(30)_mixins配置项
前端·vue.js
踩着两条虫3 小时前
AI驱动的 Vue3应用开发平台深入探究(十五):扩展与定制之自定义设置器与属性编辑器
前端·vue.js·人工智能·低代码·系统架构·编辑器
踩着两条虫14 小时前
AI驱动的Vue3应用开发平台深入探究(十):物料系统之内置组件库
android·前端·vue.js·人工智能·低代码·系统架构·rxjava
慧一居士15 小时前
nuxt3 项目和nuxt4 项目区别和对比
前端·vue.js
神舟之光17 小时前
jwt权限控制简单总结(乡村意见簿-vue-express-mongdb)
前端·vue.js·express