Graphics 如何使用libigl在薄曲面上执行布尔运算?

Graphics 如何使用libigl在薄曲面上执行布尔运算?,graphics,computational-geometry,mesh,libigl,Graphics,Computational Geometry,Mesh,Libigl,我目前正在研究,并试图抓住位于另一个物体内部的表面部分。但是,libigl似乎只适用于封闭体: 以下是适用于封闭体的代码。VA,VF为三棱柱体,VB,FB为四面体: #include <igl/readOFF.h> //#define IGL_NO_CORK //#undef IGL_STATIC_LIBRARY #include <igl/copyleft/cgal/mesh_boolean.h> #include <igl/viewer/Viewer.h>

我目前正在研究,并试图抓住位于另一个物体内部的表面部分。但是,libigl似乎只适用于封闭体:

以下是适用于封闭体的代码。VA,VF为三棱柱体,VB,FB为四面体:

#include <igl/readOFF.h>
//#define IGL_NO_CORK
//#undef IGL_STATIC_LIBRARY
#include <igl/copyleft/cgal/mesh_boolean.h>
#include <igl/viewer/Viewer.h>

#include <Eigen/Core>
#include <iostream>

Eigen::MatrixXd VA,VB,VC;
Eigen::VectorXi J,I;
Eigen::MatrixXi FA,FB,FC;
igl::MeshBooleanType boolean_type(
  igl::MESH_BOOLEAN_TYPE_UNION);

const char * MESH_BOOLEAN_TYPE_NAMES[] =
{
  "Union",
  "Intersect",
  "Minus",
  "XOR",
  "Resolve",
};

bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int mods)
{
  switch(key)
  {
    default:
      return false;
    case 'A':
        viewer.data.clear();
        std::cout << "Loading A" << std::endl;
        viewer.data.set_mesh(VA, FA);
      break;
    case 'B':
        viewer.data.clear();
        std::cout << "Loading B" << std::endl;
        viewer.data.set_mesh(VB, FB);
      break;
    case 'C':
        viewer.data.clear();
        std::cout << "Loading C" << std::endl;
        viewer.data.set_mesh(VC, FC);
      return true;
  }  
  return true;
}

int main(int argc, char *argv[])
{
  using namespace Eigen;
  using namespace std;

  double prismSize = 150;
  double Heigh = 300;
  VA.resize(6, 3);
  VA << -prismSize, prismSize, 0,
      prismSize, prismSize, 0,
      0, 2 * prismSize, 0,
      -prismSize, prismSize, Heigh,
      prismSize, prismSize, Heigh,
      0, 2 * prismSize, Heigh;
  FA.resize(8, 3);
  FA << 1, 0, 2,
      5, 3, 4,
      4, 1, 2,
      2, 5, 4,
      3, 5, 2,
      2, 0, 3,
      0, 1, 4,
      4, 3, 0;

  double tetsize = 300;
  VB.resize(4, 3);
  VB << 0, 0, tetsize,
      -tetsize, 0, 0,
      tetsize, 0, 0,
      0, tetsize*2, 0;
  FB.resize(4, 3);
  FB << 2, 1, 3,
      2, 0, 1,
      3, 0, 2,
      1, 0, 3;


  igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, igl::MESH_BOOLEAN_TYPE_INTERSECT, VC, FC);

  std::cout
      << "VA:" << std::endl << VA << std::endl << "==============" << std::endl
      << "FA:" << std::endl << FA << std::endl << "==============" << std::endl
      << "VB:" << std::endl << VB << std::endl << "==============" << std::endl
      << "FB:" << std::endl << FB << std::endl << "==============" << std::endl
      << "VC:" << std::endl << VC << std::endl << "==============" << std::endl
      << "FC:" << std::endl << FC << std::endl << "==============" << std::endl;

  // Plot the mesh with pseudocolors
  igl::viewer::Viewer viewer;

  viewer.data.set_mesh(VA, FA);
  //viewer.data.set_mesh(VB, FB);
  //viewer.data.set_mesh(VC, FC);  

  viewer.core.show_lines = true;
  viewer.callback_key_down = &key_down;
  viewer.core.camera_dnear = 3.9;
  cout<<
    "Press '.' to switch to next boolean operation type."<<endl<<
    "Press ',' to switch to previous boolean operation type."<<endl<<
    "Press ']' to push near cutting plane away from camera."<<endl<<
    "Press '[' to pull near cutting plane closer to camera."<<endl<<
    "Hint: investigate _inside_ the model to see orientation changes."<<endl;
  viewer.launch();
}

结果网格C将是空的,我想得到一个开放的薄表面,而不是一个封闭的实体。我认为我使用了错误的函数。有人知道怎么做吗?

布尔几何要求所有曲面都是无边界的流形。否则,任何操作都将导致空集。以下是对流形的简单解释:

…并对您的问题进行更多推理:


布尔几何要求所有曲面都是无边界的流形。否则,任何操作都将导致空集。以下是对流形的简单解释:

…并对您的问题进行更多推理:


正如@Eric Bischoff所描述的,布尔几何要求所有曲面都是流形。但是,我找到了一个解决方法,至少符合我的要求:

假设A是一个任意的开放曲面,B是一个封闭的流形,您希望切断曲面A的外部部分


我想描述的解决方法是先完成A,使其成为流形A。然后,从B中减去A'并找到新创建的面,这些面正好构成您想要的开放薄曲面。

如@Eric Bischoff所述,布尔几何要求所有曲面都是流形。但是,我找到了一个解决方法,至少符合我的要求:

假设A是一个任意的开放曲面,B是一个封闭的流形,您希望切断曲面A的外部部分

我想描述的解决方法是先完成A,使其成为流形A。然后,从B中减去A'并找到新创建的面,这些面正是您想要的开放薄曲面。

您可能正在寻找igl::copyleft::cgal::trim_with_solid。这假设您有一个任意网格A,而另一个闭合网格实际上是实体或网格B。输出将是一个与A具有相同曲面的网格,但添加了新边,以便每个面都可以标记为“内B”或“外/上B”。使用输出列表D中的标记,然后,提取由B修剪的A的部分就很简单了

您可能正在寻找igl::copyleft::cgal::trim_with_solid。这假设您有一个任意网格A,而另一个闭合网格实际上是实体或网格B。输出将是一个与A具有相同曲面的网格,但添加了新边,以便每个面都可以标记为“内B”或“外/上B”。使用输出列表D中的标记,然后,提取由B修剪的A的部分就很简单了


尽管我不知道您的数据集和用例:您可以关闭每个连续的边界。如果您可以访问“对半边”数据结构,我相信您可以找到恰好有一个相邻面的任何相邻边。这并不适用于所有情况,但取决于您的数据,它可能适用于大多数情况。这是我所能接受的,因为我从未使用过libigl。好运:@user54506是的,我的数据结构很特殊,所以我可以使用这条路线。最近我遇到了一个新的几何体,它不能轻易闭合。我要用solidVA,FA,VB,FB,V,F,D,J尝试igl::copyleft::cgal::trim_;@Alec JacobsonAlthough我不知道您的数据集和用例:您可以关闭每个相邻的边界。如果您可以访问“对半边”数据结构,我相信您可以找到恰好有一个相邻面的任何相邻边。这并不适用于所有情况,但取决于您的数据,它可能适用于大多数情况。这是我所能接受的,因为我从未使用过libigl。好运:@user54506是的,我的数据结构很特殊,所以我可以使用这条路线。最近我遇到了一个新的几何体,它不能轻易闭合。我要用solidVA,FA,VB,FB,V,F,D,J尝试igl::copyleft::cgal::trim_;根据@Alec JacobsonSo的建议,J的用途是什么?似乎J经常出现在和布尔相关的API中,但我并没有找到关于它的明确信息。J将告诉你们每个输出面来自哪个输入面。假设你输入的每个面都有不同的颜色,那么J会告诉你如何给你的输出网格上色以正确匹配。那么,J是用来做什么的呢?似乎J经常出现在和布尔相关的API中,但我并没有找到关于它的明确信息。J将告诉你们每个输出面来自哪个输入面。因此,假设输入的每个面都有不同的颜色,那么J将告诉您如何为输出网格着色以正确匹配。
//FA.resize(8, 3);
FA.resize(7, 3);
//FA << 1, 0, 2,
FA << 5, 3, 4,
      4, 1, 2,
      2, 5, 4,
      3, 5, 2,
      2, 0, 3,
      0, 1, 4,
      4, 3, 0;
igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,V,F,D,J);