2017-03-08 33 views
0

我有一条射线和一些三维点,我将它们三角化并送入AABBtree,这使我可以找到射线与网格的交点。 现在我还想知道射线相交的三角形的法向量。如何找到射线相交的三角形的法向矢量(或手柄)?

我将点投影到x-y平面并应用Delaunay网格划分。然后我将3D点送入AABBtree结构。理想情况下,我不想改变这部分。

找到与first_intersection()的交集非常简单。
如何找到相交三角形的法线?

编辑:问题是,那boost::get<KernelSCD::Point_3>(&(intersection->first))只给了我实际的交点。为了找到相交三角形的法线向量,我需要相交三角形的手柄。我如何得到这个?

这是我的代码:

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

有全局函数'normal'和'unit_normal'以及内核函子'Construct_normal_3'和'Construct_unit_normal_3',它们都需要3点并且可能是相关的。 –

+0

问题是我没有3分。 我的猜测是,要走的路是获得相交三角形的手柄,这将导致3个角落。或者我可以使用函数compute_face_normal()或您提到的其中一个函数。无论哪种情况,我都需要相交三角形的手柄。我如何得到这个? – Adrian

回答

0

也许我错过了一些东西,但不是那么简单的矢量数学的应用?如果您知道三角形的三个点,则可以创建一个从点[0]到点[1]和点[0]到点[2]的矢量,并执行叉积。结果将是一个矢量,这是一个矢量垂直到你的矢量(正常你的三角形)。

+0

这是正确的。问题是我没有这3点。 我如何找到这3点? – Adrian