0

我有一条射线和多个 3D 点,我对其进行三角剖分并输入 AABBtree,这使我能够找到射线与网格的交点。现在我还想知道射线相交的三角形的法线向量。

我将点投影到 xy 平面并应用 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;
}
4

1 回答 1

0

也许我错过了一些东西,但这不是简单向量数学的应用吗?如果您知道三角形的 3 个点,则可以创建一个从 point[0] 到 point[1] 以及从 point[0] 到 point[2] 的向量并进行叉积。结果将是一个垂直于两个向量(三角形的法线)的向量。

于 2017-03-08T14:00:59.097 回答