Как выполнить булеву операцию на тонкой поверхности с помощью 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>
#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();
}
Однако, если я удалил одну из поверхностей из A
или же B
например, как показано ниже:
//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;
Результат сетки C
будет пустым (я хочу получить открытую тонкую поверхность вместо закрытого тела). Я думаю, что я использую неправильную функцию. Кто-нибудь знает, как это сделать?
3 ответа
Возможно, вы ищете igl::copyleft::cgal::trim_with_solid
, Это предполагает, что у вас есть произвольная сетка A
и у вас есть еще одна закрытая сетка (на самом деле сплошная или PWN сетка) B
, На выходе будет сетка той же поверхности, что и A
но с добавлением новых ребер, чтобы каждое лицо можно было пометить как внутри B
или снаружи / на B
, Использование флагов в списке вывода D
затем тривиально извлечь часть A
"подстриженный" B
,
igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,V,F,D,J);
Булева геометрия требует, чтобы все поверхности были многообразными без границ. В противном случае любые операции приведут к пустому набору. Вот простое объяснение многообразий:
... и больше рассуждений на ваш вопрос:
Как описывает @Eric Bischoff, булева геометрия требует, чтобы все поверхности были многообразными. Однако я нашел обходной путь для этого, который по крайней мере соответствует моему требованию:
Предположим, что A
произвольная открытая поверхность и B
является закрытым коллектором, и вы хотите отрезать внешнюю часть поверхности A
,
Обходной путь, который я хочу описать, заключается в завершении A
сделать его многообразным (A'
) во-первых. Затем вычтите A'
от B, и найдите недавно созданные грани, которые точно составляют открытую тонкую поверхность, которую вы хотите.