mirror of https://github.com/CGAL/cgal
131 lines
3.6 KiB
C++
131 lines
3.6 KiB
C++
#include <algorithm>
|
|
#include <vector>
|
|
#include <fstream>
|
|
|
|
#include <boost/utility/addressof.hpp>
|
|
#include <boost/bind.hpp>
|
|
#include <boost/functional/value_factory.hpp>
|
|
#include <boost/range/algorithm/transform.hpp>
|
|
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
|
#include <CGAL/Surface_mesh.h>
|
|
#include <CGAL/box_intersection_d.h>
|
|
#include <CGAL/Timer.h>
|
|
|
|
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
|
|
|
|
typedef K::Triangle_3 Triangle_3;
|
|
typedef K::Point_3 Point_3;
|
|
typedef CGAL::Surface_mesh<typename K::Point_3> SM;
|
|
typedef CGAL::Bbox_3 Bbox_3;
|
|
typedef CGAL::Timer Timer;
|
|
|
|
typedef SM::Face_index Face_descriptor;
|
|
typedef SM::Halfedge_index Halfedge_descriptor;
|
|
|
|
/// small helper to extract a triangle from a face
|
|
Triangle_3 triangle(const SM& sm, Face_descriptor f)
|
|
{
|
|
Halfedge_descriptor hf = sm.halfedge(f);
|
|
Point_3 a = sm.point(sm.target(hf));
|
|
hf = sm.next(hf);
|
|
Point_3 b = sm.point(sm.target(hf));
|
|
hf = sm.next(hf);
|
|
Point_3 c = sm.point(sm.target(hf));
|
|
hf = sm.next(hf);
|
|
return Triangle_3(a, b, c);
|
|
}
|
|
|
|
class Box
|
|
: public CGAL::Box_intersection_d::Box_d<double, 3, CGAL::Box_intersection_d::ID_NONE> {
|
|
private:
|
|
typedef CGAL::Box_intersection_d::Box_d<
|
|
double, 3, CGAL::Box_intersection_d::ID_NONE> Base;
|
|
Face_descriptor fd;
|
|
public:
|
|
typedef double NT;
|
|
typedef std::size_t ID;
|
|
|
|
Box(Face_descriptor f, const SM& sm) : Base(triangle(sm, f).bbox()), fd(f) {}
|
|
Box(const Bbox_3& b, Face_descriptor fd) : Base(b), fd(fd) {}
|
|
Face_descriptor f() const { return fd; }
|
|
ID id() const { return static_cast<ID>(fd.idx()); }
|
|
};
|
|
|
|
struct Callback {
|
|
Callback(const SM& P, const SM& Q, unsigned int& i)
|
|
: P(P), Q(Q), count(i)
|
|
{}
|
|
|
|
void operator()(const Box* bp, const Box* bq) {
|
|
Face_descriptor fp = bp->f();
|
|
Triangle_3 tp = triangle(P, fp);
|
|
|
|
Face_descriptor fq = bq->f();
|
|
Triangle_3 tq = triangle(Q, fq);
|
|
|
|
if(do_intersect( tp, tq)) {
|
|
++(count);
|
|
}
|
|
}
|
|
|
|
const SM& P;
|
|
const SM& Q;
|
|
unsigned int& count;
|
|
};
|
|
|
|
unsigned int intersect(const SM& P, const SM& Q) {
|
|
std::vector<Box> P_boxes, Q_boxes;
|
|
std::vector<const Box*> P_box_ptr, Q_box_ptr;
|
|
P_boxes.reserve(P.number_of_faces());
|
|
P_box_ptr.reserve(P.number_of_faces());
|
|
Q_boxes.reserve(Q.number_of_faces());
|
|
Q_box_ptr.reserve(Q.number_of_faces());
|
|
|
|
// build boxes and pointers to boxes
|
|
boost::transform(P.faces(),
|
|
std::back_inserter(P_boxes),
|
|
boost::bind(boost::value_factory<Box>(), _1, boost::cref(P)));
|
|
|
|
std::transform(P_boxes.begin(), P_boxes.end(), std::back_inserter(P_box_ptr),
|
|
&boost::addressof<Box>);
|
|
|
|
boost::transform(Q.faces(),
|
|
std::back_inserter(Q_boxes),
|
|
boost::bind(boost::value_factory<Box>(), _1, boost::cref(Q)));
|
|
std::transform(Q_boxes.begin(), Q_boxes.end(), std::back_inserter(Q_box_ptr),
|
|
&boost::addressof<Box>);
|
|
|
|
unsigned int i = 0;
|
|
Callback c(P,Q, i);
|
|
CGAL::box_intersection_d(P_box_ptr.begin(), P_box_ptr.end(),
|
|
Q_box_ptr.begin(), Q_box_ptr.end(),
|
|
c);
|
|
return i;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
std::cout.precision(17);
|
|
SM P, Q;
|
|
|
|
if(argc < 3) {
|
|
std::cerr << "Usage: do_intersect <mesh_1.off> <mesh_2.off>" << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
std::ifstream inP(argv[1]);
|
|
inP >> P;
|
|
|
|
std::ifstream inQ(argv[1]);
|
|
inQ >> Q;
|
|
Timer timer;
|
|
timer.start();
|
|
unsigned int num_intersections = intersect(P,Q);
|
|
timer.stop();
|
|
std::cout << "Counted " << num_intersections << " in "
|
|
<< timer.time() << " seconds." << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
|