2017-03-08 4 views
0

J'ai un rayon et un nombre de points 3D que je triangule et alimente dans un AABBtree, ce qui me permet de trouver l'intersection du rayon avec le maillage. Maintenant, j'aimerais aussi connaître le vecteur normal du triangle que le rayon croise.Comment puis-je trouver le vecteur normal (ou la poignée) du triangle qu'un rayon croise?

Je projette les points dans le plan x-y et applique le maillage Delaunay. Je nourris ensuite les points 3D dans la structure AABBtree. Idéalement, je ne veux pas changer cette partie.

La recherche de l'intersection avec first_intersection() est simple.
Comment trouver la normale du triangle intersecté?

edit: Le problème est que boost::get<KernelSCD::Point_3>(&(intersection->first)) ne me donne que le point d'intersection réel. Pour trouver le vecteur normal au triangle intersecté, j'ai besoin de la poignée du triangle intersecté. Comment est-ce que je reçois ceci?

Ceci est mon code:

// CGAL includes for AABB tree for intersection detection 
#include <CGAL/AABB_tree.h> 
#include <CGAL/AABB_traits.h> 
#include <CGAL/AABB_triangle_primitive.h> 
#include <CGAL/Simple_cartesian.h> 

// CGAL includes for Delaunay triangulation 
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> 
#include <CGAL/Delaunay_triangulation_2.h> 
#include <CGAL/Triangulation_vertex_base_with_info_2.h> 
#include <CGAL/Polygon_mesh_processing/compute_normal.h> 

#include <CGAL/Simple_cartesian.h> 
#include <CGAL/AABB_tree.h> 
#include <CGAL/AABB_traits.h> 
#include <CGAL/Surface_mesh.h> 
#include <CGAL/AABB_face_graph_triangle_primitive.h> 
#include <CGAL/Polygon_mesh_processing/compute_normal.h> 
#include <CGAL/Polygon_mesh_processing/orientation.h> 

#include <iostream> 
#include <string> 
#include <vector> 
#include <fstream> 


int main (int argc, char *argv[]) 
{ 
    typedef CGAL::Simple_cartesian<double> KernelSCD; 
    typedef KernelSCD::Triangle_3 Triangle_3; 
    typedef std::list<Triangle_3>::iterator IteratorTriangle; 
    typedef CGAL::AABB_triangle_primitive<KernelSCD, IteratorTriangle> Primitive; 
    typedef CGAL::AABB_traits<KernelSCD, Primitive> AABB_triangle_traits; 
    typedef CGAL::AABB_tree<AABB_triangle_traits> Tree; 
    typedef CGAL::Simple_cartesian<double> K; 
    typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned, K> Vb; 
    typedef CGAL::Triangulation_data_structure_2<Vb>     Tds; 
    typedef CGAL::Delaunay_triangulation_2<K, Tds>      Delaunay; 
    typedef Delaunay::Point            PointD; 
    typedef Delaunay::Vertex_handle          Vertex_handle; 
    typedef KernelSCD::Point_3 Point_3; 
    typedef KernelSCD::Vector_3 Vector_3; 
    typedef KernelSCD::Ray_3 Ray_3; 
    typedef boost::optional<Tree::Intersection_and_primitive_id<Ray_3>::Type> Ray_intersection; 
    typedef Tree::Primitive_id AABB_primitive_id; 


    Delaunay dt; 
    std::vector< std::pair<PointD, unsigned> > points_2d; 
    std::vector<Point_3> points_3d; 

    Tree tree_3d_map_; 
    std::list<Triangle_3> triangles_; 

    std::vector<double> verts = { 0, 0, 100, 
            0, 1, 101, 
            1, 0, 102, 
            1, 1, 103, 
           10, 0, 104, 
            0, 10, 105, 
           10, 10, 106}; 

    // Filling Delaunay triangulation 
    for (int i = 0; i+2 < verts.size(); i += 3) { 
     points_2d.push_back(std::make_pair(PointD(verts.at(i), verts.at(i + 1)), i/3)); 
     points_3d.push_back(Point_3(verts.at(i), verts.at(i + 1), verts.at(i + 2))); 
    } 
    dt.insert(points_2d.begin(), points_2d.end()); 

    // Filling AABB tree 
    int v0, v1, v2; 
    for (Delaunay::Finite_faces_iterator it = dt.finite_faces_begin(); it != dt.finite_faces_end(); it++){ 
     v0 = it->vertex(0)->info(); 
     v1 = it->vertex(1)->info(); 
     v2 = it->vertex(2)->info(); 
     triangles_.push_back(Triangle_3(points_3d.at(v0), points_3d.at(v1), points_3d.at(v2))); 
    } 
    tree_3d_map_.insert(triangles_.begin(), triangles_.end()); 

    Point_3 p1(.4, .5, 0.1); 
    Vector_3 v(0, 0, 1); 
    Ray_3 ray(p1, v); 

    // Find point where the ray intersects the mesh for the first time 
    Ray_intersection intersection = tree_3d_map_.first_intersection(ray); 

    if (intersection){ 
     if (boost::get<KernelSCD::Point_3>(&(intersection->first))){ 
      const KernelSCD::Point_3* p = boost::get<KernelSCD::Point_3>(&(intersection->first)); 
      std::cout << "First intersection: " << p->x() << ", " << p->y() << ", " << p->z() << std::endl; 

      AABB_primitive_id primitive_id = intersection->second; 
      //                    Fails: 
      //                   | | | | 
      //                   v v v v 
      //KernelSCD::Vector_3 v = CGAL::Polygon_mesh_processing::compute_face_normal(primitive_id,points_3d); 
      //std::cout << "v: " << v.x() << ", " << v.y() << ", " << v.z() << std::endl; 
     } 
    }  


    /* If I use a Surface_mesh, it works: 
    typedef CGAL::Surface_mesh<Point_3> Mesh; 
    typedef CGAL::AABB_face_graph_triangle_primitive<Mesh> PrimitiveM; 
    typedef CGAL::AABB_traits<KernelSCD, PrimitiveM> Traits; 
    typedef CGAL::AABB_tree<Traits> TreeM; 
    typedef boost::optional<TreeM::Intersection_and_primitive_id<Ray_3>::Type> Ray_intersectionM; 
    typedef TreeM::Primitive_id AABB_primitive_idM; 

    std::ifstream input("tetrahedron.off"); 
    Mesh mesh; 
    input >> mesh; 
    TreeM tree; 
    tree.insert(faces(mesh).first, faces(mesh).second, mesh); 
    Ray_intersectionM intersection2 = tree.first_intersection(ray); 
    if (intersection2){ 
     if (boost::get<Point_3>(&(intersection2->first))){ 
      const Point_3* p = boost::get<Point_3>(&(intersection2->first)); 
      std::cout << "First intersection: " << *p << std::endl; 

      AABB_primitive_idM primitive_id = intersection2->second; 

      // Works: 
      Vector_3 v = CGAL::Polygon_mesh_processing::compute_face_normal(primitive_id,mesh); 
      std::cout << "v: " << v.x() << ", " << v.y() << ", " << v.z() << std::endl; 
     } 
    }*/ 

    std::cout << "done" << std::endl; 
    std::cin.get(); 
    return 0; 
} 
+0

Il existe des fonctions globales 'normal' et' unit_normal' et des foncteurs de noyau 'Construct_normal_3' et' Construct_unit_normal_3' qui prennent tous 3 points et peuvent être pertinents. –

+0

Le problème est que je n'ai pas les 3 points. Ma conjecture est, le chemin à parcourir est d'obtenir la poignée du triangle intersecté, qui mènera aux 3 coins. Ou je peux utiliser la fonction compute_face_normal() ou l'une des fonctions que vous avez mentionnées. Dans les deux cas, j'ai besoin de la poignée du triangle intersecté. Comment est-ce que je reçois ceci? – Adrian

Répondre

0

Peut-être que je l'ai raté quelque chose, mais n'est pas que l'application des mathématiques simples vecteurs? Si vous connaissez les 3 points de votre triangle, vous pouvez créer un vecteur du point [0] au point [1] et du point [0] au point [2] et faire le produit croisé. Le résultat sera un vecteur qui est perpendiculaire à vos deux vecteurs (le normal de votre triangle).

+0

C'est exact. Le problème est que je n'ai pas ces 3 points. Comment trouver ces 3 points? – Adrian