2016-06-18 28 views
0

Ich arbeite derzeit an libigl, und versuche, den Teil der Oberfläche zu greifen, die in einem anderen Körper befindet. Es scheint jedoch, als libigl nur mit geschlossenen Körpern arbeitet:Wie boolean Operation auf dünner Oberfläche mit Libigl durchführen?

Hier ist der Code, der für geschlossene Körper funktioniert. VA, VF ein Dreiecksprisma ist und VB ist FB ein Tetraeders:

#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(); 
} 

Wenn ich jedoch eine der Oberflächen von A oder B, zum Beispiel wie unten gelöscht:

//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; 

Das Ergebnis Mesh C wird leer sein (Ich möchte eine offene dünne Oberfläche anstelle eines geschlossenen Körpers erhalten). Ich denke ich benutze die falsche Funktion. Weiß jemand, wie man das macht?

Antwort

1

Sie könnten nach igl::copyleft::cgal::trim_with_solid suchen. Dies setzt voraus, dass Sie ein beliebiges Mesh A haben und Sie ein anderes geschlossenes Mesh haben (eigentlich ein Solid oder PWN Mesh) B. Die Ausgabe wird eine Masche mit der gleichen Oberfläche wie A sein, aber mit neuen Kanten hinzugefügt, so dass jede Seite entweder als B oder außerhalb/on B markiert werden kann. Mit den Flags in der Ausgabeliste D ist es dann einfach, den Teil A "getrimmt" von B zu extrahieren.

igl::copyleft::cgal::trim_with_solid(VA,FA,VB,FB,V,F,D,J); 
+0

Also, was ist 'J' verwendet für?Es scheint, dass 'J' häufig in APIs erscheint, die sich auf Boolesche Werte beziehen, aber ich habe keine klaren Informationen darüber gefunden. –

+0

'J' wird Ihnen sagen, aus welcher Seite des _input_ jedes Gesicht des _output_ stammt. Angenommen, jedes Gesicht Ihrer Eingabe hat eine andere Farbe, dann würde "J" Ihnen sagen, wie Sie Ihr Ausgabemesh farblich anpassen müssen, damit es korrekt zusammenpasst. –

1

Boole'sche Geometrie erfordert, dass alle Flächen ohne Begrenzung vielfältig sind. Alle Operationen führen ansonsten zu einem leeren Satz. Hier ist ein einfaches explination von Verteilern:

Manifolds

... und Argumentation auf Ihre Frage:

Boolean Operations

0

Wie von @Eric Bischoff, erfordert Boolesche Geometrie, dass alle Oberflächen vielfältig. Allerdings fand ich für diese eine Abhilfe, die zumindest mit meiner Forderung passt:

wird angenommen, dass A eine beliebige offene Fläche ist und B ist ein geschlossener Verteiler, und Sie wollen A den äußeren Teil der Oberfläche abzuschneiden.

Die Problemumgehung, die ich beschreiben möchte, ist A zu vervollständigen, um es zu einem Verteiler (A') zu machen. Dann subtrahiere A' von B und finde die neu erzeugten Facetten, die genau die offene dünne Oberfläche darstellen, die du willst.

+1

Obwohl ich bin nicht bewusst Ihre Daten gesetzt und Anwendungsfall: Sie könnten jede zusammenhängende Grenze aus nächster Nähe. Wenn Sie Zugriff auf die Datenstruktur der Halvekante haben, glaube ich, dass Sie nur eine benachbarte Kante finden können, die genau eine benachbarte Fläche hat. Dies würde nicht für alle Fälle funktionieren, aber abhängig von Ihren Daten könnte es für die meisten funktionieren. –

+0

Das ist so weit, wie ich es kann, da ich Libigl nie benutzt habe. Viel Glück :) –

+0

@ user5454506 Ja, meine Datenstruktur ist speziell, also kann ich diese Route verwenden. In letzter Zeit stehe ich vor einer neuen Geometrie, die nicht einfach zu schließen ist. Ich werde versuchen 'Igl :: copyleft :: cgal :: trim_with_solid (VA, FA, VB, FB, V, F, D, J);' vorgeschlagen von @ Alec Jacobson –