MEPP2 Project
boolops_polyhedra.hpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published
6 // by the Free Software Foundation; either version 3 of the License,
7 // or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 
12 #pragma once
13 
19 #include <CGAL/IO/Polyhedron_iostream.h>
20 
21 #include <CGAL/AABB_tree.h>
22 #include <CGAL/AABB_triangle_primitive.h>
23 #include <CGAL/AABB_traits.h>
24 #include "boolops_definitions.hpp"
25 #include "boolops_properties.h"
29 
30 #include <CGAL/boost/graph/copy_face_graph.h> // for CGAL::copy_face_graph()
31 #include <CGAL/boost/graph/helpers.h> // for CGAL::clear() and CGAL::is_closed()
32 
33 #include <boost/graph/graph_traits.hpp>
36 #include <list>
37 #include <stack>
38 #include <stdexcept> // for std::runtime_error
39 
40 
45 typedef typename EnrichedPolyhedron::HalfedgeDS HDS;
48 
52 //typedef CGAL::Simple_cartesian<num_type> AABB_Kernel;
53 typedef CGAL::Simple_cartesian<double> AABB_Kernel;
54 
58 class Enriched_Triangle : public AABB_Kernel::Triangle_3
59 {
60 public:
64  typedef AABB_Kernel::Point_3 Point_3;
65 
69  typedef AABB_Kernel::FT FT;
70 
76  : AABB_Kernel::Triangle_3(
77  to_K(_f->facet_begin()->vertex()->point() +
78  (_f->facet_begin()->vertex()->point() -
79  _f->facet_begin()->next()->vertex()->point()) /
80  1000),
81  to_K(_f->facet_begin()->next()->vertex()->point() +
82  (_f->facet_begin()->next()->vertex()->point() -
83  _f->facet_begin()->next()->next()->vertex()->point()) /
84  1000),
85  to_K(_f->facet_begin()->next()->next()->vertex()->point() +
86  (_f->facet_begin()->next()->next()->vertex()->point() -
87  _f->facet_begin()->vertex()->point()) /
88  1000)),
89  f(_f)
90  {
91  }
92 
96  Facet_handle facet() { return f; }
97 
102  template < typename Point3d >
103  inline Point_3 to_K(const Point3d &p)
104  {
105  return Point_3((FT)p.x(), (FT)p.y(), (FT)p.z());
106  }
107 
108 private:
111 };
112 
113 
119 typedef CGAL::AABB_triangle_primitive< AABB_Kernel,
120  std::list< Triangle >::iterator >
124 typedef CGAL::AABB_traits< AABB_Kernel, AABB_Primitive > AABB_Traits;
127 typedef CGAL::AABB_tree< AABB_Traits > AABB_Tree;
128 
129 
132 template< typename HalfedgeGraph >
134 {
135 private:
140  {
147  std::vector< std::vector< InterId > > CutList;
149  std::set< InterId > PtList;
151  std::map< HalfedgeId, InterId > RefInter;
152 
159  {
160  norm_dir = V;
161  Facet_from_A = ffA;
162  } // MT
163  };
164 
169  struct Info_Inter
170  {
186  unsigned short res;
191  };
192 
193 public:
200  BoolPolyhedra(HalfedgeGraph &_gA,
201  HalfedgeGraph &_gB,
202  HalfedgeGraph &_g_out,
203  Bool_Op BOOP)
204  : m_BOOP(BOOP)
205  {
206 #ifdef BOOLEAN_OPERATIONS_TIME
207  auto time_total_start = std::chrono::steady_clock::now();
208  auto time_start = time_total_start;
209 #endif // BOOLEAN_OPERATIONS_TIME
210 
211  // ensure both input meshes are closed (no border edge)
212  if(!(CGAL::is_closed(_gA) && CGAL::is_closed(_gB)))
213  {
214  throw std::runtime_error(
215  "Boolean Operation: only closed meshes are allowed.");
216  }
217 
218  // convert input meshes to enriched Polyhedrons
221  CGAL::copy_face_graph(_gA, gA);
222  CGAL::copy_face_graph(_gB, gB);
223 
224 #ifdef BOOLEAN_OPERATIONS_TIME
226 #endif // BOOLEAN_OPERATIONS_TIME
227 
228 #ifdef BOOLEAN_OPERATIONS_DEBUG
229  {
230  std::ofstream ofstrMA("boolean_operation__input_A.off");
231  ofstrMA << gA;
232  std::ofstream ofstrMB("boolean_operation__input_B.off");
233  ofstrMB << gB;
234  }
235 #endif // BOOLEAN_OPERATIONS_DEBUG
236 
237  Init(&gA, &gB);
238 
239 #ifdef BOOLEAN_OPERATIONS_TIME
240  duration_Init = get_time_and_reset(time_start);
241 #endif // BOOLEAN_OPERATIONS_TIME
242 
243  FindCouples();
244 
245 #ifdef BOOLEAN_OPERATIONS_TIME
247 #endif // BOOLEAN_OPERATIONS_TIME
248 
249  if(!m_Couples.empty())
250  {
252 
253 #ifdef BOOLEAN_OPERATIONS_TIME
255 #endif // BOOLEAN_OPERATIONS_TIME
256 
258 
259 #ifdef BOOLEAN_OPERATIONS_TIME
261 #endif // BOOLEAN_OPERATIONS_TIME
262 
263  PropagateFacets();
264 
265 #ifdef BOOLEAN_OPERATIONS_TIME
267 #endif // BOOLEAN_OPERATIONS_TIME
268 
269  // build output mesh
270  EnrichedPolyhedron g_out;
271  g_out.delegate(ppbuilder);
272 
273 #ifdef BOOLEAN_OPERATIONS_TIME
275 #endif // BOOLEAN_OPERATIONS_TIME
276 
277 #ifdef BOOLEAN_OPERATIONS_DEBUG
278  std::ofstream ofstrMS("boolean_operation_output.off");
279  ofstrMS << g_out;
280  WriteData(g_out);
281  ColorType();
282  std::ofstream ofstrColorInput("boolean_operation__input_A_colorized.off");
283  ofstrColorInput << gA;
284 #endif // BOOLEAN_OPERATIONS_DEBUG
285 
286  // convert output mesh from enriched Polyhedrons
287  CGAL::clear(_g_out);
288  CGAL::copy_face_graph(g_out, _g_out);
289 
290 #ifdef BOOLEAN_OPERATIONS_TIME
292  duration_total = get_time_and_reset(time_total_start);
293 
294  // print short stats about times and mesh sizes
295  std::cout << "Computation time :" << std::endl;
296  std::cout << " + Copying input meshes : "
298  << " s"
299  << std::endl;
300  std::cout << " + Initialization : "
301  << tr(duration_Init)
302  << " s"
303  << std::endl;
304  std::cout << " + Finding the Intersections : "
306  << " s"
307  << std::endl;
308  std::cout << " + Compute the Intersections : "
310  << " s"
311  << std::endl;
312  std::cout << " + Cut the Intersected Facets : "
314  << " s"
315  << std::endl;
316  std::cout << " + Complete the result : "
318  << " s"
319  << std::endl;
320  std::cout << " + Create the polyhedron : "
322  << " s"
323  << std::endl;
324  std::cout << " + Copying output mesh : "
326  << " s"
327  << std::endl;
328  std::cout << "---------------------------------------"
329  << std::endl;
330  std::cout << " Total : "
331  << tr(duration_total)
332  << " s"
333  << std::endl;
334 
335  std::cout << std::endl;
336  std::cout << "Details :" << std::endl;
337  std::cout << std::endl;
338  std::cout << "Polyedron A :" << std::endl;
339  std::cout << "Number of Facets : "
340  << m_pA->size_of_facets() << std::endl;
341  std::cout << std::endl;
342  std::cout << "Polyedron B :" << std::endl;
343  std::cout << "Number of Facets : "
344  << m_pB->size_of_facets() << std::endl;
345  std::cout << std::endl;
346  std::cout << "Result :" << std::endl;
347  std::cout << "Number of Facets : "
348  << g_out.size_of_facets() << std::endl;
349 #endif // BOOLEAN_OPERATIONS_TIME
350  }
351  }
352 
355 
356 private:
361  EnrichedPolyhedron *pMB)
362  {
363  // use pointers over meshes to keep Mepp1 code unchanged
364  m_pA = pMA;
365  m_pB = pMB;
366 
367  // triangulation of the two input polyhedra
368  // this is necessary for the AABB-tree, and simplify the computation of the
369  // intersections
370  if(!m_pA->is_pure_triangle())
371  triangulate(m_pA);
372  if(!m_pB->is_pure_triangle())
373  triangulate(m_pB);
374 
375  // initialize the tags
376  for(Vertex_iterator pVertex = m_pA->vertices_begin();
377  pVertex != m_pA->vertices_end();
378  ++pVertex)
379  {
380  pVertex->Label = 0xFFFFFFFF;
381  }
382  for(Vertex_iterator pVertex = m_pB->vertices_begin();
383  pVertex != m_pB->vertices_end();
384  ++pVertex)
385  {
386  pVertex->Label = 0xFFFFFFFF;
387  }
388  for(Facet_iterator pFacet = m_pA->facets_begin();
389  pFacet != m_pA->facets_end();
390  ++pFacet)
391  {
392  pFacet->Label = 0xFFFFFFFF;
393  pFacet->IsExt = false;
394  pFacet->IsOK = false;
395  }
396  for(Facet_iterator pFacet = m_pB->facets_begin();
397  pFacet != m_pB->facets_end();
398  ++pFacet)
399  {
400  pFacet->Label = 0xFFFFFFFF;
401  pFacet->IsExt = false;
402  pFacet->IsOK = false;
403  }
404 
405 #ifdef BOOLEAN_OPERATIONS_DEBUG_VERBOSE
406  {
407  // init HE property maps to be able to compare
408  // with Mepp1
409  EnrichedPolyhedron::Halfedge_iterator pHe;
410  for(pHe = m_pA->halfedges_begin(); pHe != m_pA->halfedges_end(); pHe++)
411  pHe->Label = 42424242;
412  for(pHe = m_pB->halfedges_begin(); pHe != m_pB->halfedges_end(); pHe++)
413  pHe->Label = 42424242;
414  }
415 #endif //BOOLEAN_OPERATIONS_DEBUG_VERBOSE
416  }
417 
418 
422  {
423 #ifdef BOOLEAN_OPERATIONS_DEBUG_VERBOSE
424  {
425  std::cout << "Triangulating mesh..." << std::endl;
426  std::cout << "before triangulating mesh:" << std::endl;
427  std::cout << " size_of_vertices = " << m->size_of_vertices() << std::endl;
428  std::cout << " size_of_halfedges = " << m->size_of_halfedges() << std::endl;
429  std::cout << " size_of_facets = " << m->size_of_facets() << std::endl;
430  }
431 #endif //BOOLEAN_OPERATIONS_DEBUG_VERBOSE
432 
433  Facet_iterator f = m->facets_begin();
434  Facet_iterator f2 = m->facets_begin();
435  do // for (; f != this->facets_end(); f++)
436  {
437  f = f2;
438  if(f == m->facets_end())
439  {
440  break;
441  }
442  f2++;
443 
444  if(!(f->is_triangle()))
445  {
446  int num = (int)(f->facet_degree() - 3);
447  Halfedge_handle h = f->halfedge();
448 
449  h = m->make_hole(h);
450 
451  Halfedge_handle g = h->next();
452  g = g->next();
453  Halfedge_handle new_he = m->add_facet_to_border(h, g);
454  g = new_he;
455 
456  num--;
457  while(num != 0)
458  {
459  g = g->opposite();
460  g = g->next();
461  Halfedge_handle new_he = m->add_facet_to_border(h, g);
462  g = new_he;
463 
464  num--;
465  }
466 
467  m->fill_hole(h);
468  }
469 
470  } while(true);
471 
472 #ifdef BOOLEAN_OPERATIONS_DEBUG_VERBOSE
473  {
474  std::cout << "after triangulating mesh:" << std::endl;
475  std::cout << " size_of_vertices = " << m->size_of_vertices() << std::endl;
476  std::cout << " size_of_halfedges = " << m->size_of_halfedges() << std::endl;
477  std::cout << " size_of_facets = " << m->size_of_facets() << std::endl;
478  }
479 #endif //BOOLEAN_OPERATIONS_DEBUG_VERBOSE
480  }
481 
482 
485  void FindCouples()
486  {
487  //A AABB-tree is built on the facets of one of the polyhedra. A collision test is done with each facet of the other polyhedron.
488  Facet_iterator pFacet = NULL;
489  std::list<AABB_Tree::Primitive_id> primitives;
490  std::list<Triangle> triangles;
491 
492  HalfedgeId i = 0;
493  FacetId j = 0;
494 
495  //The AABB-tree is built on the polyhedron with the less number of facets
496  if(m_pA->size_of_facets() < m_pB->size_of_facets())
497  {
498  //Building the AABB-tree on the first polyhedron
499  for(pFacet = m_pA->facets_begin(); pFacet != m_pA->facets_end(); pFacet++) triangles.push_back(Triangle(pFacet));
500  tree.rebuild(triangles.begin(),triangles.end());
501 
502  //collision test with each facet of the second polyhedron
503  for (pFacet = m_pB->facets_begin(); pFacet != m_pB->facets_end(); pFacet++)
504  {
505  //"primitives" is the list of the triangles intersected (as a list of triangles)
506  tree.all_intersected_primitives(Triangle(pFacet), std::back_inserter(primitives));
507  if(primitives.size() !=0)
508  {
509  m_Facet_Handle.push_back(pFacet);
510  //update of the tags (the facet and the three incidents halfedges
511  pFacet->Label = j++;
512  pFacet->facet_begin()->Label = i++;
513  pFacet->facet_begin()->next()->Label = i++;
514  pFacet->facet_begin()->next()->next()->Label = i++;
515  //creation of a Triangle_Cut structure to store the informations about the intersections
516  m_Inter_tri.push_back(Triangle_Cut(Compute_Normal_direction(pFacet->facet_begin()), false));
517  do {
518  //same operations for the intersected primitives (only one time)
519  if(primitives.back()->facet()->Label == 0xFFFFFFFF)
520  {
521  m_Facet_Handle.push_back(primitives.back()->facet());
522  primitives.back()->facet()->Label = j++;
523  primitives.back()->facet()->facet_begin()->Label = i++;
524  primitives.back()->facet()->facet_begin()->next()->Label = i++;
525  primitives.back()->facet()->facet_begin()->next()->next()->Label = i++;
526  m_Inter_tri.push_back(Triangle_Cut(Compute_Normal_direction(primitives.back()->facet()->facet_begin()), true));
527  }
528  //store every couple of intersected facet
529  m_Couples[primitives.back()->facet()->Label].insert(pFacet->Label);
530  primitives.pop_back();
531  }
532  while(primitives.size() != 0);
533  }
534  }
535  }
536  else
537  {
538  //Building the AABB-tree on the second polyhedron
539  for(pFacet = m_pB->facets_begin(); pFacet != m_pB->facets_end(); pFacet++) triangles.push_back(Triangle(pFacet));
540  tree.rebuild(triangles.begin(),triangles.end());
541 
542  //collision test with each facet of the first polyhedron
543  for (pFacet = m_pA->facets_begin(); pFacet != m_pA->facets_end(); pFacet++)
544  {
545  //"primitives" is the list of the triangles intersected (as a list of triangles)
546  tree.all_intersected_primitives(Triangle(pFacet), std::back_inserter(primitives));
547  if(primitives.size() !=0)
548  {
549  m_Facet_Handle.push_back(pFacet);
550  //update of the tags (the facet and the three incidents halfedges
551  pFacet->Label = j++;
552  pFacet->facet_begin()->Label = i++;
553  pFacet->facet_begin()->next()->Label = i++;
554  pFacet->facet_begin()->next()->next()->Label = i++;
555  //creation of a Triangle_Cut structure to store the informations about the intersections
556  m_Inter_tri.push_back(Triangle_Cut(Compute_Normal_direction(pFacet->facet_begin()), true));
557  do {
558  //same operations for the intersected primitives (only one time)
559  if(primitives.back()->facet()->Label == 0xFFFFFFFF)
560  {
561  m_Facet_Handle.push_back(primitives.back()->facet());
562  primitives.back()->facet()->Label = j++;
563  primitives.back()->facet()->facet_begin()->Label = i++;
564  primitives.back()->facet()->facet_begin()->next()->Label = i++;
565  primitives.back()->facet()->facet_begin()->next()->next()->Label = i++;
566  m_Inter_tri.push_back(Triangle_Cut(Compute_Normal_direction(primitives.back()->facet()->facet_begin()), false));
567  }
568  //store every couple of intersected facet
569  m_Couples[pFacet->Label].insert(primitives.back()->facet()->Label);
570  primitives.pop_back();
571  }
572  while(primitives.size() != 0);
573  }
574  }
575  }
576 
577 #ifdef BOOLEAN_OPERATIONS_DEBUG_VERBOSE
578  {
579  std::cout << "end of FindCouples(), mesh A, face Label property:" << std::endl;
580  for(pFacet = m_pA->facets_begin(); pFacet != m_pA->facets_end(); pFacet++)
581  std::cout << pFacet->Label << std::endl;
582  std::cout << "end of FindCouples(), mesh B, face Label property:" << std::endl;
583  for(pFacet = m_pB->facets_begin(); pFacet != m_pB->facets_end(); pFacet++)
584  std::cout << pFacet->Label << std::endl;
585  std::cout << "end of FindCouples(), mesh A, halfedge Label property:" << std::endl;
586  EnrichedPolyhedron::Halfedge_iterator pHe;
587  for(pHe = m_pA->halfedges_begin(); pHe != m_pA->halfedges_end(); pHe++)
588  std::cout << pHe->Label << std::endl;
589  std::cout << "end of FindCouples(), mesh B, halfedge Label property:" << std::endl;
590  for(pHe = m_pB->halfedges_begin(); pHe != m_pB->halfedges_end(); pHe++)
591  std::cout << pHe->Label << std::endl;
592  }
593 #endif //BOOLEAN_OPERATIONS_DEBUG_VERBOSE
594  }
595 
596 
599  {
600  while(!m_Couples.empty())
601  {
602  FacetId fA, fB;
603  fA = m_Couples.begin()->first;
604  fB = *m_Couples[fA].begin();
605  InterTriangleTriangle(fA, fB);
606  rmCouple(fA, fB);
607  }
608  }
609 
610 
613  {
614  Triangle_Cut TriCut;
615  Halfedge_handle he;
616 
617  //every intersected facet is triangulated if at least one of the intersections is a segment
618  for(FacetId Facet = 0 ; Facet != m_Inter_tri.size() ; ++Facet)
619  {
620  if(!m_Inter_tri[Facet].CutList.empty())
621  {
622  TriCut = m_Inter_tri[Facet];
623  he = m_Facet_Handle[Facet]->facet_begin();
624  bool IsExt[3];
625  //creation of a triangulation
627  //add the list of intersection points (only happens in case of intersection of two edges)
628  for(std::set<InterId>::iterator i = TriCut.PtList.begin();i != TriCut.PtList.end();++i)
629  {
630  T.add_new_pt(m_InterPts[*i], (unsigned long &)*i); // MT: ajout cast
631  }
632  //add the intersection segments
633  for(int i = 0;i!=(int)TriCut.CutList.size();++i)
634  {
635  T.add_segment(m_InterPts[TriCut.CutList[i][0]], m_InterPts[TriCut.CutList[i][1]], TriCut.CutList[i][0], TriCut.CutList[i][1]);
636  }
637  //get the triangles of the triangulation thay belong to the result
638  //and determine if the three neighboring facets belongs to the result (using IsExt[3])
639  std::vector<std::vector<unsigned long> > Tri_set = T.get_triangles((m_BOOP == MINUS && !TriCut.Facet_from_A)?true:false, IsExt);
640  //add these triangles to the result
641  ppbuilder.add_triangle(Tri_set, he);
642 
643  //update the tags
644  m_Facet_Handle[Facet]->IsOK = true;
645  if(IsExt[0]) he->opposite()->facet()->IsExt = true;
646  if(IsExt[1]) he->next()->opposite()->facet()->IsExt = true;
647  if(IsExt[2]) he->next()->next()->opposite()->facet()->IsExt = true;
648  }
649  }
650  }
651 
652 
655  {
656  Facet_handle pFacet = NULL, f = NULL, nf = NULL;
657  std::stack<Facet_handle> tmpTriangles;
658 
659  //add to a stack the intersected facets that have been cut during CutIntersectedFacets
660  for (pFacet = m_pA->facets_begin(); pFacet != m_pA->facets_end(); pFacet++)
661  {
662  if(pFacet->IsOK) tmpTriangles.push(pFacet);
663  }
664 
665  //while the stack is not empty, we look the three neighboring facets
666  //if these facets has not been validated (IsOK == false), the facet is validated and added to the stack
667  //if this facet is taged as a part of the result (IsExt == true), the facet is added to the result
668  while(!tmpTriangles.empty())
669  {
670  f = tmpTriangles.top();
671  tmpTriangles.pop();
672  nf = f->facet_begin()->opposite()->facet();
673  if(!nf->IsOK)
674  {
675  nf->IsOK = true;
676  tmpTriangles.push(nf);
677  if(nf->IsExt) add_facet_to_solution(nf, true);
678  }
679  nf = f->facet_begin()->next()->opposite()->facet();
680  if(!nf->IsOK)
681  {
682  nf->IsOK = true;
683  tmpTriangles.push(nf);
684  if(nf->IsExt) add_facet_to_solution(nf, true);
685  }
686  nf = f->facet_begin()->next()->next()->opposite()->facet();
687  if(!nf->IsOK)
688  {
689  nf->IsOK = true;
690  tmpTriangles.push(nf);
691  if(nf->IsExt) add_facet_to_solution(nf, true);
692  }
693  }
694 
695  //same process for the second polyhedron
696  for (pFacet = m_pB->facets_begin(); pFacet != m_pB->facets_end(); pFacet++)
697  {
698  if(pFacet->IsOK) tmpTriangles.push(pFacet);
699  }
700 
701  while(!tmpTriangles.empty())
702  {
703  f = tmpTriangles.top();
704  tmpTriangles.pop();
705  nf = f->facet_begin()->opposite()->facet();
706  if(!nf->IsOK)
707  {
708  nf->IsOK = true;
709  tmpTriangles.push(nf);
710  if(nf->IsExt) add_facet_to_solution(nf, false);
711  }
712  nf = f->facet_begin()->next()->opposite()->facet();
713  if(!nf->IsOK)
714  {
715  nf->IsOK = true;
716  tmpTriangles.push(nf);
717  if(nf->IsExt) add_facet_to_solution(nf, false);
718  }
719  nf = f->facet_begin()->next()->next()->opposite()->facet();
720  if(!nf->IsOK)
721  {
722  nf->IsOK = true;
723  tmpTriangles.push(nf);
724  if(nf->IsExt) add_facet_to_solution(nf, false);
725  }
726  }
727  }
728 
729 
734  void rmCouple(FacetId &A, FacetId &B)
735  {
736  if(m_Couples[A].count(B) != 0) m_Couples[A].erase(B);
737  if(m_Couples[A].empty()) m_Couples.erase(A);
738  }
739 
740 
745  {
746  Vector_exact nA, nB;
747  nA = m_Inter_tri[A].norm_dir;
748  nB = m_Inter_tri[B].norm_dir;
749 
750  Facet_handle fA, fB, fA2, fB2;
751  fA = m_Facet_Handle[A];
752  fB = m_Facet_Handle[B];
753 
754  Halfedge_handle heA[3], heB[3];
755  heA[0] = fA->facet_begin();
756  heA[1] = heA[0]->next();
757  heA[2] = heA[1]->next();
758  heB[0] = fB->facet_begin();
759  heB[1] = heB[0]->next();
760  heB[2] = heB[1]->next();
761 
762  Point3d_exact ptA[3], ptB[3];
763  ptA[0] = point_to_exact(heA[0]->vertex()->point());
764  ptA[1] = point_to_exact(heA[1]->vertex()->point());
765  ptA[2] = point_to_exact(heA[2]->vertex()->point());
766  ptB[0] = point_to_exact(heB[0]->vertex()->point());
767  ptB[1] = point_to_exact(heB[1]->vertex()->point());
768  ptB[2] = point_to_exact(heB[2]->vertex()->point());
769 
770  //compute the position of the three vertices of each triangle regarding the plane of the other
771  //positive if the vertex is above
772  //negative if the vertex is under
773  //zero if the vertex is exactly on the triangle
774  num_type posA[3], posB[3];
775  posA[0] = nB * (ptA[0] - ptB[0]);
776  posA[1] = nB * (ptA[1] - ptB[0]);
777  posA[2] = nB * (ptA[2] - ptB[0]);
778  posB[0] = nA * (ptB[0] - ptA[0]);
779  posB[1] = nA * (ptB[1] - ptA[0]);
780  posB[2] = nA * (ptB[2] - ptA[0]);
781 
782  //a code is computed on 6 bits using these results (two bits for each point)
783  //10 -> above ; 01 -> under ; 00 -> on the plane
784  unsigned short posAbin, posBbin;
785  posAbin = ( (posA[0] > 0)? 32 : 0 )
786  + ( (posA[0] < 0)? 16 : 0 )
787  + ( (posA[1] > 0)? 8 : 0 )
788  + ( (posA[1] < 0)? 4 : 0 )
789  + ( (posA[2] > 0)? 2 : 0 )
790  + ( (posA[2] < 0)? 1 : 0 );
791 
792  posBbin = ( (posB[0] > 0)? 32 : 0 )
793  + ( (posB[0] < 0)? 16 : 0 )
794  + ( (posB[1] > 0)? 8 : 0 )
795  + ( (posB[1] < 0)? 4 : 0 )
796  + ( (posB[2] > 0)? 2 : 0 )
797  + ( (posB[2] < 0)? 1 : 0 );
798 
799  //if the intersection is not a segment, the intersection is not computed
800  //the triangles intersects on a point (one vertex on the plane and the two others under or above
801  if(posAbin == 5 || posAbin == 10 || posAbin == 17 || posAbin == 34 || posAbin == 20 || posAbin == 40
802  || posBbin == 5 || posBbin == 10 || posBbin == 17 || posBbin == 34 || posBbin == 20 || posBbin == 40) return;
803  //no possible intersection (one of the triangle is completely under or above the other
804  if(posAbin == 42 || posAbin == 21
805  || posBbin == 42 || posBbin == 21) return;
806  //the triangles are coplanar
807  if(posAbin == 0) return;
808 
809  //if an edge of a triangle is on the plane of the other triangle, it is necessary to verify if the
810  //two polyhedra are intersecting on these edges, or if it only is a contact to know if the intersection
811  //between the triangles must be computed or not.
812  //"edgeA" and "edgeB" are codes
813  //0 : the first edge is on the plane
814  //1 : the second edge is on the plane
815  //2 : the third edge is on the plane
816  //3 : there is no edge on the plane
817  unsigned short edgeA = 3, edgeB = 3;
818  if( posAbin == 1 || posAbin == 2 ) edgeA = 1; //points 0 and 1 on the plane
819  else if(posAbin == 16 || posAbin == 32) edgeA = 2; //points 1 and 2 on the plane
820  else if(posAbin == 4 || posAbin == 8 ) edgeA = 0; //points 2 and 0 on the plane
821  if( posBbin == 1 || posBbin == 2 ) edgeB = 1; //points 0 and 1 on the plane
822  else if(posBbin == 16 || posBbin == 32) edgeB = 2; //points 1 and 2 on the plane
823  else if(posBbin == 4 || posBbin == 8 ) edgeB = 0; //points 2 and 0 on the plane
824 
825  Vector_exact nA2, nB2;
826  num_type p;
827  bool invert_direction = false;
828  bool stop = false;
829 
830  //if an edge of the first triangle is on the plane
831  if(edgeA != 3 && edgeB == 3)
832  {
833  fA2 = heA[edgeA]->opposite()->facet();
834  nA2 = m_Inter_tri[fA2->Label].norm_dir;
835  p = CGAL::cross_product(nA, nB) * CGAL::cross_product(nA2, nB);
836  //if p is negative, the two triangles of the first polyhedron (including edgeA) are on the same side
837  //so there is no intersection
838  if(p < 0) stop = true;
839  //if p == 0, fA2 is coplanar with the plane of fB
840  //in that case, it is necessary to consider the boolean
841  //operator used to determine if there is a contact or not
842  else if(p == 0)
843  {
844  switch(m_BOOP)
845  {
846  case UNION:
847  if(posA[(edgeA+1)%3] * (nA2 * nB) > 0) stop = true;
848  break;
849  case INTER:
850  if(posA[(edgeA+1)%3] > 0) stop = true;
851  break;
852  case MINUS:
853  if(posA[(edgeA+1)%3] * (nA2 * nB) < 0) stop = true;
854  break;
855  }
856  }
857  //the intersection between fA2 and fB is the same so this couple is removed from the list
858  rmCouple(fA2->Label, fB->Label);
859  }
860  //if an edge of the second triangle is on the plane
861  else if(edgeA == 3 && edgeB != 3)
862  {
863  fB2 = heB[edgeB]->opposite()->facet();
864  nB2 = m_Inter_tri[fB2->Label].norm_dir;
865  p = CGAL::cross_product(nA, nB) * CGAL::cross_product(nA, nB2);
866  //if p is negative, the two triangles of the second polyhedron (including edgeB) are on the same side
867  //so there is no intersection
868  if(p < 0) stop = true;
869  //if p == 0, fB2 is coplanar with the plane of fA
870  //in that case, it is necessary to consider the boolean
871  //operator used to determine if there is a contact or not
872  else if(p == 0)
873  {
874  switch(m_BOOP)
875  {
876  case UNION:
877  if(posB[(edgeB+1)%3] < 0) stop = true;
878  break;
879  case INTER:
880  if(posB[(edgeB+1)%3] * (nB2 * nA) < 0) stop = true;
881  break;
882  case MINUS:
883  if(posB[(edgeB+1)%3] > 0) stop = true;
884  break;
885  }
886  }
887  //the intersection between fA and fB2 is the same so this couple is removed from the list
888  rmCouple(fA->Label, fB2->Label);
889  }
890  //if an edge of each triangle is on the plane of the other
891  else if(edgeA != 3 && edgeB != 3)
892  {
893  //in this case, four triangles are concerned by the intersection
894  //fA2 and fB2 are the two other concerned facets
895  //we try to determine if fA and fA2 are inside or outside the second polyhedron, using fB and fB2
896  bool Intersection = false;
897  Vector_exact nAcnB2, nA2cnB;
898  num_type nAnB2, nA2nB, nA2nB2;
899  num_type posA2_A, posB_A, posB2_A, posB_B2, posA_B, posB2_B, posB_A2, posB2_A2, posA2_B, posA2_B2;
900  Point3d_exact ptA2, ptB2;
901 
902  fA2 = heA[edgeA]->opposite()->facet();
903  fB2 = heB[edgeB]->opposite()->facet();
904  nA2 = m_Inter_tri[fA2->Label].norm_dir;
905  nB2 = m_Inter_tri[fB2->Label].norm_dir;
906 
907  nAcnB2 = CGAL::cross_product(nA, nB2);
908  nA2cnB = CGAL::cross_product(nA2, nB);
909 
910  nAnB2 = nA * nB2;
911  nA2nB = nA2 * nB;
912  nA2nB2 = nA2 * nB2;
913 
914  ptA2 = point_to_exact(heA[edgeA]->opposite()->next()->vertex()->point());
915  ptB2 = point_to_exact(heB[edgeB]->opposite()->next()->vertex()->point());
916 
917  posA_B = posA[(edgeA+1)%3];
918  posB_A = posB[(edgeB+1)%3];
919  posB_A2 = nA2 * (ptB[(edgeB+1)%3] - ptA[edgeA]);
920  posB_B2 = nB2 * (ptB[(edgeB+1)%3] - ptA[edgeA]);
921  posA2_A = nA * (ptA2 - ptA[edgeA]);
922  posA2_B = nB * (ptA2 - ptA[edgeA]);
923  posA2_B2 = nB2 * (ptA2 - ptA[edgeA]);
924  posB2_A = nA * (ptB2 - ptA[edgeA]);
925  posB2_A2 = nA2 * (ptB2 - ptA[edgeA]);
926  posB2_B = nB * (ptB2 - ptA[edgeA]);
927 
928  if(nAcnB2 == CGAL::NULL_VECTOR && nA2cnB == CGAL::NULL_VECTOR
929  && nAnB2 * nA2nB > 0) stop = true;
930 
931  //firstly, we search the position of fA
932  //if fA is inside the poyhedron, Intersection = true
933  if(posB_A * posB2_A > 0) //fB and fB2 on the same side
934  {
935  if(posB_B2 > 0) Intersection = true;
936  }
937  else if(posB_A * posB2_A < 0) //fB and fB2 on opposite side
938  {
939  if(posA_B < 0) Intersection = true;
940  }
941  else //fA and fB2 coplanar
942  {
943  if(posA_B * posB2_B < 0)
944  {
945  if(posB_B2 > 0) Intersection = true;
946  }
947  else
948  {
949  if(nAnB2 < 0)
950  {
951  if(m_BOOP == UNION) Intersection = true;
952  }
953  else
954  {
955  if(m_BOOP == MINUS) Intersection = true;
956  }
957  }
958  }
959 
960  //secondly, we search the position of fA2
961  //if fA2 is inside the poyhedron, "Intersection" is inverted
962  if(posB_A2 * posB2_A2 > 0) //fB and fB2 on the same side
963  {
964  if(posB_B2 > 0) Intersection = !Intersection;
965  }
966  else if(posB_A2 * posB2_A2 < 0) //fB and fB2 on opposite side
967  {
968  if(posA2_B < 0) Intersection = !Intersection;
969  }
970  else if(posB2_A2 == 0) //fA2 and fB2 coplanar
971  {
972  if(posA2_B * posB2_B < 0)
973  {
974  if(posB_B2 > 0) Intersection = !Intersection;
975  }
976  else
977  {
978  if(nA2nB2 < 0)
979  {
980  if(m_BOOP == UNION) Intersection = !Intersection;
981  }
982  else
983  {
984  if(m_BOOP == MINUS) Intersection = !Intersection;
985  }
986  }
987  }
988  else //fA2 and fB coplanar
989  {
990  if(posA2_B2 * posB_B2 < 0)
991  {
992  if(posB_B2 > 0) Intersection = !Intersection;
993  }
994  else
995  {
996  if(nA2nB < 0)
997  {
998  if(m_BOOP == UNION) Intersection = !Intersection;
999  }
1000  else
1001  {
1002  if(m_BOOP == MINUS) Intersection = !Intersection;
1003  }
1004  }
1005  }
1006 
1007  //if Intersection == false, fA and fA2 are both inside or outside the second polyhedron.
1008  if(!Intersection) stop = true;
1009 
1010  //the intersection between (fA, fB2), (fA2, fB) and (fA2, fB2) are the same so these couples are removed from the list
1011  rmCouple(fA->Label, fB2->Label);
1012  rmCouple(fA2->Label, fB->Label);
1013  rmCouple(fA2->Label, fB2->Label);
1014 
1015  //it is possible that the direction of the intersection have to be inverted
1016  if(posB_A * posA2_A > 0 && posB_A * posB2_A >= 0 && posB2_B * posA_B > 0) invert_direction = true;
1017  }
1018 
1019  //if the intersection must not be compute
1020  if(stop) return;
1021 
1022  Info_Inter inter[4];
1023  inter[0].f = fA;
1024  inter[1].f = fA;
1025  inter[2].f = fB;
1026  inter[3].f = fB;
1027 
1028  //the two intersection points between the edges of a triangle and the
1029  //other triangle are computed for the two triangles
1030  switch(posBbin)
1031  {
1032  //common intersections : one point one one side of the plane and the two other points on the other side
1033  case 26:
1034  case 37:
1035  inter[0].he = heB[0];
1036  InterTriangleSegment(&inter[0]);
1037  inter[1].he = heB[1];
1038  InterTriangleSegment(&inter[1]);
1039  break;
1040  case 25:
1041  case 38:
1042  inter[0].he = heB[1];
1043  InterTriangleSegment(&inter[0]);
1044  inter[1].he = heB[2];
1045  InterTriangleSegment(&inter[1]);
1046  break;
1047  case 22:
1048  case 41:
1049  inter[0].he = heB[2];
1050  InterTriangleSegment(&inter[0]);
1051  inter[1].he = heB[0];
1052  InterTriangleSegment(&inter[1]);
1053  break;
1054  //particular cases : one point on the plane, one point one one side and one point on the other side
1055  case 6:
1056  case 9:
1057  inter[0].he = heB[2];
1058  InterTriangleSegment(&inter[0]);
1059  inter[1].he = heB[0];
1060  IsInTriangle(&inter[1]);
1061  break;
1062  case 18:
1063  case 33:
1064  inter[0].he = heB[0];
1065  InterTriangleSegment(&inter[0]);
1066  inter[1].he = heB[1];
1067  IsInTriangle(&inter[1]);
1068  break;
1069  case 24:
1070  case 36:
1071  inter[0].he = heB[1];
1072  InterTriangleSegment(&inter[0]);
1073  inter[1].he = heB[2];
1074  IsInTriangle(&inter[1]);
1075  break;
1076  //particular case : two points on the plane
1077  case 1:
1078  case 2:
1079  inter[0].he = heB[0];
1080  IsInTriangle(&inter[0]);
1081  inter[1].he = heB[2]->opposite();
1082  IsInTriangle(&inter[1]);
1083  break;
1084  case 16:
1085  case 32:
1086  inter[0].he = heB[1];
1087  IsInTriangle(&inter[0]);
1088  inter[1].he = heB[0]->opposite();
1089  IsInTriangle(&inter[1]);
1090  break;
1091  case 4:
1092  case 8:
1093  inter[0].he = heB[2];
1094  IsInTriangle(&inter[0]);
1095  inter[1].he = heB[1]->opposite();
1096  IsInTriangle(&inter[1]);
1097  break;
1098  default:
1099  return;
1100  }
1101 
1102  switch(posAbin)
1103  {
1104  //common intersections : one point one one side of the plane and the two other points on the other side
1105  case 26:
1106  case 37:
1107  inter[2].he = heA[0];
1108  InterTriangleSegment(&inter[2]);
1109  inter[3].he = heA[1];
1110  InterTriangleSegment(&inter[3]);
1111  break;
1112  case 25:
1113  case 38:
1114  inter[2].he = heA[1];
1115  InterTriangleSegment(&inter[2]);
1116  inter[3].he = heA[2];
1117  InterTriangleSegment(&inter[3]);
1118  break;
1119  case 22:
1120  case 41:
1121  inter[2].he = heA[2];
1122  InterTriangleSegment(&inter[2]);
1123  inter[3].he = heA[0];
1124  InterTriangleSegment(&inter[3]);
1125  break;
1126  //particular cases : one point on the plane, one point one one side and one point on the other side
1127  case 6:
1128  case 9:
1129  inter[2].he = heA[2];
1130  InterTriangleSegment(&inter[2]);
1131  inter[3].he = heA[0];
1132  IsInTriangle(&inter[3]);
1133  break;
1134  case 18:
1135  case 33:
1136  inter[2].he = heA[0];
1137  InterTriangleSegment(&inter[2]);
1138  inter[3].he = heA[1];
1139  IsInTriangle(&inter[3]);
1140  break;
1141  case 24:
1142  case 36:
1143  inter[2].he = heA[1];
1144  InterTriangleSegment(&inter[2]);
1145  inter[3].he = heA[2];
1146  IsInTriangle(&inter[3]);
1147  break;
1148  //particular case : two points on the plane
1149  case 1:
1150  case 2:
1151  inter[2].he = heA[0];
1152  IsInTriangle(&inter[2]);
1153  inter[3].he = heA[2]->opposite();
1154  IsInTriangle(&inter[3]);
1155  break;
1156  case 16:
1157  case 32:
1158  inter[2].he = heA[1];
1159  IsInTriangle(&inter[2]);
1160  inter[3].he = heA[0]->opposite();
1161  IsInTriangle(&inter[3]);
1162  break;
1163  case 4:
1164  case 8:
1165  inter[2].he = heA[2];
1166  IsInTriangle(&inter[2]);
1167  inter[3].he = heA[1]->opposite();
1168  IsInTriangle(&inter[3]);
1169  break;
1170  default:
1171  return;
1172  }
1173 
1174  //if two distincts points belongs to the two triangles
1175  if(IsSegment(inter))
1176  {
1177  //we get this segment in ptInter
1178  std::vector<InterId> ptInter;
1179  Get_Segment(inter, ptInter);
1180  //and we build the opposite segment in ptInterInv
1181  std::vector<InterId> ptInterInv;
1182  ptInterInv.push_back(ptInter[1]);
1183  ptInterInv.push_back(ptInter[0]);
1184 
1185  //the segments are stored in the concerned triangles, and oriented
1186  if(CGAL::cross_product(nA, nB) * (m_InterPts[ptInter[1]] - m_InterPts[ptInter[0]]) * ((invert_direction == true)?-1:1) > 0)
1187  {
1188  switch(m_BOOP)
1189  {
1190  case UNION:
1191  m_Inter_tri[fA->Label].CutList.push_back(ptInter);
1192  if(edgeA != 3) m_Inter_tri[fA2->Label].CutList.push_back(ptInter);
1193  m_Inter_tri[fB->Label].CutList.push_back(ptInterInv);
1194  if(edgeB != 3) m_Inter_tri[fB2->Label].CutList.push_back(ptInterInv);
1195  break;
1196  case INTER:
1197  m_Inter_tri[fA->Label].CutList.push_back(ptInterInv);
1198  if(edgeA != 3) m_Inter_tri[fA2->Label].CutList.push_back(ptInterInv);
1199  m_Inter_tri[fB->Label].CutList.push_back(ptInter);
1200  if(edgeB != 3) m_Inter_tri[fB2->Label].CutList.push_back(ptInter);
1201  break;
1202  case MINUS:
1203  m_Inter_tri[fA->Label].CutList.push_back(ptInter);
1204  if(edgeA != 3) m_Inter_tri[fA2->Label].CutList.push_back(ptInter);
1205  m_Inter_tri[fB->Label].CutList.push_back(ptInter);
1206  if(edgeB != 3) m_Inter_tri[fB2->Label].CutList.push_back(ptInter);
1207  break;
1208  }
1209  }
1210  else
1211  {
1212  switch(m_BOOP)
1213  {
1214  case UNION:
1215  m_Inter_tri[fA->Label].CutList.push_back(ptInterInv);
1216  if(edgeA != 3) m_Inter_tri[fA2->Label].CutList.push_back(ptInterInv);
1217  m_Inter_tri[fB->Label].CutList.push_back(ptInter);
1218  if(edgeB != 3) m_Inter_tri[fB2->Label].CutList.push_back(ptInter);
1219  break;
1220  case INTER:
1221  m_Inter_tri[fA->Label].CutList.push_back(ptInter);
1222  if(edgeA != 3) m_Inter_tri[fA2->Label].CutList.push_back(ptInter);
1223  m_Inter_tri[fB->Label].CutList.push_back(ptInterInv);
1224  if(edgeB != 3) m_Inter_tri[fB2->Label].CutList.push_back(ptInterInv);
1225  break;
1226  case MINUS:
1227  m_Inter_tri[fA->Label].CutList.push_back(ptInterInv);
1228  if(edgeA != 3) m_Inter_tri[fA2->Label].CutList.push_back(ptInterInv);
1229  m_Inter_tri[fB->Label].CutList.push_back(ptInterInv);
1230  if(edgeB != 3) m_Inter_tri[fB2->Label].CutList.push_back(ptInterInv);
1231  break;
1232  }
1233  }
1234  }
1235  }
1236 
1237 
1241  {
1242  Facet_handle f = inter->f;
1243  Halfedge_handle he = inter->he;
1244  //if the intersection has been computed, the function returns directly the Id of the intersection
1245  if(m_Inter_tri[f->Label].RefInter.count(he->Label) != 0)
1246  {
1247  inter->Id = m_Inter_tri[f->Label].RefInter[he->Label];
1248  return;
1249  }
1250  //else, the calculation is done
1251 
1252  //this method is called when the intersection is not on the vertex pointed by the halfedge
1253  inter->IsOnVertex = false;
1254  //the intersection does not have an Id. 0xFFFFFFFF is set (this value means "no Id")
1255  inter->Id = 0xFFFFFFFF;
1256 
1257  Vector_exact e1, e2, dir, p, s, q;
1258  num_type u, v, tmp;
1259 
1260  Point3d_exact s1 = point_to_exact(he->opposite()->vertex()->point());
1261  Point3d_exact s2 = point_to_exact(he->vertex()->point());
1262  Point3d_exact v0 = point_to_exact(f->facet_begin()->vertex()->point());
1263  Point3d_exact v1 = point_to_exact(f->facet_begin()->next()->vertex()->point());
1264  Point3d_exact v2 = point_to_exact(f->facet_begin()->next()->next()->vertex()->point());
1265 
1266  //computation of the intersection (exact numbers)
1267  e1 = v1 - v0;
1268  e2 = v2 - v0;
1269  dir = s2 - s1;
1270  p = CGAL::cross_product(dir, e2);
1271  tmp = (num_type)1/(p*e1);
1272  s = s1 - v0;
1273  u = tmp * s * p;
1274  if(u < 0 || u > 1)
1275  {
1276  //the intersection is not in the triangle
1277  inter->res = 7;
1278  return;
1279  }
1280  q = CGAL::cross_product(s, e1);
1281  v = tmp * dir * q;
1282  if(v < 0 || v > 1)
1283  {
1284  //the intersection is not in the triangle
1285  inter->res = 7;
1286  return;
1287  }
1288  if(u + v > 1)
1289  {
1290  //the intersection is not in the triangle
1291  inter->res = 7;
1292  return;
1293  }
1294 
1295  //the result is stored in inter->pt
1296  inter->pt = s1+(tmp*e2*q)*dir;
1297 
1298  //creation of the code for the location of the intersection
1299  inter->res = 0;
1300  if(u == 0) inter->res += 1; //intersection on he(0)
1301  if(v == 0) inter->res += 2; //intersection on he(1)
1302  if(u+v == 1) inter->res += 4; //intersection on he(2)
1303  }
1304 
1305 
1309  {
1310  Facet_handle f = inter->f;
1311  Halfedge_handle he = inter->he;
1312  //if the intersection has been computed, the function returns directly the Id of the intersection
1313  if(m_Inter_tri[f->Label].RefInter.count(he->Label) != 0)
1314  {
1315  inter->Id = m_Inter_tri[f->Label].RefInter[he->Label];
1316  return;
1317  }
1318  //else, the calculation is done
1319 
1320  //this method is called when the intersection is exactly on the vertex pointed by the halfedge
1321  inter->IsOnVertex = true;
1322  //the intersection does not have an Id. 0xFFFFFFFF is set (this value means "no Id")
1323  inter->Id = 0xFFFFFFFF;
1324 
1325  Point3d_exact p = point_to_exact(he->vertex()->point());
1326  Point3d_exact v0 = point_to_exact(f->facet_begin()->vertex()->point());
1327  Point3d_exact v1 = point_to_exact(f->facet_begin()->next()->vertex()->point());
1328  Point3d_exact v2 = point_to_exact(f->facet_begin()->next()->next()->vertex()->point());
1329 
1330  Vector_exact N = m_Inter_tri[f->Label].norm_dir;
1331  num_type u, v, w;
1332 
1333  u = N * CGAL::cross_product(v0 - v2, p - v2);
1334  if(u < 0)
1335  {
1336  //the intersection is not in the triangle
1337  inter->res = 7;
1338  return;
1339  }
1340  v = N * CGAL::cross_product(v1 - v0, p - v0);
1341  if(v < 0)
1342  {
1343  //the intersection is not in the triangle
1344  inter->res = 7;
1345  return;
1346  }
1347  w = N * CGAL::cross_product(v2 - v1, p - v1);
1348  if(w < 0)
1349  {
1350  //the intersection is not in the triangle
1351  inter->res = 7;
1352  return;
1353  }
1354 
1355  //the point is in the triangle
1356  inter->pt = p;
1357 
1358  //creation of the code for the location of the intersection
1359  inter->res = 0;
1360  if(u == 0) inter->res += 1; //intersection on he(0)
1361  if(v == 0) inter->res += 2; //intersection on he(1)
1362  if(w == 0) inter->res += 4; //intersection on he(2)
1363  }
1364 
1365 
1369  bool IsSegment(Info_Inter *inter)
1370  {
1371  bool point = false; //true if a point is founded
1372  Point3d_exact pt; //the point founded
1373  bool id = false; //true if an Id is founded
1374  unsigned long Id = 0; //the Id founded // MT
1375 
1376  //each intersection is checked separately.
1377  //first intersection
1378  if(inter[0].Id != 0xFFFFFFFF)
1379  {
1380  //an Id different than 0xFFFFFFFF is founded
1381  //this intersection has already been computed and is valid
1382  id = true;
1383  Id = inter[0].Id;
1384  }
1385  else if(inter[0].res != 7)
1386  {
1387  //the intersection have no Id (0xFFFFFFFF)
1388  //but the intersection is in the triangle
1389  point = true;
1390  pt = inter[0].pt;
1391  }
1392  //second intersection
1393  if(inter[1].Id != 0xFFFFFFFF)
1394  {
1395  //an Id different than 0xFFFFFFFF is founded
1396  //this intersection has already been computed and is valid
1397 
1398  //if a point or an Id has already be founded, we founded the two distinct valid points (the intersection is a segment)
1399  //(it is not possible that the two first points are the same)
1400  if(point || id) return true;
1401  id = true;
1402  Id = inter[1].Id;
1403  }
1404  else if(inter[1].res != 7)
1405  {
1406  //the intersection have no Id (0xFFFFFFFF)
1407  //but the intersection is in the triangle
1408 
1409  //if a point or an Id has already be founded, we founded the two distinct valid points (the intersection is a segment)
1410  //(it is not possible that the two first points are the same)
1411  if(point || id) return true;
1412  point = true;
1413  pt = inter[1].pt;
1414  }
1415  //third intersection
1416  if(inter[2].Id != 0xFFFFFFFF)
1417  {
1418  //an Id different than 0xFFFFFFFF is founded
1419  //this intersection has already been computed and is valid
1420 
1421  //if a point or a different Id has already be founded, we founded the two distinct valid points (the intersection is a segment)
1422  //(it is not possible that the two first points are the same)
1423  if(point || (id && Id != inter[2].Id)) return true;
1424  id = true;
1425  Id = inter[2].Id;
1426  }
1427  else if(inter[2].res != 7)
1428  {
1429  //the intersection have no Id (0xFFFFFFFF)
1430  //but the intersection is in the triangle
1431 
1432  //if an Id or a different point has already be founded, we founded the two distinct valid points (the intersection is a segment)
1433  //(it is not possible that the two first points are the same)
1434  if((point && pt != inter[2].pt) || id) return true;
1435  point = true;
1436  pt = inter[2].pt;
1437  }
1438  //fourth intersection
1439  if(inter[3].Id != 0xFFFFFFFF)
1440  {
1441  //an Id different than 0xFFFFFFFF is founded
1442  //this intersection has already been computed and is valid
1443 
1444  //if a point or a different Id has already be founded, we founded the two distinct valid points (the intersection is a segment)
1445  //(it is not possible that the two first points are the same)
1446  if(point || (id && Id != inter[3].Id)) return true;
1447  }
1448  else if(inter[3].res != 7)
1449  {
1450  //the intersection have no Id (0xFFFFFFFF)
1451  //but the intersection is in the triangle
1452 
1453  //if an Id or a different point has already be founded, we founded the two distinct valid points (the intersection is a segment)
1454  //(it is not possible that the two first points are the same)
1455  if((point && pt != inter[3].pt) || id) return true;
1456  }
1457  return false;
1458  }
1459 
1460 
1465  void Get_Segment(Info_Inter *inter, std::vector<InterId> &I)
1466  {
1467  for(unsigned int i = 0;i != 4;++i)
1468  {
1469  //if the point have an Id
1470  if(inter[i].Id != 0xFFFFFFFF)
1471  {
1472  //the Id is stored if it is not already done
1473  if(I.size() == 0 || I[0] != inter[i].Id) I.push_back(inter[i].Id);
1474  }
1475  //else if the point is valid
1476  else if(inter[i].res != 7)
1477  {
1478  //the intersection point is stored in the list of the intersection points
1479  //and its new Id is stored in the output segment
1480  if(I.size() == 0 || m_InterPts[I[0]] != inter[i].pt)
1481  {
1482  Store_Intersection(&inter[i]);
1483  I.push_back(inter[i].Id);
1484  }
1485  }
1486  //return if the two points are founded
1487  if(I.size() == 2) return;
1488  }
1489  }
1490 
1491 
1495  {
1496  Facet_handle f;
1497  Halfedge_handle he;
1498  f = inter->f;
1499  he = inter->he;
1500  InterId I;
1501 
1502  //store the point to the list of the intersections and store its new Id
1503  inter->Id = static_cast< InterId >(m_InterPts.size());
1504  I = inter->Id;
1505  m_InterPts.push_back(inter->pt);
1506 
1507  //add this point as a vertex of the result
1508  ppbuilder.add_vertex(point_to_double(inter->pt), inter->Id);
1509 
1510  //if the intersection is on the vertex pointed by the halfedge (he), we update the Id (Label) of this vertex
1511  if(inter->IsOnVertex) he->vertex()->Label = I;
1512 
1513  //the intersection is memorized for each possible couple of (facet, halfedge) concerned by the intersection
1514  //if the intersection is exactly on the vertex pointed by the halfedge (he), it is necessary to take account
1515  //of every halfedge pointing to this vertex
1516  switch(inter->res)
1517  {
1518  case 0: //intersection on the facet
1519  {
1520  if(!inter->IsOnVertex)
1521  {
1522  m_Inter_tri[f->Label].RefInter[he->Label] = I;
1523  m_Inter_tri[f->Label].RefInter[he->opposite()->Label] = I;
1524  }
1525  else
1526  {
1527  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(), H_end = he->vertex_begin();
1528  do {
1529  m_Inter_tri[f->Label].RefInter[H_circ->Label] = I;
1530  m_Inter_tri[f->Label].RefInter[H_circ->opposite()->Label] = I;
1531  H_circ++;
1532  } while(H_circ != H_end);
1533  }
1534  }
1535  break;
1536  case 1: //Intersection on the first halfedge of the facet
1537  {
1538  m_Inter_tri[f->Label].PtList.insert(I);
1539  m_Inter_tri[f->facet_begin()->opposite()->facet()->Label].PtList.insert(I);
1540  if(!inter->IsOnVertex)
1541  {
1542  m_Inter_tri[he->facet()->Label].PtList.insert(I);
1543  m_Inter_tri[he->opposite()->facet()->Label].PtList.insert(I);
1544  m_Inter_tri[f->Label].RefInter[he->Label] = I;
1545  m_Inter_tri[f->Label].RefInter[he->opposite()->Label] = I;
1546  m_Inter_tri[f->facet_begin()->opposite()->facet()->Label].RefInter[he->Label] = I;
1547  m_Inter_tri[f->facet_begin()->opposite()->facet()->Label].RefInter[he->opposite()->Label] = I;
1548  m_Inter_tri[he->facet()->Label].RefInter[f->facet_begin()->Label] = I;
1549  m_Inter_tri[he->facet()->Label].RefInter[f->facet_begin()->opposite()->Label] = I;
1550  m_Inter_tri[he->opposite()->facet()->Label].RefInter[f->facet_begin()->Label] = I;
1551  m_Inter_tri[he->opposite()->facet()->Label].RefInter[f->facet_begin()->opposite()->Label] = I;
1552  }
1553  else
1554  {
1555  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(), H_end = he->vertex_begin();
1556  do {
1557  m_Inter_tri[f->Label].RefInter[H_circ->Label] = I;
1558  m_Inter_tri[f->Label].RefInter[H_circ->opposite()->Label] = I;
1559  m_Inter_tri[f->facet_begin()->opposite()->facet()->Label].RefInter[H_circ->Label] = I;
1560  m_Inter_tri[f->facet_begin()->opposite()->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1561  m_Inter_tri[H_circ->facet()->Label].RefInter[f->facet_begin()->Label] = I;
1562  m_Inter_tri[H_circ->facet()->Label].RefInter[f->facet_begin()->opposite()->Label] = I;
1563  H_circ++;
1564  } while(H_circ != H_end);
1565  }
1566  }
1567  break;
1568  case 2: //Intersection on the second halfedge of the facet
1569  {
1570  m_Inter_tri[f->Label].PtList.insert(I);
1571  m_Inter_tri[f->facet_begin()->next()->opposite()->facet()->Label].PtList.insert(I);
1572  if(!inter->IsOnVertex)
1573  {
1574  m_Inter_tri[he->facet()->Label].PtList.insert(I);
1575  m_Inter_tri[he->opposite()->facet()->Label].PtList.insert(I);
1576  m_Inter_tri[f->Label].RefInter[he->Label] = I;
1577  m_Inter_tri[f->Label].RefInter[he->opposite()->Label] = I;
1578  m_Inter_tri[f->facet_begin()->next()->opposite()->facet()->Label].RefInter[he->Label] = I;
1579  m_Inter_tri[f->facet_begin()->next()->opposite()->facet()->Label].RefInter[he->opposite()->Label] = I;
1580  m_Inter_tri[he->facet()->Label].RefInter[f->facet_begin()->next()->Label] = I;
1581  m_Inter_tri[he->facet()->Label].RefInter[f->facet_begin()->next()->opposite()->Label] = I;
1582  m_Inter_tri[he->opposite()->facet()->Label].RefInter[f->facet_begin()->next()->Label] = I;
1583  m_Inter_tri[he->opposite()->facet()->Label].RefInter[f->facet_begin()->next()->opposite()->Label] = I;
1584  }
1585  else
1586  {
1587  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(), H_end = he->vertex_begin();
1588  do {
1589  m_Inter_tri[f->Label].RefInter[H_circ->Label] = I;
1590  m_Inter_tri[f->Label].RefInter[H_circ->opposite()->Label] = I;
1591  m_Inter_tri[f->facet_begin()->next()->opposite()->facet()->Label].RefInter[H_circ->Label] = I;
1592  m_Inter_tri[f->facet_begin()->next()->opposite()->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1593  m_Inter_tri[H_circ->facet()->Label].RefInter[f->facet_begin()->next()->Label] = I;
1594  m_Inter_tri[H_circ->facet()->Label].RefInter[f->facet_begin()->next()->opposite()->Label] = I;
1595  H_circ++;
1596  } while(H_circ != H_end);
1597  }
1598  }
1599  break;
1600  case 3: //Intersection on the first and second halfedge of the facet (vertex pointed by the first halfedge)
1601  {
1602  //update the Id (Label) of the first vertex of the facet
1603  f->facet_begin()->vertex()->Label = I;
1604  if(!inter->IsOnVertex)
1605  {
1606  m_Inter_tri[he->facet()->Label].PtList.insert(I);
1607  m_Inter_tri[he->opposite()->facet()->Label].PtList.insert(I);
1608 
1609  Halfedge_around_vertex_circulator H_circ = f->facet_begin()->vertex_begin(),
1610  H_end = f->facet_begin()->vertex_begin();
1611  do {
1612  m_Inter_tri[H_circ->facet()->Label].RefInter[he->Label] = I;
1613  m_Inter_tri[H_circ->facet()->Label].RefInter[he->opposite()->Label] = I;
1614  m_Inter_tri[he->facet()->Label].RefInter[H_circ->Label] = I;
1615  m_Inter_tri[he->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1616  m_Inter_tri[he->opposite()->facet()->Label].RefInter[H_circ->Label] = I;
1617  m_Inter_tri[he->opposite()->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1618  H_circ++;
1619  } while(H_circ != H_end);
1620  }
1621  else
1622  {
1623  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(),
1624  H_end = he->vertex_begin();
1625  do {
1626  Halfedge_around_vertex_circulator F_circ = f->facet_begin()->vertex_begin(),
1627  F_end = f->facet_begin()->vertex_begin();
1628  do {
1629  m_Inter_tri[F_circ->facet()->Label].RefInter[H_circ->Label] = I;
1630  m_Inter_tri[F_circ->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1631  m_Inter_tri[H_circ->facet()->Label].RefInter[F_circ->Label] = I;
1632  m_Inter_tri[H_circ->facet()->Label].RefInter[F_circ->opposite()->Label] = I;
1633  F_circ++;
1634  } while(F_circ != F_end);
1635  H_circ++;
1636  } while(H_circ != H_end);
1637  }
1638  }
1639  break;
1640  case 4: //Intersection on the third halfedge of the facet
1641  {
1642  m_Inter_tri[f->Label].PtList.insert(I);
1643  m_Inter_tri[f->facet_begin()->next()->next()->opposite()->facet()->Label].PtList.insert(I);
1644  if(!inter->IsOnVertex)
1645  {
1646  m_Inter_tri[he->facet()->Label].PtList.insert(I);
1647  m_Inter_tri[he->opposite()->facet()->Label].PtList.insert(I);
1648  m_Inter_tri[f->Label].RefInter[he->Label] = I;
1649  m_Inter_tri[f->Label].RefInter[he->opposite()->Label] = I;
1650  m_Inter_tri[f->facet_begin()->next()->next()->opposite()->facet()->Label].RefInter[he->Label] = I;
1651  m_Inter_tri[f->facet_begin()->next()->next()->opposite()->facet()->Label].RefInter[he->opposite()->Label] = I;
1652  m_Inter_tri[he->facet()->Label].RefInter[f->facet_begin()->next()->next()->Label] = I;
1653  m_Inter_tri[he->facet()->Label].RefInter[f->facet_begin()->next()->next()->opposite()->Label] = I;
1654  m_Inter_tri[he->opposite()->facet()->Label].RefInter[f->facet_begin()->next()->next()->Label] = I;
1655  m_Inter_tri[he->opposite()->facet()->Label].RefInter[f->facet_begin()->next()->next()->opposite()->Label] = I;
1656  }
1657  else
1658  {
1659  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(), H_end = he->vertex_begin();
1660  do {
1661  m_Inter_tri[f->Label].RefInter[H_circ->Label] = I;
1662  m_Inter_tri[f->Label].RefInter[H_circ->opposite()->Label] = I;
1663  m_Inter_tri[f->facet_begin()->next()->next()->opposite()->facet()->Label].RefInter[H_circ->Label] = I;
1664  m_Inter_tri[f->facet_begin()->next()->next()->opposite()->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1665  m_Inter_tri[H_circ->facet()->Label].RefInter[f->facet_begin()->next()->next()->Label] = I;
1666  m_Inter_tri[H_circ->facet()->Label].RefInter[f->facet_begin()->next()->next()->opposite()->Label] = I;
1667  H_circ++;
1668  } while(H_circ != H_end);
1669  }
1670  }
1671  break;
1672  case 5: //Intersection on the first and third halfedge of the facet (vertex pointed by the third halfedge)
1673  {
1674  //update the Id (Label) of the third vertex of the facet
1675  f->facet_begin()->next()->next()->vertex()->Label = I;
1676  if(!inter->IsOnVertex)
1677  {
1678  m_Inter_tri[he->facet()->Label].PtList.insert(I);
1679  m_Inter_tri[he->opposite()->facet()->Label].PtList.insert(I);
1680 
1681  Halfedge_around_vertex_circulator H_circ = f->facet_begin()->next()->next()->vertex_begin(),
1682  H_end = f->facet_begin()->next()->next()->vertex_begin();
1683  do {
1684  m_Inter_tri[H_circ->facet()->Label].RefInter[he->Label] = I;
1685  m_Inter_tri[H_circ->facet()->Label].RefInter[he->opposite()->Label] = I;
1686  m_Inter_tri[he->facet()->Label].RefInter[H_circ->Label] = I;
1687  m_Inter_tri[he->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1688  m_Inter_tri[he->opposite()->facet()->Label].RefInter[H_circ->Label] = I;
1689  m_Inter_tri[he->opposite()->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1690  H_circ++;
1691  } while(H_circ != H_end);
1692  }
1693  else
1694  {
1695  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(),
1696  H_end = he->vertex_begin();
1697  do {
1698  Halfedge_around_vertex_circulator F_circ = f->facet_begin()->next()->next()->vertex_begin(),
1699  F_end = f->facet_begin()->next()->next()->vertex_begin();
1700  do {
1701  m_Inter_tri[F_circ->facet()->Label].RefInter[H_circ->Label] = I;
1702  m_Inter_tri[F_circ->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1703  m_Inter_tri[H_circ->facet()->Label].RefInter[F_circ->Label] = I;
1704  m_Inter_tri[H_circ->facet()->Label].RefInter[F_circ->opposite()->Label] = I;
1705  F_circ++;
1706  } while(F_circ != F_end);
1707  H_circ++;
1708  } while(H_circ != H_end);
1709  }
1710  }
1711  break;
1712  case 6: //Intersection on the second and third halfedge of the facet (vertex pointed by the second halfedge)
1713  {
1714  //update the Id (Label) of the second vertex of the facet
1715  f->facet_begin()->next()->vertex()->Label = I;
1716  if(!inter->IsOnVertex)
1717  {
1718  m_Inter_tri[he->facet()->Label].PtList.insert(I);
1719  m_Inter_tri[he->opposite()->facet()->Label].PtList.insert(I);
1720 
1721  Halfedge_around_vertex_circulator H_circ = f->facet_begin()->next()->vertex_begin(),
1722  H_end = f->facet_begin()->next()->vertex_begin();
1723  do {
1724  m_Inter_tri[H_circ->facet()->Label].RefInter[he->Label] = I;
1725  m_Inter_tri[H_circ->facet()->Label].RefInter[he->opposite()->Label] = I;
1726  m_Inter_tri[he->facet()->Label].RefInter[H_circ->Label] = I;
1727  m_Inter_tri[he->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1728  m_Inter_tri[he->opposite()->facet()->Label].RefInter[H_circ->Label] = I;
1729  m_Inter_tri[he->opposite()->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1730  H_circ++;
1731  } while(H_circ != H_end);
1732  }
1733  else
1734  {
1735  Halfedge_around_vertex_circulator H_circ = he->vertex_begin(),
1736  H_end = he->vertex_begin();
1737  do {
1738  Halfedge_around_vertex_circulator F_circ = f->facet_begin()->next()->vertex_begin(),
1739  F_end = f->facet_begin()->next()->vertex_begin();
1740  do {
1741  m_Inter_tri[F_circ->facet()->Label].RefInter[H_circ->Label] = I;
1742  m_Inter_tri[F_circ->facet()->Label].RefInter[H_circ->opposite()->Label] = I;
1743  m_Inter_tri[H_circ->facet()->Label].RefInter[F_circ->Label] = I;
1744  m_Inter_tri[H_circ->facet()->Label].RefInter[F_circ->opposite()->Label] = I;
1745  F_circ++;
1746  } while(F_circ != F_end);
1747  H_circ++;
1748  } while(H_circ != H_end);
1749  }
1750  }
1751  break;
1752  }
1753 
1754  }
1755 
1756 
1760  void add_facet_to_solution(Facet_handle &pFacet, bool facet_from_A)
1761  {
1762  //if the facet contains an intersection point but no intersection segment, the facet must be triangulate before
1763  if(pFacet->Label < m_Inter_tri.size())
1764  {
1765  Triangle_Cut TriCut = m_Inter_tri[pFacet->Label];
1766  Halfedge_handle he = pFacet->facet_begin();
1767  //creation of the triangulation
1768  Triangulation<Exact_Kernel> T(he, TriCut.norm_dir);
1769  //add the intersection points to the triangulation
1770  for(std::set<InterId>::iterator i = TriCut.PtList.begin();i != TriCut.PtList.end();++i)
1771  {
1772  T.add_new_pt(m_InterPts[*i], (unsigned long &)*i); // MT: ajout cast
1773  }
1774  //get all the triangles of the triangulation
1775  std::vector<std::vector<unsigned long> > Tri_set = T.get_all_triangles((m_BOOP == MINUS && !TriCut.Facet_from_A)?true:false);
1776  //add these triangles to the result
1777  ppbuilder.add_triangle(Tri_set, he);
1778  }
1779  else
1780  {
1781  //the facet is added to the result. If the facet belongs to the second polyhedron, and if the
1782  //Boolean operation is a Subtraction, it is necessary to invert the orientation of the facet.
1783  if(m_BOOP == MINUS && !facet_from_A) ppbuilder.add_triangle(pFacet, true);
1784  else ppbuilder.add_triangle(pFacet, false);
1785  }
1786  //the tag of the three neighboring facets is updated
1787  pFacet->facet_begin()->opposite()->facet()->IsExt = true;
1788  pFacet->facet_begin()->next()->opposite()->facet()->IsExt = true;
1789  pFacet->facet_begin()->next()->next()->opposite()->facet()->IsExt = true;
1790  }
1791 
1792 #ifdef BOOLEAN_OPERATIONS_DEBUG
1793 
1797  void ColorType()
1798  {
1799 #if 0//TODO-elo-restore
1800  Facet_iterator pFacet = NULL;
1801  for(pFacet = m_pA->facets_begin(); pFacet != m_pA->facets_end(); pFacet++)
1802  {
1803  if(pFacet->Label < m_Inter_tri.size())
1804  pFacet->color(1.0, 0.0, 0.0);
1805  else if(pFacet->IsExt)
1806  pFacet->color(0.0, 1.0, 0.0);
1807  else
1808  pFacet->color(0.0, 0.0, 1.0);
1809  }
1810  for(pFacet = m_pB->facets_begin(); pFacet != m_pB->facets_end(); pFacet++)
1811  {
1812  if(pFacet->Label < m_Inter_tri.size())
1813  pFacet->color(1.0, 0.0, 0.0);
1814  else if(pFacet->IsExt)
1815  pFacet->color(0.0, 1.0, 0.0);
1816  else
1817  pFacet->color(0.0, 0.0, 1.0);
1818  }
1819 #endif
1820  }
1821 
1822 
1825  void WriteData(const EnrichedPolyhedron &m_out)
1826  {
1827  std::size_t N_IFA = 0;
1828  std::size_t N_FFA = 0;
1829  std::size_t N_LFFA = 0;
1830  std::size_t N_IFB = 0;
1831  std::size_t N_FFB = 0;
1832  std::size_t N_LFFB = 0;
1833  std::size_t N_CF;
1834 
1835  for(Facet_iterator pFacet = m_pA->facets_begin();pFacet != m_pA->facets_end();++pFacet)
1836  {
1837  if(pFacet->Label < m_Inter_tri.size()) N_IFA++;
1838  else if(pFacet->IsExt) N_FFA++;
1839  else N_LFFA++;
1840  }
1841  for(Facet_iterator pFacet = m_pB->facets_begin();pFacet != m_pB->facets_end();++pFacet)
1842  {
1843  if(pFacet->Label < m_Inter_tri.size()) N_IFB++;
1844  else if(pFacet->IsExt) N_FFB++;
1845  else N_LFFB++;
1846  }
1847  N_CF = m_out.size_of_facets() - N_FFA - N_FFB;
1848 
1849  std::ofstream ofstrtime("boolean_operation_time.txt");
1850 
1851  ofstrtime << "Computation time :" << std::endl;
1852  ofstrtime << std::endl;
1853  ofstrtime << "Algorithm" << std::endl;
1854  ofstrtime << " Initialization : "
1855  << tr(duration_Init)
1856  << " s"
1857  << std::endl;
1858  ofstrtime << " + Finding the Intersections : "
1860  << " s"
1861  << std::endl;
1862  ofstrtime << " + Compute the Intersections : "
1864  << " s"
1865  << std::endl;
1866  ofstrtime << " + Cut the Intersected Facets : "
1868  << " s"
1869  << std::endl;
1870  ofstrtime << " + Complete the result : "
1872  << " s"
1873  << std::endl;
1874  ofstrtime << " + Create the polyhedron : "
1875  << tr(duration_delegate)
1876  << " s"
1877  << std::endl;
1878  ofstrtime << "---------------------------------------"
1879  << std::endl;
1880  ofstrtime << " Total : "
1881  << tr(duration_total)
1882  << " s"
1883  << std::endl;
1884 
1885  ofstrtime << std::endl;
1886  ofstrtime << std::endl;
1887  ofstrtime << "Details :" << std::endl;
1888  ofstrtime << std::endl;
1889  ofstrtime << "Polyedron A :" << std::endl;
1890  ofstrtime << "Number of Facets : "
1891  << m_pA->size_of_facets() << std::endl;
1892  ofstrtime << "Number of Intersected Facets : " << N_IFA << std::endl;
1893  ofstrtime << "Number of Facets not in the result : " << N_LFFA << std::endl;
1894  ofstrtime << std::endl;
1895  ofstrtime << "Polyedron B :" << std::endl;
1896  ofstrtime << "Number of Facets : "
1897  << m_pB->size_of_facets() << std::endl;
1898  ofstrtime << "Number of Intersected Facets : " << N_IFB << std::endl;
1899  ofstrtime << "Number of Facets not in the result : " << N_LFFB << std::endl;
1900  ofstrtime << std::endl;
1901  ofstrtime << "Result :" << std::endl;
1902  ofstrtime << "Number of Facets : "
1903  << m_out.size_of_facets() << std::endl;
1904  ofstrtime << "Number of Facets from A : " << N_FFA << std::endl;
1905  ofstrtime << "Number of Facets from B : " << N_FFB << std::endl;
1906  ofstrtime << "Number of Created Facets : " << N_CF << std::endl;
1907  }
1908 #endif // BOOLEAN_OPERATIONS_DEBUG
1909 
1910  // attributes
1911 
1914 
1919 
1920 
1923 
1925  std::map< FacetId, std::set< FacetId > > m_Couples;
1927  std::vector< Point3d_exact > m_InterPts;
1929  std::vector< Triangle_Cut > m_Inter_tri;
1931  std::vector< Facet_handle > m_Facet_Handle;
1932 
1935 
1937  double duration_Inputs_copy; // in secs
1939  double duration_Init; // in secs
1941  double duration_FindCouples; // in secs
1947  double duration_PropagateFacets; // in secs
1949  double duration_delegate; // in secs
1951  double duration_Output_copy; // in secs
1953  double duration_total; // in secs
1954 };
1955 
HDS
EnrichedPolyhedron::HalfedgeDS HDS
Definition: boolops_polyhedra.hpp:45
EnrichedPolyhedron
CGAL::Polyhedron_3< CGALKernel, EnrichedItems > EnrichedPolyhedron
Definition: boolops_enriched_polyhedron.hpp:102
Enriched_Triangle::f
Facet_handle f
The handle of the facet used to build the triangle.
Definition: boolops_polyhedra.hpp:110
boolops_definitions.hpp
BoolPolyhedra::InterTriangleTriangle
void InterTriangleTriangle(FacetId &A, FacetId &B)
Compute the intersection between two facets.
Definition: boolops_polyhedra.hpp:744
BoolPolyhedra::m_pB
EnrichedPolyhedron * m_pB
The second input polyhedron.
Definition: boolops_polyhedra.hpp:1918
FEVV::DataStructures::AIF::next
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor next(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the next halfedge around its face.
Definition: Graph_traits_aif.h:599
BoolPolyhedra::triangulate
void triangulate(EnrichedPolyhedron *m)
Triangulate the mesh.
Definition: boolops_polyhedra.hpp:421
point_to_double
Point3d point_to_double(Point3d_exact &pe)
Convertion from a Point3d_exact (exact) to a Point3d (double)
Definition: boolops_definitions.hpp:99
BoolPolyhedra::Info_Inter::he
Halfedge_handle he
The halfedge.
Definition: boolops_polyhedra.hpp:174
BoolPolyhedra::duration_delegate
double duration_delegate
Time to create the result polyhedron.
Definition: boolops_polyhedra.hpp:1949
BoolPolyhedra::add_facet_to_solution
void add_facet_to_solution(Facet_handle &pFacet, bool facet_from_A)
Add a facet to the result.
Definition: boolops_polyhedra.hpp:1760
BoolPolyhedra::Triangle_Cut::Triangle_Cut
Triangle_Cut(Vector_exact V, bool ffA)
Constructor.
Definition: boolops_polyhedra.hpp:158
Facet_iterator
EnrichedPolyhedron::Facet_iterator Facet_iterator
Definition: boolops_polyhedra.hpp:44
Facet_handle
EnrichedPolyhedron::Facet_handle Facet_handle
Definition: boolops_polyhedra.hpp:43
num_type
CGAL::Lazy_exact_nt< CGAL::Gmpq > num_type
exact number type
Definition: boolops_definitions.hpp:61
Enriched_Triangle
An enriched triangle.
Definition: boolops_polyhedra.hpp:59
tr
double tr(double &n)
Truncate a number to 1/1000 (only if BOOLEAN_OPERATIONS_DEBUG is enable)
Definition: boolops_definitions.hpp:127
Vertex_iterator
EnrichedPolyhedron::Vertex_iterator Vertex_iterator
Definition: boolops_polyhedra.hpp:41
BoolPolyhedra::Triangle_Cut::PtList
std::set< InterId > PtList
A list of points (when the intersection is a point)
Definition: boolops_polyhedra.hpp:149
Halfedge_handle
EnrichedPolyhedron::Halfedge_handle Halfedge_handle
Definition: boolops_polyhedra.hpp:42
Triangulation::add_segment
void add_segment(Point_3 &p1, Point_3 &p2, unsigned long &Label1, unsigned long &Label2)
Adds a constrained segment in the triangulation.
Definition: boolops_triangulation.hpp:288
BoolPolyhedra::Triangle_Cut::Facet_from_A
bool Facet_from_A
true if the facet belongs to the first polyhedron
Definition: boolops_polyhedra.hpp:142
BoolPolyhedra::m_Inter_tri
std::vector< Triangle_Cut > m_Inter_tri
Informations about the intersected facets.
Definition: boolops_polyhedra.hpp:1929
boolops_enriched_polyhedron.hpp
BoolPolyhedra::duration_Init
double duration_Init
Initialisation time.
Definition: boolops_polyhedra.hpp:1939
FEVV::DataStructures::AIF::opposite
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor opposite(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the halfedge with source and target swapped.
Definition: Graph_traits_aif.h:625
BoolPolyhedra::m_InterPts
std::vector< Point3d_exact > m_InterPts
Lists the exact intersection points computed.
Definition: boolops_polyhedra.hpp:1927
Enriched_Triangle::FT
AABB_Kernel::FT FT
number type used in the kernel
Definition: boolops_polyhedra.hpp:69
BoolPolyhedra::Init
void Init(EnrichedPolyhedron *pMA, EnrichedPolyhedron *pMB)
Initialisation of the tags, and triangulation of the two input polyhedra.
Definition: boolops_polyhedra.hpp:360
HalfedgeId
unsigned long HalfedgeId
Halfedge Id.
Definition: boolops_properties.h:30
BoolPolyhedra::Get_Segment
void Get_Segment(Info_Inter *inter, std::vector< InterId > &I)
Extracts the segment from a set of four intersection points and store these points in the list of int...
Definition: boolops_polyhedra.hpp:1465
BoolPolyhedra::IsInTriangle
void IsInTriangle(Info_Inter *inter)
Finds the position of a point in a 3d triangle.
Definition: boolops_polyhedra.hpp:1308
FEVV::Math::Vector::cross_product
static std::vector< ElementType > cross_product(const ElementType v1[DIM], const ElementType v2[DIM])
Definition: MatrixOperations.hpp:460
AABB_Kernel
CGAL::Simple_cartesian< double > AABB_Kernel
Kernel used for the computations in a AABB-tree.
Definition: boolops_polyhedra.hpp:53
Point3d_exact
CGAL::Point_3< Exact_Kernel > Point3d_exact
3d point using exact number type
Definition: boolops_definitions.hpp:79
Enriched_Triangle::Point_3
AABB_Kernel::Point_3 Point_3
3d point
Definition: boolops_polyhedra.hpp:64
BoolPolyhedra::duration_Output_copy
double duration_Output_copy
Output mesh copy time.
Definition: boolops_polyhedra.hpp:1951
InterId
unsigned long InterId
Intersection Id.
Definition: boolops_properties.h:42
BoolPolyhedra::Triangle_Cut::Triangle_Cut
Triangle_Cut()
Default constructor.
Definition: boolops_polyhedra.hpp:154
Enriched_Triangle::to_K
Point_3 to_K(const Point3d &p)
convert any 3d point in the kernel used by the AABB-tree
Definition: boolops_polyhedra.hpp:103
BoolPolyhedra::FindCouples
void FindCouples()
Finds every couple of facets between the two input polyhedra that intersects.
Definition: boolops_polyhedra.hpp:485
BoolPolyhedra::Store_Intersection
void Store_Intersection(Info_Inter *inter)
Store the intersection and memorize it for every couples of facet-halfedge.
Definition: boolops_polyhedra.hpp:1494
BoolPolyhedra::m_pA
EnrichedPolyhedron * m_pA
The first input polyhedron.
Definition: boolops_polyhedra.hpp:1916
BoolPolyhedra::Triangle_Cut::norm_dir
Vector_exact norm_dir
An exact vector giving the direction of the normal.
Definition: boolops_polyhedra.hpp:144
Vector_exact
CGAL::Vector_3< Exact_Kernel > Vector_exact
3d vector using exact number type
Definition: boolops_definitions.hpp:73
Enriched_Triangle::Enriched_Triangle
Enriched_Triangle(Facet_handle &_f)
Constructor.
Definition: boolops_polyhedra.hpp:75
BoolPolyhedra::duration_total
double duration_total
Time to Compute a Boolean operation.
Definition: boolops_polyhedra.hpp:1953
Halfedge_around_vertex_circulator
EnrichedPolyhedron::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator
Definition: boolops_polyhedra.hpp:47
FacetId
unsigned long FacetId
Facet Id.
Definition: boolops_properties.h:36
AABB_Primitive
CGAL::AABB_triangle_primitive< AABB_Kernel, std::list< Triangle >::iterator > AABB_Primitive
A primitive for an AABB-tree.
Definition: boolops_polyhedra.hpp:121
Triangle
Enriched_Triangle Triangle
A triangle enriched with a facet handle.
Definition: boolops_polyhedra.hpp:116
BoolPolyhedra::duration_PropagateFacets
double duration_PropagateFacets
Time to complete the result with the facets from the input polyhedra.
Definition: boolops_polyhedra.hpp:1947
BoolPolyhedra::PropagateFacets
void PropagateFacets()
Complete the building of the result.
Definition: boolops_polyhedra.hpp:654
CPolyhedron_from_polygon_builder_3
A polyhedron incremental builder.
Definition: boolops_cpolyhedron_builder.hpp:34
Geometry_traits.h
point_to_exact
Point3d_exact point_to_exact(Point3d &p)
Convertion from a Point3d (double) to a Point3d_exact (exact)
Definition: boolops_definitions.hpp:87
BoolPolyhedra::Triangle_Cut::CutList
std::vector< std::vector< InterId > > CutList
A list of segments (the intersections with the facets of the other polyhedron)
Definition: boolops_polyhedra.hpp:147
BoolPolyhedra::duration_CutIntersectedFacets
double duration_CutIntersectedFacets
Time to Cut the facets.
Definition: boolops_polyhedra.hpp:1945
Triangulation::add_new_pt
Vertex_handle_tri add_new_pt(Point_3 p, unsigned long &Label)
Adds a point in the triangulation.
Definition: boolops_triangulation.hpp:265
BoolPolyhedra::ppbuilder
CPolyhedron_from_polygon_builder_3< HDS > ppbuilder
The polyhedron builder.
Definition: boolops_polyhedra.hpp:1922
Triangulation
To subdivide a facet. (the kernel K must be exact)
Definition: boolops_triangulation.hpp:109
boolops_triangulation.hpp
BoolPolyhedra::InterTriangleSegment
void InterTriangleSegment(Info_Inter *inter)
Compute the intersection between a facet and a halfedge.
Definition: boolops_polyhedra.hpp:1240
BoolPolyhedra::m_Couples
std::map< FacetId, std::set< FacetId > > m_Couples
Lists the couples of facets that intersect.
Definition: boolops_polyhedra.hpp:1925
BoolPolyhedra::Info_Inter::Id
InterId Id
The Id of the intersection point.
Definition: boolops_polyhedra.hpp:190
MINUS
@ MINUS
Definition: boolops_definitions.hpp:55
BoolPolyhedra::Triangle_Cut::RefInter
std::map< HalfedgeId, InterId > RefInter
The list of the intersections.
Definition: boolops_polyhedra.hpp:151
AABB_Traits
CGAL::AABB_traits< AABB_Kernel, AABB_Primitive > AABB_Traits
concept for AABB-tree
Definition: boolops_polyhedra.hpp:124
Triangulation::get_triangles
std::vector< std::vector< unsigned long > > get_triangles(bool inv_triangles, bool *IsExt)
Gets the triangles of the triangulation that belongs to the result and deduce for the three neighbori...
Definition: boolops_triangulation.hpp:307
BoolPolyhedra::IsSegment
bool IsSegment(Info_Inter *inter)
Verify that the intersection is a segment.
Definition: boolops_polyhedra.hpp:1369
Bool_Op
Bool_Op
The three Boolean operations.
Definition: boolops_definitions.hpp:55
Halfedge_handle
EnrichedPolyhedron::Halfedge_handle Halfedge_handle
Definition: boolops_cpolyhedron_builder.hpp:25
Facet_handle
EnrichedPolyhedron::Facet_handle Facet_handle
Definition: boolops_cpolyhedron_builder.hpp:26
BoolPolyhedra::Info_Inter::IsOnVertex
bool IsOnVertex
true if the intersection is exactly on the vertex pointed by he
Definition: boolops_polyhedra.hpp:176
BoolPolyhedra::Info_Inter::pt
Point3d_exact pt
The intersection point (exact)
Definition: boolops_polyhedra.hpp:188
AABB_Tree
CGAL::AABB_tree< AABB_Traits > AABB_Tree
AABB-tree.
Definition: boolops_polyhedra.hpp:127
BoolPolyhedra::duration_FindCouples
double duration_FindCouples
Time to find all the couples of facet that intersect.
Definition: boolops_polyhedra.hpp:1941
BoolPolyhedra::Info_Inter::f
Facet_handle f
The facet.
Definition: boolops_polyhedra.hpp:172
Point3d
EnrichedPolyhedron::Point_3 Point3d
Definition: boolops_cpolyhedron_builder.hpp:27
Compute_Normal_direction
Vector_exact Compute_Normal_direction(Halfedge_handle he)
Definition: boolops_definitions.hpp:111
BoolPolyhedra::m_BOOP
Bool_Op m_BOOP
Boolean operation computed.
Definition: boolops_polyhedra.hpp:1913
Triangulation::get_all_triangles
std::vector< std::vector< unsigned long > > get_all_triangles(bool inv_triangles)
Gets all the triangles of the triangulation.
Definition: boolops_triangulation.hpp:399
properties.h
BoolPolyhedra::BoolPolyhedra
BoolPolyhedra(HalfedgeGraph &_gA, HalfedgeGraph &_gB, HalfedgeGraph &_g_out, Bool_Op BOOP)
Constructor.
Definition: boolops_polyhedra.hpp:200
boolops_properties.h
BoolPolyhedra::rmCouple
void rmCouple(FacetId &A, FacetId &B)
removes properly a couple from the list
Definition: boolops_polyhedra.hpp:734
BoolPolyhedra::Info_Inter::res
unsigned short res
A code for the location of the intersection : 0 : Intersection is strictly in the facet 1 : Intersec...
Definition: boolops_polyhedra.hpp:186
INTER
@ INTER
Definition: boolops_definitions.hpp:55
Enriched_Triangle::facet
Facet_handle facet()
Accessor.
Definition: boolops_polyhedra.hpp:96
BoolPolyhedra::ComputeIntersections
void ComputeIntersections()
Compute the intersections.
Definition: boolops_polyhedra.hpp:598
BoolPolyhedra::CutIntersectedFacets
void CutIntersectedFacets()
Cuts the intersected facets and starts to build the result.
Definition: boolops_polyhedra.hpp:612
BoolPolyhedra::Triangle_Cut
A structure containing informations about an intersected facet.
Definition: boolops_polyhedra.hpp:140
BoolPolyhedra::duration_Inputs_copy
double duration_Inputs_copy
Input meshes copy time.
Definition: boolops_polyhedra.hpp:1937
BoolPolyhedra::tree
AABB_Tree tree
the AABB-tree
Definition: boolops_polyhedra.hpp:1934
BoolPolyhedra::~BoolPolyhedra
~BoolPolyhedra()
Destructor.
Definition: boolops_polyhedra.hpp:354
BoolPolyhedra::Info_Inter
Contains informations about an intersection between a facet and a halfedge.
Definition: boolops_polyhedra.hpp:170
UNION
@ UNION
Definition: boolops_definitions.hpp:55
BoolPolyhedra
The class that compute a Boolean operation.
Definition: boolops_polyhedra.hpp:134
get_time_and_reset
double get_time_and_reset(std::chrono::time_point< std::chrono::steady_clock > &time_start)
Measure time since starting time and reset starting time.
Definition: boolops_definitions.hpp:140
BoolPolyhedra::duration_ComputeIntersections
double duration_ComputeIntersections
Time to Compute all the intersections.
Definition: boolops_polyhedra.hpp:1943
boolops_cpolyhedron_builder.hpp
BoolPolyhedra::m_Facet_Handle
std::vector< Facet_handle > m_Facet_Handle
Index to obtain the handle of a facet with its Id.
Definition: boolops_polyhedra.hpp:1931