У меня есть луч и количество трехмерных точек, которые я триангулирую и передаю в дерево AABB, которое позволяет мне найти пересечение луча с сеткой.
Теперь я также хотел бы знать вектор нормали треугольника, который пересекает луч.
Я проецирую точки в плоскость x-y и применяю сетку Делоне. Затем я передаю трехмерные точки в структуру 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;
}
Может быть, я что-то упустил, но разве это не применение простой векторной математики? если вы знаете 3 точки вашего треугольника, вы можете создать вектор из точки [0] в точку [1] и из точки [0] в точку [2] и выполнить перекрестное произведение. Результатом будет вектор, который перпендикуляр для обоих ваших векторов ( нормальный вашего треугольника).
Других решений пока нет …