CGAL Mesh 网格曲面栅格化

CGAL Mesh 网格曲面栅格化

使用CGAL将地形曲面网格体栅格化。

Code

#include<iostream>
#include<cmath>

#include<CGAL/Surface_mesh.h>
#include<CGAL/Surface_mesh/IO/PLY.h>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/Delaunay_triangulation_2.h>

#include <CGAL/Polygon_mesh_processing/locate.h>

#include "include/Color_ramp.h"

using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Projection_traits = CGAL::Projection_traits_xy_3<Kernel>;
using Point_2 = Kernel::Point_2;
using Point_3 = Kernel::Point_3;

// Triangulated Irregular Network
using TIN = CGAL::Delaunay_triangulation_2<Projection_traits>;
using Mesh = CGAL::Surface_mesh<Point_3>;

int main(){
   //读取网格曲面
    Mesh mesh;
    CGAL::IO::read_PLY("test.ply",mesh);
    // 计算包围盒
    CGAL::Bbox_3 bbox = CGAL::bbox_3(mesh.points().begin(), mesh.points().end());
    std::cout << "with:" << bbox.x_span() << "\nheight:" << bbox.y_span() << std::endl;
    int width = std::ceil(bbox.x_span());
    int height = std::ceil(bbox.y_span());
    width = std::max(width, height);
    height = width;
    // 构建Delaunay_triangulation 三角网
    TIN tin (mesh.points().begin(), mesh.points().end());
    TIN::Face_handle location;

    // Use PPM format (Portable PixMap) for simplicity
    std::ofstream raster_ofile("raster.ppm", std::ios_base::binary);
    // PPM header
    raster_ofile << "P6" << std::endl // magic number
        << width << " " << height << std::endl // dimensions of the image
        << 255 << std::endl; // maximum color value
    // Use rainbow color ramp output
    Color_ramp color_ramp;
    //查询并插值,使用三角形重心插值
    for (std::size_t y = 0; y < height; ++y)
        for (std::size_t x = 0; x < width; ++x)
        {
            Point_3 query(bbox.xmin() + x * (bbox.xmax() - bbox.xmin()) / double(width),
                bbox.ymin() + (height - y) * (bbox.ymax() - bbox.ymin()) / double(height),
                0); // not relevant for location in 2D
            location = tin.locate(query, location);
            // Points outside the convex hull will be colored black
            std::array<unsigned char, 3> colors { 0, 0, 0 };
            // 查询到网格点所在三角形面
            if (!tin.is_infinite(location))
            {
                std::array<double, 3> barycentric_coordinates
                    = CGAL::Polygon_mesh_processing::barycentric_coordinates
                    (Point_2(location->vertex(0)->point().x(), location->vertex(0)->point().y()),
                        Point_2(location->vertex(1)->point().x(), location->vertex(1)->point().y()),
                        Point_2(location->vertex(2)->point().x(), location->vertex(2)->point().y()),
                        Point_2(query.x(), query.y()),
                        Kernel());
                  // 插值
                double height_at_query
                    = (barycentric_coordinates[0] * location->vertex(0)->point().z()
                        + barycentric_coordinates[1] * location->vertex(1)->point().z()
                        + barycentric_coordinates[2] * location->vertex(2)->point().z());
                // Color ramp generates a color depending on a value from 0 to 1
                // 高程值映射(拉伸或缩放)
                double height_ratio = (height_at_query - bbox.zmin()) / (bbox.zmax() - bbox.zmin());
                height_ratio = height_ratio > 1.0 ? 1.0 : height_ratio;
                colors = color_ramp.get(height_ratio);
            }
            //写入映射后的RGB
            raster_ofile.write(reinterpret_cast<char*>(&colors), 3);
        }
    raster_ofile.close();
    return 0;
}

构建

cmake_minimum_required(VERSION 3.1...3.23)
project(main)
find_package(CGAL REQUIRED)
create_single_source_cgal_program("main.cpp")
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=D:\vcpkg\scripts\buildsystems\vcpkg.cmake
cmake --build build --config Debug

Result

网格体
在这里插入图片描述
栅格化符号化结果:红色->黄色->绿色->蓝色->白色(高程值递减)
在这里插入图片描述

反过程

在这里插入图片描述
在这里插入图片描述

参考及相关链接

  1. https://blog.csdn.net/mrbaolong/article/details/137610742
  2. https://doc.cgal.org/latest/Manual/tuto_gis.html
  3. stl2png-Mesh转栅格
  4. 高度栅格图转网格体Mesh
### CGAL 中删除三角形网格顶点的方法 在 CGAL 的 `Surface_mesh` 数据结构中,可以通过调用其成员函数来操作顶点和边。要删除某个特定的顶点,通常需要先标记该顶点并调整相邻面片的关系以保持网格的有效性。以下是具体方法及其示例代码: #### 使用 `remove_vertex()` 函数 CGAL 提供了 `remove_vertex()` 方法用于移除指定顶点。此方法会自动处理与被删除顶点相连的边和面,并重新构建局部拓扑关系。 需要注意的是,在实际应用中,直接删除可能导致不连通区域或者破坏整体网格质量的情况。因此建议结合其他工具(如平滑算法[^2]),优网格后再执行删除操作。 下面是一个简单的 C++ 实现例子展示如何利用这些功能完成目标: ```cpp #include <CGAL/Simple_cartesian.h> #include <CGAL/Surface_mesh.h> typedef CGAL::Simple_cartesian<double> Kernel; typedef CGAL::Surface_mesh<Kernel::Point_3> Mesh; int main() { // 创建一个测试网格对象 Mesh mesh; // 添加一些初始节点作为演示用途... auto v0 = mesh.add_vertex(Kernel::Point_3(0, 0, 0)); auto v1 = mesh.add_vertex(Kernel::Point_3(1, 0, 0)); auto v2 = mesh.add_vertex(Kernel::Point_3(0, 1, 0)); // 构建基本三角形单元 mesh.add_face(v0, v1, v2); // 假设我们要删除第一个顶点v0 bool success = mesh.remove_vertex(v0); if (!success){ std::cerr << "Vertex removal failed." << std::endl; } return 0; } ``` 上述程序片段展示了向表面网格添加三个点形成简单平面图形的过程;随后尝试从中去除其中一个端点。注意这里假设所有条件都满足才能成功消除所选位置——否则返回失败标志。 #### 关键注意事项 - **拓扑一致性**: 当前版本支持有限制条件下安全地去掉孤立或边界上的结点而不违反数据结构定义的要求。 - **性能考量**: 对于大规模复杂模型而言频繁增删动作可能引起效率下降问题,应谨慎评估需求场景再决定是否采用此类手段改进设计流程。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值