基于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>
相关推荐
徐小夕17 小时前
100小时,我做了一款AI CAD建模软件,开源!
前端·vue.js·github
淸湫19 小时前
项目中使用了全局权限管理,请详细描述如何通过Vue Router的路由守卫来实现全局权限控制?
前端·vue.js
李剑一19 小时前
前端必看 | Vue 刷新页面,生命周期钩子直接 "罢工",原来问题在这?90% 开发者都栽过!
前端·vue.js
閞杺哋笨小孩19 小时前
域名驱动多租户入驻:后台配置 + 前端解析
前端·vue.js
用户1257585243620 小时前
写了三年定时任务还在手改 Cron 表达式?这个 GoFrame 后台框架帮你全闭环了
vue.js
前端那点事21 小时前
Vue3自定义Hooks保姆级教程!从原理到企业级实战,告别混乱代码
前端·vue.js
前端那点事21 小时前
别再乱用Vue3响应式!ref、reactive、toRef、toRefs完整区别+企业级落地实战
前端·vue.js
白鳯21 小时前
塔罗神谕:星月神域莱诺薇为您占卜
react·web·three.js·codex·deepseek·vibe coding·塔罗占卜
閞杺哋笨小孩21 小时前
从脚手架到构建注入:Vue 多租户「入驻」工程实践
vue.js·vite
卤蛋fg61 天前
VxeTable 实现表尾合计行并支持数据实时统计
vue.js