You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CGAL三维网格布尔并集运算后顶点RGB颜色丢失问题咨询

解决CGAL布尔运算后顶点颜色丢失的问题

我之前也碰到过类似的情况——CGAL的多边形网格布尔运算(比如你用的并集操作)默认只会处理网格的几何形状和拓扑结构,完全不会自动传递顶点颜色这类自定义属性。不过别担心,咱们可以通过手动映射颜色的方式来解决,具体步骤和代码示例如下:

核心思路

布尔运算会生成三种顶点:

  • 完全来自第一个输入网格的顶点
  • 完全来自第二个输入网格的顶点
  • 相交处生成的全新顶点

我们需要:

  1. 确保输入网格正确读取顶点颜色
  2. 跟踪结果网格顶点与原网格顶点的对应关系
  3. 对不同来源的顶点分别处理颜色:原顶点直接继承颜色,新顶点通过相邻原顶点颜色插值生成

具体实现步骤

1. 定义带颜色属性的网格结构

推荐使用CGAL::Surface_mesh,它更容易处理自定义顶点属性:

#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/boolean_operations.h>
#include <CGAL/IO/read_COFF.h>
#include <CGAL/IO/write_COFF.h>

typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Surface_mesh<Point> Mesh;
typedef boost::property_map<Mesh, CGAL::vertex_color_t>::type Color_map;

2. 读取输入网格并确认颜色加载

COFF格式本身支持顶点颜色,CGAL的read_COFF函数会自动加载这个属性:

Mesh mesh1, mesh2, result;
if(!CGAL::read_COFF("model1.coff", mesh1) || !CGAL::read_COFF("model2.coff", mesh2)) {
  std::cerr << "Failed to load input meshes!" << std::endl;
  return EXIT_FAILURE;
}

Color_map cm1 = get(CGAL::vertex_color, mesh1);
Color_map cm2 = get(CGAL::vertex_color, mesh2);

3. 执行布尔运算并跟踪顶点对应关系

关键是使用vertex_map1和vertex_map2参数,记录结果顶点与原网格顶点的映射,这样能避免浮点精度问题导致的位置匹配错误:

std::map<Mesh::Vertex_index, Mesh::Vertex_index> vmap_from_mesh1, vmap_from_mesh2;

CGAL::Polygon_mesh_processing::boolean_operation(
  mesh1, mesh2,
  CGAL::Polygon_mesh_processing::Union(),
  result,
  CGAL::parameters::vertex_map1(vmap_from_mesh1).vertex_map2(vmap_from_mesh2)
);

4. 为结果网格映射颜色

  • 对于来自原网格的顶点,直接继承对应颜色
  • 对于新生成的相交顶点,取相邻原顶点颜色的平均值(你也可以根据需求换成更精细的插值方式)
Color_map cm_result = get(CGAL::vertex_color, result);

// 处理来自mesh1的顶点
for(auto& pair : vmap_from_mesh1) {
  Mesh::Vertex_index res_v = pair.first;
  Mesh::Vertex_index src_v = pair.second;
  cm_result[res_v] = cm1[src_v];
}

// 处理来自mesh2的顶点
for(auto& pair : vmap_from_mesh2) {
  Mesh::Vertex_index res_v = pair.first;
  Mesh::Vertex_index src_v = pair.second;
  cm_result[res_v] = cm2[src_v];
}

// 处理新生成的顶点(不在两个映射中的顶点)
for(Mesh::Vertex_index v : result.vertices()) {
  if(vmap_from_mesh1.count(v) == 0 && vmap_from_mesh2.count(v) == 0) {
    CGAL::IO::Color avg_color(0, 0, 0);
    int neighbor_count = 0;
    // 遍历该顶点的所有相邻顶点
    for(Mesh::Halfedge_index h : result.halfedges_around_target(v)) {
      Mesh::Vertex_index neighbor_v = result.source(h);
      // 优先取mesh1的颜色,再取mesh2的
      if(vmap_from_mesh1.count(neighbor_v)) {
        avg_color += cm1[vmap_from_mesh1[neighbor_v]];
        neighbor_count++;
      } else if(vmap_from_mesh2.count(neighbor_v)) {
        avg_color += cm2[vmap_from_mesh2[neighbor_v]];
        neighbor_count++;
      }
    }
    if(neighbor_count > 0) {
      avg_color /= neighbor_count;
    }
    cm_result[v] = avg_color;
  }
}

5. 保存带颜色的结果网格

最后用write_COFF保存结果,颜色会被自动写入:

if(!CGAL::write_COFF("result.coff", result)) {
  std::cerr << "Failed to save result mesh!" << std::endl;
  return EXIT_FAILURE;
}

注意事项

  • 浮点精度问题:用顶点映射的方式比直接匹配点位置要可靠得多,能避免因为计算误差导致的颜色匹配失败
  • 插值方式:示例中用了简单的平均插值,你可以根据需求换成距离加权插值、 barycentric 插值等更精细的方式
  • 属性兼容性:确保你的CGAL版本支持vertex_color_t属性,以及boolean_operation的vertex_map参数(较新版本的CGAL都支持)

内容的提问来源于stack exchange,提问作者A. Fasih

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:09:06