cgal/Mesh_3/include/CGAL/Data_structure_using_octree...

2028 lines
54 KiB
C++

// Copyright (c) 2005 INRIA Sophia-Antipolis (France).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you may redistribute it under
// the terms of the Q Public License version 1.0.
// See the file LICENSE.QPL distributed with CGAL.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
//
//
// Author(s) : Marie Samozino
// Laurent Rineau
#ifndef DATA_STRUCTURE_USING_OCTREE
#define DATA_STRUCTURE_USING_OCTREE
#include <string>
#include <CGAL/basic.h>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <cmath>
#include <utility>
#include <map>
#include <set>
#include <list>
#include "Constrained_Element.h"
#include "Constrained_Vertex.h"
#include "Constrained_Edge.h"
#include "Constrained_Facet.h"
#include "CGAL/squared_distance_3.h"
#include <CGAL/iterator.h>
//Corresponding to the "octree neighboor presence table" in the
//thesis of P.Bhattacharya.
//The following function shows wether for a given node its neighbor
//in a particular direction is in the same octant or not.A false
//entrie indicates the presence of neighbor of the given node in the
//same octant as the node is and true otherwise.
//dans les tableau indice 1 = indice du cube , indice 2 = direction
//Pierre utilise des char au lieu de int --> pourquoi ??
static const unsigned int PSI[8][6] = {{4,4,2,2,1,1},
{5,5,3,3,0,0},
{6,6,0,0,3,3},
{7,7,1,1,2,2},
{0,0,6,6,5,5},
{1,1,7,7,4,4},
{2,2,4,4,7,7},
{3,3,5,5,6,6}};
// F B U D L R
static const bool NU[8][6] = {{false, true, false, true, false, true },
{false, true, false, true, true, false},
{false, true, true, false, false, true },
{false, true, true, false, true, false},
{true, false, false, true, false, true },
{true, false, false, true, true, false},
{true, false, true, false, false, true },
{true, false, true, false, true, false}};
CGAL_BEGIN_NAMESPACE
template <class Gt>
class Data_structure_using_octree_3
{
/* typedef's */
public:
typedef Gt Geom_traits;
typedef typename Gt::FT Nb;
typedef typename Gt::Triangle_3 Triangle;
typedef typename Gt::Point_3 Point;
typedef typename Gt::Plane_3 Plane;
typedef typename Gt::Vector_3 Vector;
typedef typename Gt::Iso_cuboid_3 Iso_Cuboid;
typedef typename Gt::Segment_3 Segment;
typedef typename Gt::Line_3 Line;
typedef typename Gt::Object_3 Object;
typedef typename Gt::Ray_3 Ray;
//CAUTION : can i use the kernel bbox ?
typedef CGAL::Bbox_3 Bbox;
// Constraints
typedef Constrained_Element<Gt> C_elt;
typedef Constrained_Vertex<Gt> C_vertex;
typedef Constrained_Edge<Gt> C_edge;
typedef Constrained_Facet<Gt> C_facet;
typedef std::list<C_elt*> C_elt_list;
typedef typename C_elt_list :: iterator C_elt_iterator;
typedef std::map<int,C_elt*> Constraint_map;
typedef std::list<int> Ind_constraint_list;
//Name coresponds to the index node. it's a number includ between 0
//and 7. it's the path from the root to the node.
typedef std::list<int> Name;
typedef struct Node;
typedef Node* Octree;
// data structure for the octree
struct Node {
Iso_Cuboid boite;
Name nom;
Octree fils[8];
Octree pere;
Ind_constraint_list i_c_l;
};
//a direction
typedef enum Direction {FRONT = 0,
BACK = 1,
UP = 2,
DOWN = 3,
LEFT = 4,
RIGHT = 5};
//typedef enum Direction {FRONT, BACK, UP, DOWN, LEFT, RIGHT};
public:
Octree arbre;
Constraint_map c_m;
private :
Geom_traits gt;
// for the octree
double niv_max;
//to keep in memory the visited edge
std::list<Segment> ls;
//f = number of facet, s = number of constraints
int count,f,s,nbp;
double tl,tri;
//to know which constraint we want to take into account.
bool use_vertex, use_edge, use_facet;
Bbox space_bbox;
Nb PREC;
public:
// le constructeur
Data_structure_using_octree_3()
{
gt = Geom_traits();
count=0;
f = 0;
s = 0;
nbp = 0;
tl = 0;tri = 0;
use_vertex = false;
use_edge = false;
use_facet = true;
space_bbox = Bbox();
PREC = 0.0000000000001;
}
Data_structure_using_octree_3(bool v, bool e, bool f )
{
gt = Geom_traits();
count=0;
f = 0;
s = 0;nbp = 0;
tl = 0;tri = 0;
use_vertex = v;
use_edge = e;
use_facet = f;
PREC = 0.0000000000001;
}
void setUse_vertex (bool b){ use_vertex = b; }
void setUse_edge (bool b){ use_edge = b; }
void setUse_facet (bool b){ use_facet = b; }
public :
//initialisation
template <class Point_output_iterator>
void input(std::ifstream& ifs,
Point_output_iterator out = Emptyset_iterator());
void input ( C_elt_iterator it, C_elt_iterator end);
//Queries
Nb lfs ( Point p);
Nb lfs2 ( Point p);
Object intersect ( Point p, Point q);
Object intersect ( Ray r);
private :
void create_data_structure ( );
void add_constrained_vertex ( Point p );
void add_constrained_edge ( Point p, Point q);
void add_constrained_facet ( Point p, Point q, Point r);
void construct_octree ( Node* o,
Ind_constraint_list icl);
Constraint_map intersection ( Iso_Cuboid boite, Constraint_map* cm);
bool is_leaf ( Node* o);
bool visited ( Segment s);
//octree traversal function
std::list<int> ind_neighbor_son ( Direction d);
std::list<Node*> go_to_neighbor ( Node* o, Direction d);
std::list<Node*> find_face_neighbor ( Node* noeud,Direction d);
Node* go_to_node ( Octree o, Name p);
//localisation d'un point dans l'octree
Node* locate ( Octree o,Point p);
//Queries
Nb lfs_cont ( Point p,
Node* noeud,
std::map<int,Nb>* distance,
std::list<int>* ordre,
std::map<Name,bool>*
visited_cube,
Nb min);
Nb lfs_simp ( Point p,
Node* noeud,
std::map<int,Nb>* distance,
std::list<int>* ordre,
std::map<Name,bool>*
visited_cube,
Nb min);
int sci_aux ( Point p,
Segment s,
Node* noeud,
std::map<Name,bool>*
visited_cube);
//to compute distance
bool squared_distance_to_constraint_in_node( Point p,
Node* noeud,
std::map<int,Nb>* md,
std::list<int>* od);
//to check or find intersection
Nb squared_distance2 ( Point p,Triangle t);
Nb squared_distance_to_side ( Point p,
Iso_Cuboid c,
Direction d);
bool does_intersect ( Segment seg,
Iso_Cuboid c,
Direction d);
bool does_intersect ( Ray ray,
Iso_Cuboid c,
Direction d);
Point intersection ( Segment seg,
Iso_Cuboid c,
Direction d);
bool do_intersect2 ( Iso_Cuboid c,
Segment seg);
Point intersection ( Ray ray,
Iso_Cuboid c,
Direction d);
};
//----------------------------------------------------------------------------
//add a vertex to the constraints list
template <class Gt>
void
Data_structure_using_octree_3 <Gt> :: add_constrained_vertex(Point p )
{
if (nbp == 0)
//it's the first point
space_bbox = p.bbox();
else
space_bbox = space_bbox + p.bbox();
nbp ++;
if (use_vertex)
{
//create a new constraint
std::pair<int,C_elt*> c_p;
C_vertex* cv = new C_vertex (p );
c_p.first = s;
c_p.second = cv;
c_m.insert(c_p);
s++;
}
}
//----------------------------------------------------------------------------
//return true if s is in ls... make sure that we will a
//constrained_edge is not duplicate
template <class Gt>
bool
Data_structure_using_octree_3 <Gt> ::visited( Segment s)
{
typename Geom_traits::Equal_3 equal_3 = gt.equal_3_object();
if (ls.empty())
return false;
else {
typename std::list<Segment>::iterator
lsit = ls.begin(),
lsend = ls.end();
while ( lsit != lsend ){
if (equal(s,(*lsit)))
return true;
lsit++;
}
return false;
}
}
//----------------------------------------------------------------------------
// add a constrained edge to the constraints list
template <class Gt>
void
Data_structure_using_octree_3 <Gt> :: add_constrained_edge(Point p,
Point q)
{
if (use_edge) {
typename Geom_traits::Construct_segment_3
construct_segment = gt.construct_segment_3_object();
Segment seg = construct_segment(p,q);
if (!(visited(seg))){
ls.push_front(seg);
std::pair<int,C_elt*> c_p;
C_edge* ce = new C_edge(seg);
c_p.first = s;
c_p.second = ce;
c_m.insert(c_p);
s++;
}
}
}
//----------------------------------------------------------------------------
// add a constrained_facet to the constraints list
template <class Gt>
void
Data_structure_using_octree_3 <Gt> ::
add_constrained_facet(Point p, Point q, Point r){
if (use_facet) {
std::pair<int,C_elt*> c_p;
C_facet* cf = new C_facet (p,q,r);
c_p.first = s;
c_p.second = cf;
c_m.insert(c_p);
f++;
s++;
}
}
//----------------------------------------------------------------------------
//create the data structure... initialisation + construct the data
//structure via Construct_octree
template <class Gt>
void
Data_structure_using_octree_3 <Gt> :: create_data_structure()
{
Point
p = Point(space_bbox.xmin(),space_bbox.ymin(),space_bbox.zmin()),
q = Point(space_bbox.xmax(),space_bbox.ymax(),space_bbox.zmax());
typename Geom_traits::Construct_iso_cuboid_3
construct_iso_cuboid = gt.construct_iso_cuboid_3_object();
typename Geom_traits::Compute_volume_3 compute_volume =
gt.compute_volume_3_object();
Iso_Cuboid boite = construct_iso_cuboid(p,q);
double
vol = CGAL::to_double(compute_volume(boite));
//CAUTION : this criteria have no sens... must find an other one.
// we want a depth max such that the volume of the cuboid isn't
// smaller than 10^-3
niv_max =std::log(vol)/log((double)8) + 3*
std::log((double)10)/log((double)8);
int niv = 5;
// the deph of the tree mustn't be greater than 5 otherwise the
// tree will be too big ie the time of contruction too long
if ( niv_max > niv )
niv_max = niv;
arbre = new Node();
arbre->nom = Name();
arbre->boite = boite;
arbre->i_c_l = std::list<int>::list();
arbre->pere = NULL;
Ind_constraint_list icl;
typename Constraint_map ::iterator
cmit = c_m.begin(),
cmend = c_m.end();
while ( cmit != cmend )
{
icl.push_front((*cmit).first);
++cmit;
}
construct_octree(arbre, icl);
}
//-----------------------------------------------------------------------------
// construc the octree
template <class Gt>
void
Data_structure_using_octree_3<Gt> :: construct_octree ( Node* o,
Ind_constraint_list icl)
{
typename Geom_traits:: Construct_iso_cuboid_3 construct_iso_cuboid =
gt.construct_iso_cuboid_3_object();
typename Geom_traits:: Construct_midpoint_3 construct_midpoint =
gt.construct_midpoint_3_object();
typename Geom_traits::Construct_centroid_3 construct_centroid =
gt.construct_centroid_3_object();
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
typename Geom_traits::Compute_volume_3 compute_volume =
gt.compute_volume_3_object();
//threshold has to leave which the cell is not subdivised
unsigned s = 25;
// go through all constraints of the node
Ind_constraint_list ::iterator
iclit = icl.begin(),
iclend = icl.end();
//std::cout<<"creation de la liste de contraintes"<<std::endl;
while ( iclit != iclend )
{
if ( c_m[(*iclit)]->does_intersect( o->boite ))
{
o->i_c_l.push_front((*iclit));
}
++iclit;
}
//std::cout<<"creation de la liste des fils"<<std::endl;
if ((o->i_c_l.size()>=s) && (o->nom.size()<=niv_max))
{
//create the 8 children of the node
for (int l=0;l<8;l++)
{
o->fils[l] = new Node();
o->fils[l]->nom = std::list<int>::list(o->nom);
o->fils[l]->nom.push_back(l);
o->fils[l]->i_c_l = std::list<int>::list();
o->fils[l]->pere = o;
}
Point s[8];
for (int i=0; i<8;i++) {
s[i] = construct_vertex(o->boite,i);
}
Point m01, m03, m05, m27, m67, m47, m2347, m0123, m5647, m0354,
m0156,m1267, centre;
m01 = construct_midpoint( s[0],s[1]);
m03 = construct_midpoint( s[0],s[3]);
m05 = construct_midpoint( s[0],s[5]);
m27 = construct_midpoint( s[2],s[7]);
m67 = construct_midpoint( s[6],s[7]);
m47 = construct_midpoint( s[4],s[7]);
m0123 = construct_centroid( s[0],s[1],s[2],s[3]);
m2347 = construct_centroid( s[4],s[7],s[2],s[3]);
m5647 = construct_centroid( s[5],s[6],s[4],s[7]);
m0354 = construct_centroid( s[4],s[0],s[5],s[3]);
m0156 = construct_centroid( s[0],s[1],s[5],s[6]);
m1267 = construct_centroid( s[1],s[2],s[6],s[7]);
centre = construct_midpoint( m0156,m2347);
o->fils[0]->boite = construct_iso_cuboid(m05,m5647);
o->fils[1]->boite = construct_iso_cuboid(m0156,m67);
o->fils[2]->boite = construct_iso_cuboid(s[0],centre);
o->fils[3]->boite = construct_iso_cuboid(m01,m1267);
o->fils[4]->boite = construct_iso_cuboid(m0354,m47);
o->fils[5]->boite = construct_iso_cuboid(centre,s[7]);
o->fils[6]->boite = construct_iso_cuboid(m03,m2347);
o->fils[7]->boite = construct_iso_cuboid(m0123,m27);
for(int i = 0; i <8; i++){
//std::cerr << "|\r ";
construct_octree(o->fils[i], o->i_c_l);
}
}
else{
for (int l=0;l<8;l++){
o->fils[l] = new Node();
o->fils[l] = NULL;
}
}
/*std::cout<<"Noeud cree : ";
for( Name::iterator it = o->nom.begin(); it != o->nom.end(); it++)
std::cout<<*it<<" ";
std::cout<<std::endl;
std::cout<<"\tnombre de contraintes : "<<o->i_c_l.size()<<std::endl;*/
}
//----------------------------------------------------------------------------
template <class Gt>
void
Data_structure_using_octree_3<Gt> ::
input( C_elt_iterator it, C_elt_iterator end ){
while (it != end) {
//compute the bbox
if (nbp == 0)
//it's the first point
space_bbox = (*it)->getBBox();
else
space_bbox = space_bbox + (*it)->getBBox();
nbp ++;
std::pair<int,C_elt*> c_p;
c_p.first = s;
c_p.second = (*it);
c_m.insert(c_p);
s++;
it++;
}
create_data_structure();
}
//----------------------------------------------------------------------------
//read a oFF file and construct the corresponding data structure
template <class Gt>
template <class Point_output_iterator>
void
Data_structure_using_octree_3<Gt> ::
input(std::ifstream& ifs,
Point_output_iterator out){
int nb_points,nb_faces, ent2;
char entete;
// lecture de off
entete = ifs.get();
entete = ifs.get();
entete = ifs.get();
// lecture des 3 nombres
ifs >> nb_points;
ifs >> nb_faces;
ifs >> ent2;
int i1,i2,n,s = 0;
double x,y,z,f1;
std::cout<<"nombre de points : "<<nb_points<<std::endl;
std::cout<<"nombre de faces : "<<nb_faces<<std::endl;
std::cout<<"ent2 : "<<ent2<<std::endl;
std::vector<Point> vvect(nb_points);
//std::list<C_elt*> lc_input;
// points
while (s < nb_points){
ifs >> x; ifs >> y; ifs >> z;
vvect[s] = Point (x,y,z);
*out++ = vvect[s];
//idea : instead of compute the bbox in constrained_vertex why
//don't you compute it here ?
add_constrained_vertex(vvect[s]);
s++;
}
std::cout<<"number of vertices : "<<s<<std::endl;
//linking
int nb_points_of_face;
int i = 0,k;
ifs >> nb_points_of_face;
Point *p = new Point[nb_points_of_face];
while (!ifs.eof()) {
std::set<int> lind;
lind.clear();
ifs >> i1;
lind.insert(i1);
p[0] = vvect[i1];
n = 0;
k = 1;
for (i = 2 ; i <= nb_points_of_face ; i++) {
ifs >> i2;
// pour eviter d'avoir deux fois le meme sommet ds la face
if (lind.find(i2) == lind.end()){
p[k]=vvect[i2];
n++;
lind.insert(i2);
}
k++;
}
if (n >= 2) {// ruse pour traiter uniquement le cas de faces triangulaires
add_constrained_facet(p[0],p[1],p[2]);
//C_facet* cf = new C_facet (p[0],p[1],p[2]);
//lc_input.push_front(cf);
}
ifs >> f1;
while ((!ifs.eof()) && (f1 < 2)) ifs >> f1;
nb_points_of_face = (int) f1;
}
std::cout<<"number of facets : "<<f<<std::endl;
//creation de la structure
create_data_structure();
std::cout<<"data structure created"<<std::endl;
}
//-----------------------------------------------------------------------------
// find the constraints in cm which intersect the iso_cuboide boite
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Constraint_map
Data_structure_using_octree_3<Gt> :: intersection (Iso_Cuboid boite,
Constraint_map* cm)
{
Constraint_map result = *( new Constraint_map);
typename Constraint_map::iterator
cmit = cm->begin(),
cmend = cm->end();
while ( cmit != cmend ){
if ((*cmit)->does_intersect(boite) ){
result.push_back((*cmit));
}
++cmit;
}
return result;
}
//-----------------------------------------------------------------------------
//auxiliary function : return the children indices of a block such
//that this sub-block have a side includ in the block's side in
//direction D
template <class Gt>
std :: list<int>
Data_structure_using_octree_3 <Gt> :: ind_neighbor_son (Direction d)
{
std::list<int> ind ;
switch (d)
{
case BACK :
ind.push_front(0) ;
ind.push_front(1) ;
ind.push_front(2) ;
ind.push_front(3) ;
break;
case FRONT :
ind.push_front(4) ;
ind.push_front(5) ;
ind.push_front(6) ;
ind.push_front(7) ;
break;
case DOWN :
ind.push_front(0) ;
ind.push_front(1) ;
ind.push_front(4) ;
ind.push_front(5) ;
break;
case UP :
ind.push_front(2) ;
ind.push_front(3) ;
ind.push_front(6) ;
ind.push_front(7) ;
break;
case RIGHT :
ind.push_front(0) ;
ind.push_front(2) ;
ind.push_front(4) ;
ind.push_front(6) ;
break;
case LEFT :
ind.push_front(1) ;
ind.push_front(3) ;
ind.push_front(5) ;
ind.push_front(7) ;
break;
default : //it mustn't be
CGAL_kernel_assertion_msg(false,"error .... ");
return ind;
}
return ind;
}
//-----------------------------------------------------------------------------
//we found the neighbor node "voisin" of a given node, we want to
//know all the neighbor leafs of this node. So we go down the tree,
//choosing in voisin each child which its corresponding block have a
//side includ in side of voisin's block in direction D.
template <class Gt>
std :: list<typename Data_structure_using_octree_3 <Gt> :: Node*>
Data_structure_using_octree_3 <Gt> :: go_to_neighbor ( Node* voisin,
Direction d)
{
//CGAL :: Timer t0;
//t0.start();
//std::cerr<<"entree dans gotoneighbor"<<endl;
std::list<Node*> result, aux;
if (is_leaf(voisin)){
result.push_front(voisin);
return result;
}
else {
//do the same with each child.
std::list<int> ind_fils = ind_neighbor_son (d);
std::list<int> :: iterator
ifit = ind_fils.begin(),
ifend = ind_fils.end();
while (ifit != ifend){
if (voisin->fils[(*ifit)] != NULL ) {
if (is_leaf(voisin->fils[(*ifit)])){
result.push_front(voisin->fils[(*ifit)]);
}
else{
aux = go_to_neighbor(voisin->fils[(*ifit)],d);
result.merge (aux);
}
}
ifit++;
}
}
return result;
}
//-----------------------------------------------------------------------------
//return the neighbor leaf of a given node noeud in the diection D.
template <class Gt>
std :: list<typename Data_structure_using_octree_3 <Gt> :: Node*>
Data_structure_using_octree_3 <Gt> ::
find_face_neighbor (Node* noeud, Direction d)
{
//curant neighbor node
Node* voisin = &*noeud;
//n --> for going down the tree(step 2) keep in memory the path...
//p --> index of the node
Name n, p = noeud->nom;
n.clear();
Name :: iterator
pbeg = --p.begin(),
pit = --p.end();
while (pit != pbeg)
{
if ( NU[(*pit)][d]) //( nu((*pit),d))
{//compute n for step 2
n.push_front(PSI[(*pit)][d]); //psi((*pit),d));
//go up to the father
if (voisin->pere != NULL )
voisin =&*( voisin->pere);
else
{// it mustn't be
CGAL_kernel_assertion_msg(false,"error : voisin->pere = NULL");
break;
}
--pit;
}
else
{
//the neighbor is a present in the same octant of voisin
//voisin->pere is the first common ancestor of the node and
//its neighbor
if ( voisin->pere != NULL )
voisin = &*( voisin->pere);
else {
CGAL_kernel_assertion_msg(false,"error : voisin->pere = NULL");
//break;
}
//we compute the neighbor node in the octant
n.push_front(PSI[(*pit)][d]); //psi((*pit),d));
// go down the tree
Name::iterator
nit = n.begin(),
nend = n.end();
while (nit != nend)
{
if ( !(is_leaf(voisin)))
voisin =&*( voisin->fils[(*nit)]);
else
break;
++nit;
}
pit = pbeg;
}
}
//we found the neighbor node of noeud in the direction D. Now, we
//want to know all the neighbor leafs of this node.
std::list< Node* > result, aux;
if ( voisin->nom.size() !=0) {
if (is_leaf(voisin)) {
result.push_front(voisin);
return result;
}
else {
std::list<int> ind_fils = ind_neighbor_son (d);
std::list<int> :: iterator
ifit = ind_fils.begin(),
ifend = ind_fils.end();
while (ifit != ifend)
{
if (voisin->fils[(*ifit)] != NULL ) {
if (is_leaf(voisin->fils[(*ifit)])){
result.push_front(voisin->fils[(*ifit)]);
}
else {
aux = go_to_neighbor(voisin->fils[(*ifit)],d);
result.merge (aux);
}
}
ifit++;
}
}
}
return result;
}
//-----------------------------------------------------------------------------
//return the node correspomding to the name p
template <class Gt>
typename Data_structure_using_octree_3 <Gt> :: Node*
Data_structure_using_octree_3 <Gt> :: go_to_node (Octree o, Name p) {
if (p.empty()){
return o;
}
else {
int pn = p.front();
p.pop_front ();
if (o->fils[pn] != NULL )
return go_to_node (o->fils[pn],p);
else {
return o;
}
}
}
//-----------------------------------------------------------------------------
//return true iff o is a leaf
template <class Gt>
bool
Data_structure_using_octree_3 <Gt> :: is_leaf(Node* o)
{
for (int i = 0; i<8 ; i++ )
{
if (o->fils[i] != NULL)
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// locate a point p in the octree
template <class Gt>
typename Data_structure_using_octree_3 <Gt> :: Node*
Data_structure_using_octree_3 <Gt> :: locate(Octree o, Point p)
{
typename Geom_traits:: Has_on_bounded_side_3 has_on_bounded_side
=gt.has_on_bounded_side_3_object();
typename Geom_traits:: Has_on_boundary_3 has_on_boundary
=gt.has_on_boundary_3_object();
/*std::cout<<"localisation dans : ";
for( Name::iterator it = o->nom.begin(); it != o->nom.end(); it++)
std::cout<<*it<<" ";
std::cout<<std::endl;*/
//std::cout<<o->boite<<std::endl;
if ( (has_on_bounded_side(o->boite,p))||
(has_on_boundary(o->boite ,p)))
{
if (is_leaf(o)) {
return o;
}
else {
//look at the child whose block contain p
for (int i=0;i<8;i++){
if ( (has_on_bounded_side(o->fils[i]->boite ,p))
|| (has_on_boundary(o->fils[i]->boite ,p))){
return locate(o->fils[i] ,p);
}
}
}
}
//else
// std::cout<<"is not in bounded side..."<<std::endl;
//std::cout<<"the point p lie outside the bounding box"<<std::endl;
return NULL;
}
//-----------------------------------------------------------------------------
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Nb
Data_structure_using_octree_3<Gt> :: squared_distance2(Point p,Triangle t)
{
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
typename Geom_traits::Construct_segment_3
construct_segment = gt.construct_segment_3_object();
typename Geom_traits:: Compute_squared_distance_3
compute_squared_distance = gt.compute_squared_distance_3_object();
Nb res,restemp;
Point
a0 = construct_vertex(t,0),
a1 = construct_vertex(t,1),
a2 = construct_vertex(t,2);
Vector v0,v1,v2;
v0 = a2 - a1;
v1 = a0 - a2;
v2 = a1 - a0;
//normal of the plane a0a1a2
Vector N = cross_product(v0,v1);
//let p' the projected point of p on the plane a0a1a2
bool b0=0,b1=0,b2=0;
//test if p' is anticlockwise of v0
if (cross_product(v0,p - a0)*N >0)
b0 = 1;
//test if p' is anticlockwise of v1
if (cross_product(v1,p - a1)*N >0)
b0 = 1;
//test if p' is anticlockwise of v2
if (cross_product(v2,p - a2)*N >0)
b0 = 1;
if (b0*b1*b2) {
res = (N*(p - a1)*
(N*(p - a1)/(N*N)));
}
else{
Segment
e1 = construct_segment (a0,a1),
e2 = construct_segment (a0,a2),
e3 = construct_segment (a1,a2);
res = squared_distance(p,e1);
restemp = squared_distance(p,e2);
if (res > restemp) res = restemp;
restemp = squared_distance(p,e3);
if (res > restemp) res = restemp;
}
return res;
}
//----------------------------------------------------------------------------
//compute the distance between a point and the side of c in direction d
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Nb
Data_structure_using_octree_3<Gt> ::squared_distance_to_side( Point p,
Iso_Cuboid c,
Direction d)
{
typename Geom_traits::Construct_plane_3 construct_plane =
gt.construct_plane_3_object();
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
Point q,r,s,t;
switch (d){
case FRONT :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,6);
s = construct_vertex(c,5);
break;
case BACK :
t = construct_vertex(c,2);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case UP :
t = construct_vertex(c,6);
q = construct_vertex(c,5);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case DOWN :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,2);
s = construct_vertex(c,3);
break;
case LEFT :
t = construct_vertex(c,0);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,5);
break;
case RIGHT :
t = construct_vertex(c,1);
q = construct_vertex(c,2);
r = construct_vertex(c,7);
s = construct_vertex(c,6);
break;
default : //it mustn't be
CGAL_kernel_assertion_msg(false,"error .... ");
return -4;
}
typename Geom_traits::Construct_triangle_3
construct_triangle = gt.construct_triangle_3_object();
Triangle
t1 = construct_triangle(t,q,s),
t2 = construct_triangle(q,r,s);
Nb
d1 = squared_distance2(p,t1),
d2 = squared_distance2(p,t2);
if (d1<d2) return d1;
else return d2;
}
//-----------------------------------------------------------------------------
//compute the distance between a point p and all constraints whose
//intersect the node noeu.
//input : a point p and a node noeud
//output : the map md such that md[i]= the distance between p and the
//ith constraint
// the list od, well-ordered such that for i<j, md[od[i]] is
// nearest p than md[od[j]]
template <class Gt>
bool
Data_structure_using_octree_3<Gt> ::
squared_distance_to_constraint_in_node(Point p,
Node* noeud,
std::map<int,Nb>* md,
std::list<int>* od)
{
//CGAL :: Timer t0;
//t0.start();
Nb dist;
std::pair<int,Nb> d_aux;
if ( noeud != NULL ){
//compute the distance between p and all the constraints of noeud.
Ind_constraint_list :: iterator
iclit = noeud->i_c_l.begin(),
iclend = noeud->i_c_l.end();
while (iclit != iclend){
if ( md->find((*iclit)) == md->end() ) {
// Compute the distance between p and the constraint (*iclit)
dist = c_m[(*iclit)]->sqared_distance_to_sheet(p);
d_aux.first = (*iclit);
d_aux.second = dist;
md->insert(d_aux);
if (od->empty()) // it's the first constraint
od->push_front((*iclit));
else { // find where we have to put the constraint in od
std::list<int> :: iterator
it = od->begin(),
end = od->end();
while ((it != end) && ( (*md)[(*it)]<dist))
it++;
od->insert(it,(*iclit));
}
}
iclit++;
}
return true;
}
return false;
}
//-----------------------------------------------------------------------------
//lfs auxiliary function... compute the lfs with shewchuk definition
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Nb
Data_structure_using_octree_3<Gt> ::
lfs_cont( Point p,
Node* noeud,
std::map<int,Nb>* distance,
std::list<int>* ordre,
std::map<Name,bool>* visited_cube,
typename Data_structure_using_octree_3<Gt> :: Nb min)
{
std :: list<Node*> voisins;
(*visited_cube)[noeud->nom] = true;
if (noeud->i_c_l.size()!= 0){
//compute the distance between p and all constraints of the node
//whose containt it
squared_distance_to_constraint_in_node(p,noeud,distance,ordre);
//we go through ordre until we find 2 separates constraints
//nearest p
std::list<int> :: iterator
oit = ordre->begin(),
oend = ordre->end();
bool encours = true;
int i =0;
while ((oit != oend) && (encours) )
{
std::list<int> :: iterator oit2 = ordre->begin();
int j = 0;
while ( (oit2 != oit) && (encours) )
{
std::cout<<" couple "<<i<<", "<<j<<std::endl;
if ( !( c_m[(*oit2)]->does_intersect( c_m[(*oit)])) )
{
Nb d = (*distance)[(*oit2)];
std::cout<<" d = "<<d<<std::endl;
if ( d>PREC ) {
//min = d;
min = (*distance)[(*oit)];
encours = false;
}
}
else
std::cout<<"(c_m[(*oit2)]->does_intersect( c_m[(*oit)]))"<<std::endl;
oit2++;
j++;
}
oit++;
i++;
std::cout<<"\tmin = "<<min<<std::endl;
}
}
//visiting neighbor in each direction
Direction tdir[6] = {FRONT, BACK, UP, DOWN, LEFT, RIGHT};
Nb l;
for (int i=0; i<6;i++) {
Nb dc = squared_distance_to_side (p ,noeud->boite,tdir[i]);
if ( (min == -1) || ( dc < min ) ){
voisins = find_face_neighbor(noeud,tdir[i]);
typename std::list<Node*> :: iterator
vit = voisins.begin(),
vend = voisins.end();
while (vit != vend){
if (!((*visited_cube)[(*vit)->nom])){
l=lfs_cont(p,(*vit),distance,ordre,visited_cube,min);
if ( (min == -1) || (l < min))
min = l;
}
vit++;
}
}
}
return min;
}
//-----------------------------------------------------------------------------
//lfs auxiliary function... compute the lfs with the definition 2
template <class Gt>
typename Data_structure_using_octree_3<Gt> ::Nb
Data_structure_using_octree_3<Gt> :: lfs_simp( Point p,
Node* noeud,
std::map<int,Nb>* distance,
std::list<int>* ordre,
std::map<Name,bool>*
visited_cube,
Nb min)
{
std :: list<Node*> voisins;
(*visited_cube)[noeud->nom] = true;
if (noeud->i_c_l.size()!= 0){
//compute the distance between p and all constraints of the node
//whose containt it
squared_distance_to_constraint_in_node(p,noeud,distance,ordre);
//we go through ordre until we find a constraint such that its
//distance to p is greater than PREC
//ie find the nearest constraint (of noeud) whose not containt p.
std::list<int> :: iterator
oit = ordre->begin(),
oend = ordre->end();
bool encours = true;
while ((oit != oend) && (encours) ){
Nb d = (*distance)[(*oit)];
if (d>PREC) {
min = d;
encours = false;
}
oit++;
}
}
//visiting neighbor in each direction
Direction tdir[6] = {FRONT, BACK, UP, DOWN, LEFT, RIGHT};
Nb l;
//std::cout<<"visite des voisins"<<std::endl;
for (int i=0; i<6;i++) {
Nb dc = squared_distance_to_side (p ,noeud->boite,tdir[i]);
if ( (min == -1) || ( dc < min ) ){
voisins = find_face_neighbor(noeud,tdir[i]);
typename std::list<Node*> :: iterator
vit = voisins.begin(),
vend = voisins.end();
while (vit != vend){
if (!((*visited_cube)[(*vit)->nom])) {
l=lfs_simp(p,(*vit),distance,ordre,visited_cube,min);
if ( (min == -1) || (l < min))
min = l;
}
vit++;
}
}
}
return min;
}
//-----------------------------------------------------------------------------
//Compute the lfs with shewchuk definition
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Nb
Data_structure_using_octree_3<Gt> :: lfs(Point p){
// lfs_time.start();
std::list<int> ordre ;
std::map<int,Nb> distance;
std::map<Name,bool> visited_cube;
//locate the point p in the octree
Node* noeud = locate(arbre,p);
// CGAL::Timer t0;
// std::cout<<count++<<" - point traite : "<<p<<endl;
// t0.start();
Nb l=-3;
if (noeud != NULL){
l= lfs_cont(p,noeud,&distance,&ordre,&visited_cube,-1 );
}
else
std::cout<<"Noeud == NULL"<<std::endl;
// t0.stop();
//std::cout<<"lfs calculee en "<<t0.time()<<endl;
// tl = tl +t0.time();
// lfs_time.stop();
return l;
}
//-----------------------------------------------------------------------------
//Compute the lfs with the definition 2
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Nb
Data_structure_using_octree_3<Gt> :: lfs2(Point p)
{
// lfs_time.start();
//std::cout<<"Point : "<<p<<std::endl;
std::list<int> ordre ;
std::map<int,Nb> distance;
std::map<Name,bool> visited_cube;
//locate the point p in the octree
Node* noeud = locate(arbre,p);
// CGAL::Timer t0;
// std::cout<<count++<<" - point traite : "<<p<<endl;
// t0.start();
Nb l=-3;
if (noeud != NULL)
{
l= lfs_simp(p,noeud,&distance,&ordre,&visited_cube,-1 );
}
// t0.stop();
//std::cout<<"lfs calculee en "<<t0.time()<<endl;
//std::cout<<"lfs de ce point = "<<l<<endl<<endl;
//std::cout<<tl<<endl;
// tl = tl +t0.time();
// lfs_time.stop();
return l;
}
//----------------------------------------------------------------------------
//Return true iff seg intersect the side of c in the direction d
template <class Gt>
bool
Data_structure_using_octree_3<Gt> :: does_intersect( Segment seg,
Iso_Cuboid c,
Direction d)
{
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
typename Geom_traits:: Is_degenerate_3 is_degenerate
=gt.is_degenerate_3_object();
typename Geom_traits::Construct_triangle_3
construct_triangle = gt.construct_triangle_3_object();
if (is_degenerate(seg))
return false;
if (is_degenerate(c))
return false;
//q, r, s and t are the vertex of the side of c in the direction d
Point q,r,s,t;
switch (d)
{
case FRONT :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,6);
s = construct_vertex(c,5);
break;
case BACK :
t = construct_vertex(c,3);
q = construct_vertex(c,2);
r = construct_vertex(c,7);
s = construct_vertex(c,4);
break;
case UP :
t = construct_vertex(c,6);
q = construct_vertex(c,5);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case DOWN :
t = construct_vertex(c,1);
q = construct_vertex(c,0);
r = construct_vertex(c,3);
s = construct_vertex(c,2);
break;
case LEFT :
t = construct_vertex(c,0);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,5);
break;
case RIGHT :
t = construct_vertex(c,1);
q = construct_vertex(c,2);
r = construct_vertex(c,7);
s = construct_vertex(c,6);
break;
default : //ca ne doit pas arriver !!
CGAL_kernel_assertion_msg(false,"error .... ");
return -4;
}
Triangle
t1 = construct_triangle(t,q,r),
t2 = construct_triangle(t,r,s);
return ( (do_intersect (t1,seg))
|| (do_intersect (t2,seg)) );
}
//----------------------------------------------------------------------------
//Return true iff ray intersect the side of c in the direction d
template <class Gt>
bool
Data_structure_using_octree_3<Gt> :: does_intersect( Ray ray,
Iso_Cuboid c,
Direction d)
{
typename Geom_traits::Construct_plane_3 construct_plane =
gt.construct_plane_3_object();
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
typename Geom_traits:: Is_degenerate_3 is_degenerate
=gt.is_degenerate_3_object();
if (is_degenerate(ray))
return false;
if (is_degenerate(c))
return false;
Point q,r,s,t;
switch (d)
{
case FRONT :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,6);
s = construct_vertex(c,5);
break;
case BACK :
t = construct_vertex(c,2);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case UP :
t = construct_vertex(c,6);
q = construct_vertex(c,5);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case DOWN :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,2);
s = construct_vertex(c,3);
break;
case LEFT :
t = construct_vertex(c,0);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,5);
break;
case RIGHT :
t = construct_vertex(c,1);
q = construct_vertex(c,2);
r = construct_vertex(c,7);
s = construct_vertex(c,6);
break;
default : //ca ne doit pas arriver !!
CGAL_kernel_assertion_msg(false,"error .... ");
return -4;
}
typename Geom_traits::Construct_triangle_3
construct_triangle = gt.construct_triangle_3_object();
Triangle
t1 = construct_triangle(q,s,r),
t2 = construct_triangle(q,s,t);
return ( (do_intersect(t1,ray)) ||
(do_intersect(t2,ray)) );
}
//----------------------------------------------------------------------------
//Construct the intersection between seg and the side of c in the
//direction d...
//PRECONDITION: seg intersect the side of c in the direction d
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Point
Data_structure_using_octree_3<Gt> :: intersection ( Segment seg,
Iso_Cuboid c,
Direction d)
{
typename Geom_traits::Construct_plane_3 construct_plane =
gt.construct_plane_3_object();
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
typename Geom_traits::Intersect_3 intersect =
gt.intersect_3_object();
typename Geom_traits:: Assign_3 assign =
gt.assign_3_object();
typename Geom_traits:: Is_degenerate_3 is_degenerate
=gt.is_degenerate_3_object();
CGAL_kernel_exactness_precondition( ! c.is_degenerate() ) ;
CGAL_kernel_exactness_precondition( ! seg.is_degenerate() ) ;
Point q,r,s,t;
switch (d){
case FRONT :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,6);
s = construct_vertex(c,5);
break;
case BACK :
t = construct_vertex(c,2);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case UP :
t = construct_vertex(c,6);
q = construct_vertex(c,5);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case DOWN :
t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,2);
s = construct_vertex(c,3);
break;
case LEFT :
t = construct_vertex(c,0);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,5);
break;
case RIGHT :
t = construct_vertex(c,1);
q = construct_vertex(c,2);
r = construct_vertex(c,7);
s = construct_vertex(c,6);
break;
default : //ca ne doit pas arriver !!
CGAL_kernel_assertion_msg(false,"error .... ");
//return NULL;
}
Plane plan = construct_plane(s,q,r);
typename Gt::Object_3 o = intersect(plan,seg);
Point p ;
assign(p,o);
return p;
}
//----------------------------------------------------------------------------
//return true iff seg intersect the iso_cuboid c
template <class Gt>
bool
Data_structure_using_octree_3<Gt> :: do_intersect2(Iso_Cuboid c, Segment seg)
{
typename Geom_traits::Construct_vertex_3
construct_vertex = gt.construct_vertex_3_object();
typename Geom_traits:: Has_on_bounded_side_3 has_on_bounded_side
=gt.has_on_bounded_side_3_object();
typename Geom_traits::Construct_triangle_3
construct_triangle = gt.construct_triangle_3_object();
typename Geom_traits:: Has_on_boundary_3 has_on_boundary
=gt.has_on_boundary_3_object();
typename Geom_traits:: Is_degenerate_3 is_degenerate
=gt.is_degenerate_3_object();
if (is_degenerate(seg))
return false;
if (is_degenerate(c))
return false;
Point
p = construct_vertex(seg,0),
q = construct_vertex(seg,1);
//test if one of segment vertex lie on the bounded side or on the
// boundary of c
if (has_on_bounded_side(c,p) || has_on_boundary(c,q) ) {
return true;
}
if (has_on_bounded_side(c,q) || has_on_boundary(c,q) ){
return true;
}
//neither of segment vertex lie on the bounded side or on the
// boundary of c ---> construct triangle whose make the sides of c
// and test if segment intersect these triangles.
Point sc[8];
for (int i=0; i<8;i++){
sc[i] = construct_vertex(c,i);
//std::cout << i<<" - "<<sc[i]<<endl;
}
Triangle tf;
tf = construct_triangle(sc[1],sc[3],sc[0]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[1],sc[3],sc[2]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[1],sc[6],sc[0]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[0],sc[6],sc[5]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[1],sc[7],sc[6]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[1],sc[7],sc[2]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[2],sc[4],sc[3]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[2],sc[4],sc[7]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[3],sc[5],sc[0]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[3],sc[5],sc[4]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[5],sc[4],sc[6]);
if (do_intersect(tf,seg)) return true;
tf = construct_triangle(sc[6],sc[4],sc[7]);
if (do_intersect(tf,seg)) return true;
return false;
}
//----------------------------------------------------------------------------
//Construct the intersection between ray and the side of c in the
//direction d...
//PRECONDITION: seg intersect the side of c in the direction d
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Point
Data_structure_using_octree_3<Gt> :: intersection (Ray ray,
Iso_Cuboid c,
Direction d)
{
typename Geom_traits::Construct_plane_3 construct_plane =
gt.construct_plane_3_object();
typename Geom_traits::Construct_vertex_3 construct_vertex =
gt.construct_vertex_3_object();
typename Geom_traits::Intersect_3 intersect =
gt.intersect_3_object();
typename Geom_traits:: Assign_3 assign =
gt.assign_3_object();
typename Geom_traits:: Is_degenerate_3 is_degenerate
=gt.is_degenerate_3_object();
CGAL_kernel_exactness_precondition( ! c.is_degenerate() ) ;
CGAL_kernel_exactness_precondition( ! ray.is_degenerate() ) ;
Point q,r,s,t;
switch (d)
{
case FRONT :
//t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,6);
s = construct_vertex(c,5);
break;
case BACK :
//t = construct_vertex(c,2);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case UP :
//t = construct_vertex(c,6);
q = construct_vertex(c,5);
r = construct_vertex(c,4);
s = construct_vertex(c,7);
break;
case DOWN :
//t = construct_vertex(c,0);
q = construct_vertex(c,1);
r = construct_vertex(c,2);
s = construct_vertex(c,3);
break;
case LEFT :
//t = construct_vertex(c,0);
q = construct_vertex(c,3);
r = construct_vertex(c,4);
s = construct_vertex(c,5);
break;
case RIGHT :
//t = construct_vertex(c,1);
q = construct_vertex(c,2);
r = construct_vertex(c,7);
s = construct_vertex(c,6);
break;
default : //ca ne doit pas arriver !!
CGAL_kernel_assertion_msg(false,"error .... ");
//return NULL;
}
Plane plan = construct_plane(q,r,s);
typename Gt::Object_3 o = intersect(plan,ray);
Point p ;
assign(p,o);
return p;
}
//----------------------------------------------------------------------------
//Check if there is a constraint whose intersect the segment pq... if
//this intersection exist then compute it.
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Object
Data_structure_using_octree_3<Gt> :: intersect( Point p,
Point q)
{
// ri_time.start();
typename Geom_traits::Construct_segment_3 construct_segment =
gt.construct_segment_3_object();
typename Geom_traits:: Is_degenerate_3 is_degenerate
=gt.is_degenerate_3_object();
std::map<Name,bool> visited_cube;
//locate the point p in the octree
Node* noeud = locate(arbre,p);
int ind_fc = -1;
Segment s = construct_segment(p,q);
if (is_degenerate(s))
return Object();
if (noeud != NULL) {
ind_fc = sci_aux(p,s,noeud,&visited_cube);
}
else{
//p doesn't lie in the bounding box so locate q in the octree
noeud = locate(arbre,q);
if (noeud != NULL){
ind_fc = sci_aux(q,s,noeud,&visited_cube);
}
else{
//p and q don't lie in the bounding box so chek if the segment
//pq intersect a side of the bounding box, if an intersection
//exist, compute it and locate it
Direction tdir[6] = {FRONT, BACK, UP, DOWN, LEFT, RIGHT};
int i= 0;
bool find = false;
while ((i<6) && (!(find))){
if (does_intersect(s,arbre->boite,tdir[i])) {
//we found the side of the bbox s intersect.
find = true;
//locate the intersection point
Point r = intersection(s,arbre->boite,tdir[i]);
noeud = locate(arbre,r);
if (noeud != NULL) {
ind_fc = sci_aux(r,s,noeud,&visited_cube);
}
}
i++;
}
}
}
// ri_time.stop();
if (ind_fc == -1) {
//we didn't find a constraint intersected by s
//std::cout<<"false"<<endl<<endl;
return Object();
}
else {
//std::cout<<"true"<<endl<<endl;
return c_m[ind_fc]->intersection(s);
}
}
//----------------------------------------------------------------------------
// auxiliary function of intersect
template <class Gt>
int
Data_structure_using_octree_3<Gt> :: sci_aux (Point p,
Segment s,
Node* noeud,
std::map<Name,bool>*
visited_cube)
{
int ind_min = -1;
std :: list<Node*> voisins;
//mark the cube --> we don't want to viste it again
(*visited_cube)[noeud->nom] = true;
//affichage
// Name :: iterator
// nomit = noeud->nom.begin(),
// nomend = noeud->nom.end();
// while (nomit != nomend)
// {
// std::cerr<<(*nomit);
// nomit++;
// }
// std::cerr<<endl;
//std::cerr<<"boite correspondante "<<noeud->boite<<endl;
//std::cerr<<"nombre de contraintes du noeud : "<<noeud->i_c_l.size()<<endl;
//fin affichage
Ind_constraint_list :: iterator
iclit = noeud->i_c_l.begin(),
iclend = noeud->i_c_l.end();
bool find = false;
while ((iclit != iclend) && (!(find)) )
{
if (c_m[(*iclit)]->does_intersect(s)) {
ind_min = (*iclit);
//stop when the first constaint is found
find = true;
}
iclit++;
}
if (!(find)) {
//we didn't find constraint whose intersect the segment, so we
//look at the neighbor
Direction tdir[6] = {FRONT, BACK, UP, DOWN, LEFT, RIGHT};
int i = 0;
while ((i<6) && (!(find))) {
if (does_intersect(s,noeud->boite,tdir[i])) {
voisins = find_face_neighbor(noeud,tdir[i]);
typename std::list<Node*> :: iterator
vit = voisins.begin(),
vend = voisins.end();
while ((vit != vend) && (!(find))){
if (!((*visited_cube)[(*vit)->nom])) {
if (do_intersect2((*vit)->boite,s)) {
ind_min = sci_aux(p,s,(*vit),visited_cube );
if (ind_min != -1 )
find = true;
}
}
vit++;
}
}
i++;
}
}
return ind_min;
}
//----------------------------------------------------------------------------
//Check if there is a constraint whose intersect ray... if
//this intersection exist then compute it.
template <class Gt>
typename Data_structure_using_octree_3<Gt> :: Object
Data_structure_using_octree_3<Gt> :: intersect(Ray r)
{
// ri_time.start();
typename Geom_traits::Construct_segment_3 construct_segment =
gt.construct_segment_3_object();
typename Geom_traits::Construct_point_on_3 construct_point_on =
gt.construct_point_on_3_object();
std::map<Name,bool> visited_cube;
std::set<Point, typename Geom_traits::Compare_xyz_3> lp;
//find the side of the bbox is intersected by ray
Direction tdir[6] = {FRONT, BACK, UP, DOWN, LEFT, RIGHT};
for (int i=0;i<6;i++){
if (does_intersect(r,arbre->boite,tdir[i]))
{
Point p = intersection(r,arbre->boite,tdir[i]);
lp.insert(p);
//std::cout<<"une intersection trouvee "<<p<<std::endl;
}
}
Point origin = construct_point_on(r, 0);
Point p,q;
if (lp.size()==2) {
p = *(lp.begin());
q = *(--lp.end());
//std::cout<<"deux intersections "<<p<<" et "<<q<<std::endl;
return intersect(p,q);
}
else if (lp.size()==1) {
p = *(lp.begin());
//std::cout<<"une intersection "<< p <<std::endl;
return intersect(p,origin);
}
else
{
//std::cout<<"pas d'intersection"<<std::endl;
return Object();
}
}
CGAL_END_NAMESPACE
#endif