Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Overlay.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // $Id: Overlay.C,v 1.27 2008/12/06 08:43:28 mtcampbe Exp $
24 
25 //==========================================================
26 // The implementation of the overlay algorithm.
27 //
28 // Author: Xiangmin Jiao
29 // Last modified: 06/23/2006 (Added implicit feature matching.)
30 //
31 //==========================================================
32 
33 #include <cstdlib>
34 #include <iostream>
35 #include <fstream>
36 #include <queue>
37 #include <set>
38 #include <utility>
39 #include <cstdio>
40 #include <cmath>
41 #include "Timing.h"
42 #include "Overlay.h"
43 
45 
46 Overlay::Overlay( const COM::Window *w1, const COM::Window *w2,
47  const char *pre)
48  : op(1.e-9, 1.e-6, 1.e-2), is_opposite(true),
49  verbose(true), verbose2(false), out_pre(pre?pre:""),
50  eps_e( 1.e-2), eps_p(1.e-6) {
51  B = new RFC_Window_overlay( const_cast<COM::Window*>(w1), BLUE,
52  out_pre.c_str());
53  G = new RFC_Window_overlay( const_cast<COM::Window*>(w2), GREEN,
54  out_pre.c_str());
55 
56 #if DEBUG
57  verbose2 = true;
58 #endif
59 }
60 
62  delete G;
63  delete B;
64 }
65 
66 void Overlay::set_tolerance( double tol) {
67  COM_assertion_msg( tol<=0.2, "Tolerance too large");
68 
69  eps_e = std::max(tol, 1.e-3); // Set snap tolerance.
70 }
71 
72 // This function is the main interface for the overlay algorithm.
74  Bbox_3 bbox=B->get_bounding_box(), gbox = G->get_bounding_box();
75 
76  std::cout << "\tMesh " << B->name() << ": "
77  << B->size_of_nodes() << " vertices, "
78  << B->size_of_faces() << " faces, with bounding box "
79  << bbox << "\n\tMesh " << G->name() << ": "
80  << G->size_of_nodes() << " vertices, "
81  << G->size_of_faces() << " faces, with bounding box "
82  << gbox << std::endl;
83 
84  double tol_high = 3.e-1, tol_low=1.e-1;
85 
86  // First, check whether the scales of the two bounding boxes are
87  // the same by comparing the total lengths of bounding boxes and
88  // the individual dimensions.
89  double bl = (bbox.xmax()-bbox.xmin()) +
90  (bbox.ymax()-bbox.ymin()) + (bbox.zmax()-bbox.zmin());
91  double gl = (gbox.xmax()-gbox.xmin()) +
92  (gbox.ymax()-gbox.ymin()) + (gbox.zmax()-gbox.zmin());
93 
94  if ( bl>gl*(1+tol_high) || gl>bl*(1+tol_high) ||
95  !bbox.do_match( gbox, std::min(bl,gl)*tol_high)) {
96  std::cerr << "ERROR: The bounding boxes differ by more than "
97  << tol_high*100 << "%. Please check the geometries. Stopping..."
98  << std::endl;
99  abort();
100  }
101 
102  // If the bounding boxes do not match at all sides within a fraction
103  // of the longest dimension, then stop the code.
104  // the difference between the two boxes is smaller than a fraction (eps)
105  // of the largest dimension of the two boxes.
106  if ( !bbox.do_match( gbox, std::min(bl,gl)*tol_low)) {
107  std::cerr << "WARNING: The bounding boxes differ by more than "
108  << tol_low*100 << "% but less than "
109  << tol_high*100 << "%. Continuing anyway." << std::endl;
110  }
111 
112  double t0 = get_wtime();
113 
114  // Create helper data in two input meshes.
117 
118  // Detect the 0-features of the two meshes.
119  std::cerr << "Detecting features in " << B->name() << "..." << std::endl;
120  B->detect_features();
121 
122  std::cerr << "Detecting features in " << G->name() << "..." << std::endl;
123  G->detect_features();
124 
126 
127  // Evaluate normals for the nodes.
128  B->evaluate_normals();
129  G->evaluate_normals();
130 
131  std::cout << "Performing mesh overlay..." << std::flush;
132  // Step 1: Project the blue vertices onto G and
133  // compute the intersection points of blue edges with green
134  // edges, and insert the intersections into the blue edges on the fly.
136  std::cout << "..." << std::flush;
137 
138  // Step 2: Sort the intersection points corresponding to each green
139  // edge and insert them into green edges (in linear time).
141  std::cout << "..." << std::flush;
142 
143  // Step 3: Compute the projection of the green vertices on B.
145  std::cout << "..." << std::flush;
146 
147  if ( verbose) {
148  std::cout << "\n\tLocated " << inodes.size()
149  << " edge intersections.\n\tDone in "
150  << get_wtime()-t0 << " sec.\n"
151  << "Exporting the subdivision..." << std::flush;
152  t0 = get_wtime();
153  }
154 
155  // Finally, assign local ids to the subnodes within panes and
156  number_subnodes();
157 
158  // subdivide the faces and assign local ids to these subfaces,and
159  // create the nodal and face lists for the panes.
160  number_subfaces();
161 
162  // Now, clean up the overlay data
163  // Destroy helper data in the input windows
165  while ( !inodes.empty()) {
166  INode* x = inodes.front(); inodes.pop_front();
167  delete x;
168  }
169 
170  std::cout << "Done";
171  if ( verbose) {
172  std::cout << " in " << get_wtime()-t0 << " sec.";
173  }
174  std::cout << std::endl;
175  return 0;
176 }
177 
178 Real Overlay::sq_length( const Halfedge &h) const {
179  return (h.origin()->point() - h.destination()->point()).squared_norm();
180 }
181 
182 // This subroutine corrects the green parent of an inode i by intersecting
183 // it with the previous assigned green parent.
184 // TODO: Currently does not resolve inconsistencies involving multiple
185 // blue edges. Needs to add support for it.
186 void Overlay::
188  Halfedge *b = x.halfedge( BLUE);
190 
191  // Step 1, verify that x is not at a green vertex that already has
192  // an inode associated with. If so, merge the two inodes by making
193  // its blue parent the intersection of the two blue edges/vertices,
194  // and delete the old one.
195  if ( x.parent_type( GREEN) == PARENT_VERTEX) {
196  INode *i = acc.get_inode( acc.get_origin( g));
197  if (i) {
198  if ( i->parent_type( BLUE) == PARENT_VERTEX) {
199  std::cerr << "ERROR: One-to-many mapping at green vertex "
200  << acc.get_pane(g)->get_index(g->origin())+1
201  << " of pane " << acc.get_pane(g)->id()
202  << " at " << g->origin()->point()
203  << ".\n It is projected onto from blue vertices \n\t"
204  << acc.get_pane(b)->get_index(b->origin())+1 << " of pane "
205  << acc.get_pane(b)->id() << " at " << b->origin()->point() << " and\n\t";
206  b = i->halfedge(BLUE);
207  std::cerr << acc.get_pane(b)->get_index(b->origin())+1
208  << " of pane " << acc.get_pane(b)->id()
209  << " at " << b->origin()->point() << std::endl;
210  RFC_assertion(i->parent_type( BLUE) != PARENT_VERTEX); abort();
211  }
212  if ( !contains( i->halfedge( BLUE), i->parent_type( BLUE),
213  b, PARENT_VERTEX)) {
214  b = acc.get_next( b);
216  b, PARENT_VERTEX));
217  }
218  x.set_parent( b, Point_2(0,0), BLUE);
219  }
220  }
221 
222  if ( x.parent_type( BLUE) == PARENT_VERTEX) {
223  // Step 2a, assign blue parent
224  INode *i = acc.get_inode( acc.get_origin( b));
225  if ( i != NULL) {
226  if ( !contains( i->halfedge( GREEN), i->parent_type( GREEN),
227  g, x.parent_type( GREEN))) {
228  // Otherwise, we must correct the green parent of i by computing
229  // the intersection of the two computed parents
230  if ( x.parent_type( GREEN) == PARENT_FACE) {
231  Parent_type pg = i->parent_type(GREEN);
232 
233  bool found=false;
234  if ( pg ==PARENT_FACE) {
235  // Find the intersection of the two faces
236  Halfedge *h = g; RFC_assertion( !acc.is_border(h));
237  do {
238  if ( contains( i->halfedge( GREEN), pg, h, PARENT_EDGE)) {
239  // the edge is the intersection of the two
241  h, GREEN);
242  RFC_assertion( nc[0]>0 && nc[0]<1 && nc[1]>0 && nc[1]<0.5);
243  x.set_parent( g, Point_2(nc[0],0), GREEN);
244 
245  found = true;
246  break;
247  }
248  } while ( (h=acc.get_next( h)) != g);
249  }
250 
251  if ( !found) {
252  // Search for the common vertex
253  Halfedge *h = g;
254  do {
255  if ( contains( i->halfedge( GREEN), pg, h, PARENT_VERTEX)) {
256  g = h; x.set_parent( g, Point_2(0,0), GREEN);
257 
258  found = true;
259  break;
260  }
261  } while ( (h=acc.get_next( h)) != g);
262  RFC_assertion( found);
263  }
264  }
265  else { // green parent of x is not a face.
266  if ( x.parent_type(GREEN)==PARENT_EDGE &&
267  x.parent_type( GREEN) == i->parent_type( GREEN) &&
268  !contains( i->halfedge( GREEN), i->parent_type( GREEN),
269  g, PARENT_VERTEX)) {
270  g = acc.get_next( g);
272  g, PARENT_VERTEX));
273  }
275  acc.get_inode(acc.get_origin(g))->parent_type(BLUE)
276  == PARENT_EDGE);
277 
278  x.set_parent( g, Point_2(0,0), GREEN);
279 
280  if ( !contains( i->halfedge( GREEN), i->parent_type( GREEN),
281  g, x.parent_type( GREEN))) {
282  std::cerr << "ERROR: One-to-many mapping at blue vertex "
283  << acc.get_pane(b)->get_index(b->origin())+1
284  << " of pane " << acc.get_pane(b)->id()
285  << " at " << b->origin()->point()
286  << ". It projects onto \n\tgreen vertex "
287  << acc.get_pane(g)->get_index(g->origin())+1 << " of pane "
288  << acc.get_pane(g)->id() << " at " << g->origin()->point()
289  << " and\n\tgreen ";
290  switch (i->parent_type(GREEN)) {
291  case PARENT_VERTEX: std::cerr << "vertex"; break;
292  case PARENT_EDGE: std::cerr << "edge"; break;
293  case PARENT_FACE: std::cerr << "face incident on"; break;
294  default: ;
295  }
296  g = i->halfedge(GREEN);
297  std::cerr << " ("
298  << acc.get_pane(g)->get_index(g->origin())+1 << ","
299  << acc.get_pane(g)->get_index(g->destination())+1
300  << ") of pane " << acc.get_pane(g)->id() << " at ("
301  << g->origin()->point() << ","
302  << g->destination()->point() << ")." << std::endl;
303 
305  g, x.parent_type( GREEN))); abort();
306  }
307  }
308  }
309  delete i; i=NULL;
310  }
311  acc.set_inode( acc.get_origin( b), &x);
312 
313  // Step 3a
314  // Delete the inconsistent inodes on adjacent edges of b
315  Halfedge *h = b;
316  do {
317  INode_list &il = acc.get_inode_list( h);
318  if ( !il.empty()) {
319  // Throw away the false intersection points.
320  while ( ! il.empty()) {
321  INode *i=&il.front();
322 
323  if ( contains( i->halfedge( GREEN), i->parent_type( GREEN),
324  g, x.parent_type( GREEN))) {
325  il.pop_front();
326  delete i; i=NULL;
327  }
328  else
329  break;
330  }
331  }
332  else {
334  // Throw away the false intersection points.
335  while ( ! ilr.empty()) {
336  INode *i=&ilr.back();
337 
338  if ( contains( i->halfedge( GREEN), i->parent_type( GREEN),
339  g, x.parent_type( GREEN))) {
340  ilr.pop_back();
341  delete i; i=NULL;
342  }
343  else
344  break;
345  }
346  }
347  } while ( ( h = acc.get_next_around_origin( h)) != b);
348  }
349  else {
350  // If x is on a blue edge, remove the inconsistent ones
351  RFC_assertion( x.parent_type( BLUE) == PARENT_EDGE && b1==b);
352 
353  // Step 3b
354  INode_list &il = acc.get_inode_list( b);
355  // Throw away the false intersection points.
356  while ( !il.empty()) {
357  INode *i=&il.back();
358  if ( i->nat_coor(BLUE)[0] >= x.nat_coor(BLUE)[0]) {
359  std::cerr << "WARNING: Intersections are out-of-order on blue edge ("
360  << acc.get_pane(b)->get_index(b->origin())+1 << ","
361  << acc.get_pane(b)->get_index(b->destination())+1
362  << ") on pane " << acc.get_pane(b)->id() << " at ("
363  << b->origin()->point() << "," << b->destination()->point()
364  << ").\n\tPrevious intersection was "
365  << i->nat_coor(BLUE)[0]
366  << " but current one is at " << x.nat_coor(BLUE)[0]
367  << " and green parameterization is "
368  << x.nat_coor(GREEN)[0] << "." << std::endl;
369 
370  RFC_assertion( std::abs(i->nat_coor(0)[0] - x.nat_coor(0)[0]) < 0.1);
372 
373  if ( !contains( i->halfedge( GREEN), i->parent_type( GREEN),
374  g, PARENT_VERTEX) &&
375  !contains( i->halfedge( GREEN), i->parent_type( GREEN),
376  g->next(), PARENT_VERTEX)) {
377  std::cerr << "Cannot be continued. Stopping..." << std::endl;
378  abort();
379  }
380 
381  // Otherwise, we must correct the green parent of i by computing
382  // the intersection of the two computed parents
383  if ( !contains( i->halfedge( GREEN), i->parent_type( GREEN),
384  g, PARENT_VERTEX))
385  g = acc.get_next( g);
386 
387  x.set_parent( g, Point_2(0,0), GREEN);
388 
389  { // Determine the blue parameterization of x based on closest point
390  // of the green vertex on the blue edge.
391  Vector_3 t = b->destination()->point()-b->origin()->point();
392  Real c = (g->origin()->point()-b->origin()->point())*t / (t*t);
393 
394  // If snapped onto a blue vertex, then call recursively.
395  if ( c>=1-eps_e) {
396  x.set_parent( b->next(), Point_2(0,0), BLUE);
397  insert_node_in_blue_edge( x, x.halfedge(BLUE)); return;
398  }
399  else if ( c<=eps_e) {
400  x.set_parent( b, Point_2(0,0), BLUE);
401  insert_node_in_blue_edge( x, x.halfedge(BLUE)); return;
402  }
403 
404  // Otherwise, pop the neighbor vertex.
405  x.set_parent( b, Point_2(c,0), BLUE);
406  }
407  }
408 
409  if ( contains( i->halfedge( GREEN), i->parent_type( GREEN),
410  g, x.parent_type( GREEN))) {
411  il.pop_back();
412  delete i; i=NULL;
413  }
414  else
415  break;
416  }
417  il.push_back( x);
418  }
419 
420  // If x is a vertex and b is border, change to a nonborder edge.
421  if ( x.parent_type(BLUE) == PARENT_VERTEX && acc.is_border( b)) {
423  x.set_parent( b, Point_2(0,0), BLUE);
424  }
425 
426  // If the green parent of x is a vertex, associate x with the green vertex.
427  if ( x.parent_type(GREEN) == PARENT_VERTEX) {
428  RFC_assertion(g==x.halfedge(GREEN));
429  acc.set_inode( acc.get_origin(g), &x);
430  }
431 
432  // Output some debugging information.
433  static int count=0, countmax=10;
434  if ( verbose && count<countmax) {
435  if ( x.parent_type(BLUE) == PARENT_VERTEX) {
436  b = x.halfedge(BLUE);
437  double dist = ( b->origin()->point() -
438  op.get_point( x.halfedge(GREEN), x.nat_coor(GREEN))).squared_norm();
439 
440  if ( dist > 0.1*(b->destination()->point()-
441  b->origin()->point()).squared_norm()) {
442  if ( count == 0) std::cout << std::endl;
443  std::cout << "WARNING: Distance from blue vertex "
444  << acc.get_pane(b)->get_index(b->origin())+1
445  << " of pane " << acc.get_pane(b)->id()
446  << " at " << b->origin()->point()
447  << " to green mesh is relatively large: " << std::sqrt(dist) << std::endl;
448 
449  if ( count++==0) {
450  std::cout << "Note: Only " << countmax << " such warnings "
451  << " will be printed." << std::endl;
452  }
453  }
454  }
455  else if ( x.parent_type(GREEN) == PARENT_VERTEX) {
456  g = x.halfedge( GREEN);
457  double dist = ( g->origin()->point() -
458  op.get_point( x.halfedge(BLUE), x.nat_coor(BLUE))).squared_norm();
459 
460  if ( dist > 0.1*( g->destination()->point()-
461  g->origin()->point()).squared_norm()) {
462 
463  if ( count == 0) std::cout << std::endl;
464  std::cout << "WARNING: Distance from green vertex "
465  << acc.get_pane(g)->get_index(g->origin())+1
466  << " of pane " << acc.get_pane(g)->id()
467  << " at " << g->origin()->point()
468  << " to blue mesh is relatively large: " << std::sqrt(dist) << std::endl;
469 
470  if ( count++==0) {
471  std::cout << "NOTE: Only " << countmax << " such warnings"
472  << " will be printed." << std::endl;
473  }
474  }
475  }
476  }
477 }
478 
479 // Move an edge from ridge- or corner-queue into main queue.
480 // We use q_rdg to store edges that point from ridge vertices to
481 // non-feature vertices and use q_crn for edges from corner
482 // vertices to non-corner vertices. Move edge from q_rdg into
483 // q only if q is empty; and move edge from q_crn to q if both q
484 // and q_rdg are empty.
485 void Overlay::
487  std::queue<Halfedge*> &q,
488  std::queue<Halfedge*> &q_rdg,
489  std::queue<Halfedge*> &q_crn) {
490  // If the edge or its opposite has been marked, then skip.
491  if ( acc.marked( h)) return;
492 
493  // First, determine feature rank of origin and destination vertices.
494  int frank_org = acc.is_on_feature( h->origin());
495  if ( frank_org) frank_org += acc.is_feature_0( ( h->origin()));
496 
497  if ( frank_org != 2) { // Consider feature type of green parent.
498  Parent_type pt = v->parent_type(GREEN);
499  Halfedge *g = v->halfedge(GREEN);
500  if ( pt == PARENT_VERTEX) {
501  Vertex *gv;
502  if ( acc.is_feature_0( gv=g->origin()))
503  frank_org = 2; // If mapped onto a corner, consider vertex as corner
504  else if ( frank_org == 0 && acc.is_on_feature( gv))
505  frank_org = 1;
506  }
507  else if ( frank_org==0 && pt==PARENT_EDGE && acc.is_feature_1( g)) {
508  frank_org = 1; // Ridge vertex
509  }
510  }
511 
512  int frank_dst = 0;
513  if ( frank_org) { // Determine type of destination vertex
514  frank_dst = acc.is_on_feature( ( h->destination()));
515  if ( frank_dst) frank_dst += acc.is_feature_0( h->destination());
516  }
517 
518  Halfedge *hopp = acc.get_opposite(h);
519  acc.mark( h);
520  if ( frank_org == 0 || frank_org < frank_dst || acc.is_border(hopp) ||
521  frank_dst != 2 && !acc.is_border(hopp) && acc.marked( hopp)) {
522  // If push edge into main queue, then mark both the edge and its opposite
523  q.push( h); acc.mark( hopp);
524  }
525  else if ( frank_org == 2 && !acc.is_border(hopp) && acc.marked( hopp)) {
526  // If I am a corner and the other edge is candidate, move into main queue
527  q.push( hopp);
528  }
529  else if ( frank_org == 1) {
530  // Otherwise, if frank_org is ridge, then push into ridge queue
531  q_rdg.push( h);
532  }
533  else {
534  // Otherwise frank_org is corner, don't push it.
535  q_crn.push(h);
536  }
537 }
538 
539 // Move an edge from ridge- or corner-queue into main queue.
540 // We use q_rdg to store edges that point from ridge vertices to
541 // non-feature vertices and use q_crn for edges from corner
542 // vertices to non-corner vertices. Move edge from q_rdg into
543 // q only if q is empty; and move edge from q_crn to q if both q
544 // and q_rdg are empty.
545 bool Overlay::
546 is_queue_empty( std::queue<Halfedge*> &q,
547  std::queue<Halfedge*> &q_rdg,
548  std::queue<Halfedge*> &q_crn) {
549  if ( !q.empty()) return false;
550 
551  for ( int i=0; i<2; ++i) {
552  std::queue<Halfedge*> &qbuf = (i==0) ? q_rdg : q_crn;
553  while ( !qbuf.empty()) {
554  Halfedge *h = qbuf.front(); qbuf.pop();
555  Halfedge *hopp = acc.get_opposite(h);
556  if ( !acc.marked( hopp)) {
557  q.push( h); acc.mark( acc.get_opposite(h));
558  return false;
559  }
560  }
561  }
562 
563  return true;
564 }
565 
566 // This is step 1 of the overlay algorithm. It projects the blue vertices
567 // and computes the intersections of the blue edges with the green
568 // edges. These intersections are stored in the lists associated with
569 // with the blue edges.
570 // At input, x is an inode corresponding to a blue vertex.
571 void Overlay::
573  // Precondition: None of the blue halfedges is marked.
574  std::queue<Halfedge*> q, q_rdg, q_crn;
575 
576 for ( int ncomp=1; ;++ncomp) { // Top loop over connected components.
577  INode *seed = overlay_init();
578  if ( seed==NULL) return; // If all halfedges are marked, then stop.
580  Halfedge *b = seed->halfedge( BLUE), *h=b;
581 
582  if ( verbose) {
583  if ( ncomp>1)
584  std::cout << "There appear to be multiple connected components "
585  << "in the input mesh.\n\tWorking on component "
586  << ncomp << std::endl;
587  else
588  std::cout << "\nThe input meshes have "
589  << ( is_opposite ? "opposite orientations" :
590  "the same orientation") << std::endl;
591 
592  std::cout << "Starting with seed vertex "
593  << acc.get_pane(b)->get_index(b->origin())+1
594  << " in pane " << acc.get_pane(b)->id() << " of blue mesh at "
595  << b->origin()->point() << std::endl;
596  }
597 
598  // Embed the seed into the blue vertex, (and the green vertex if its
599  // green parent is a vertex.)
600  insert_node_in_blue_edge( *seed, seed->halfedge(BLUE));
601  do {
602  insert_edge_into_queue( h, seed, q, q_rdg, q_crn);
603  } while ( (h = acc.get_next_around_origin(h)) != b);
604 
605  while ( !is_queue_empty( q, q_rdg, q_crn)) {
606  Halfedge *b = q.front(); q.pop();
607  Halfedge *bopp=acc.get_opposite(b);
608 
609  INode_list &il = acc.get_inode_list( b);
610  INode *x = acc.get_inode( acc.get_origin(b));
611  Vertex *dst = acc.get_destination(b);
612  INode *idst= acc.get_inode( dst);
613 
614  bool is_feature = acc.get_pane(b)->is_feature_1( b);
615  bool is_border = acc.is_border(b) || acc.is_border( acc.get_opposite(b));
616  bool is_dst_feature = is_feature || acc.is_on_feature( dst);
617  bool is_dst_border = is_border || acc.is_border( dst);
618 
619  // This is to snap open-ends of features.
620  const Real tol_snap_fea = 0.2, tol_snap_border = 2./3.;
621  Real cb=0, cg;
622 
623  for (;;) {
624  if (x->parent_type( BLUE)==PARENT_VERTEX &&
625  acc.get_origin(x->halfedge( BLUE))==dst ||
626  idst && get_edge_parent(*x,*idst,GREEN)!=Host_face(NULL,PARENT_NONE))
627  break; // The last two inodes on the edge are adjacent
628 
629  Halfedge *g1, *g0, *g2;
630  Parent_type t1, t0, t2;
631 
632  if ( il.empty()) {
633  INode *iorg = acc.get_inode( acc.get_origin(b));
634  g1 = iorg->halfedge( GREEN); t1 = iorg->parent_type( GREEN);
635  g0 = NULL; t0 = PARENT_NONE;
636  }
637  else {
638  INode_list::iterator it=--il.end();
639  g1 = it->halfedge( GREEN); t1 = it->parent_type( GREEN);
640  if ( it==il.begin()) {
641  INode *iorg = acc.get_inode( acc.get_origin(b));
642  g0 = iorg->halfedge( GREEN); t0 = iorg->parent_type( GREEN);
643  }
644  else {
645  --it; g0 = it->halfedge( GREEN); t0 = it->parent_type( GREEN);
646  }
647  }
648 
649  // Compute the intersection of b with the edges in the link
650  // of <g1,t1> but not in the star of <g0, t0>.
651  Real start = cb;
652  intersect_link( x, b, g0, t0, g1, t1, start, &cb, &cg, &g2, &t2);
653 
654  // If current edge is a ridge edge, then attempt to snap it onto ridge.
655  if ( is_feature && cb < 1 && cb > 0) {
656  op.snap_blue_ridge_edge( b, g2, &cb, &cg, &t2,
657  is_border ? tol_snap_border : tol_snap_fea);
658  }
659  else if ( !is_feature && cb < 1 &&
660  ( is_dst_feature && cb>1-tol_snap_fea &&
661  (t2 == PARENT_VERTEX && acc.is_on_feature(g2->origin()) ||
662  t2 == PARENT_EDGE && acc.is_feature_1(g2)) ||
663  is_dst_feature && cb>1-tol_snap_border &&
664  (t2 == PARENT_VERTEX && acc.is_border(g2->origin()) ||
665  t2 == PARENT_EDGE && acc.is_border(g2)))) {
666  // Enforce snapping vertex onto feature/border
667  cb = 1 + tol_snap_fea;
668  t2 = PARENT_EDGE;
669  }
670 
671  Point_2 nc(cg,0.);
672  RFC_assertion( t2 != PARENT_NONE);
673  if ( cb > 1) { // If intersects beyond the end point, do projection.
675  bool onto=op.project_onto_element( dst->point(),&g2,&t2,
676  Vector_3(0,0,0), &nc, eps_e, 0.2);
677  RFC_assertion( onto);
678  }
679 
680  if ( is_dst_feature && t2 != PARENT_VERTEX && cb>=1) {
681  op.snap_blue_ridge_vertex( dst, &g2, &t2, &nc, is_dst_border ?
682  tol_snap_border : tol_snap_fea);
683  }
684 
685  // Create an inode for the intersection point.
686  x = new INode();
687  if ( cb < 1)
688  x->set_parent( b, Point_2( cb, 0), BLUE);
689  else
690  x->set_parent( bopp, Point_2(0,0), BLUE);
691 
692  if ( nc[0] == 1.) {
693  nc[0] = 0;
694  g2 = !acc.is_border( g2) ? g2->next() : acc.get_opposite(g2);
695  }
696 
697  static int count=0, countmax = 10;
698  if ( verbose && count < countmax) {
699  if ( acc.is_border( dst) && cb>=1 && acc.get_inode( dst)==NULL &&
700  !( t2 == PARENT_EDGE && acc.is_border(acc.get_opposite(g2)) ||
701  t2 == PARENT_VERTEX && acc.is_border(g2->origin()))) {
702  if ( count == 0) std::cerr << std::endl;
703  std::cerr << "WARNING: Blue border vertex " << b->destination()->point()
704  << " is not matched with green boundary" << std::endl;
705  ++count;
706  }
707  else if ( is_border && cb>0 && cb<1 &&
708  !( t2 == PARENT_EDGE && acc.is_border(acc.get_opposite(g2)) ||
709  t2 == PARENT_VERTEX && acc.is_border(g2->origin()))) {
710 
711  if ( count == 0) std::cerr << std::endl;
712  std::cerr << "WARNING: Blue border edge " << b->origin()->point()
713  << b->destination()->point()
714  << " is not matched with green boundary " << std::endl;
715  ++count;
716  }
717 
718  if ( is_dst_feature && cb>=1 && acc.get_inode( dst)==NULL &&
719  !( t2 == PARENT_EDGE && acc.get_pane(g2)->is_feature_1(g2) ||
720  t2 == PARENT_VERTEX && acc.is_on_feature(g2->origin()))) {
721  std::cerr << "WARNING: Blue ridge vertex " << b->destination()->point()
722  << " is not matched with green ridge. cb is " << cb
723  << " and nc is " << nc << std::endl;
724  ++count;
725  }
726  else if ( is_feature && cb<1 &&
727  !( t2 == PARENT_EDGE && acc.get_pane(g2)->is_feature_1(g2) ||
728  t2 == PARENT_VERTEX && acc.is_on_feature(g2->origin()))) {
729  std::cerr << "WARNING: Blue ridge edge " << b->origin()->point()
730  << b->destination()->point()
731  << " is not matched with green ridge. cb is " << cb
732  << " and nc is " << nc << std::endl;
733  ++count;
734  }
735  }
736 
737  x->set_parent( g2, nc, GREEN);
738 
739  insert_node_in_blue_edge( *x, b);
740  }
741 
742  // Copy inode from border edge into neighbor edge
743  if ( acc.is_border( b) && !il.empty()) {
744  INode_list &ilr = acc.get_inode_list( bopp);
745 
746  while ( !il.empty()) {
747  INode &i = il.front(); il.pop_front();
748  ilr.push_front( i);
749  i.set_parent( bopp, Point_2(1-i.nat_coor(BLUE)[0],0), BLUE);
750  }
751  }
752 
753  // Push unvisited incident halfedges of b->destination() into q.
754  Halfedge *h; h = acc.get_next(b);
755 
756  do {
757  // Push the edge into queue and mark it as nonzero.
758  insert_edge_into_queue( h, x, q, q_rdg, q_crn);
759  } while ( ( h = acc.get_next_around_origin( h)) != bopp);
760  }
761  } // end for
762 
763  // Unmark all the halfedges of B
764  B->unmark_alledges();
765 }
766 
767 // This is step 2 of the algorithm. It sorts the intersection points
768 // corresponding to each green edge and insert them into green edges
769 // in linear time.
770 void Overlay::
772  std::vector<RFC_Pane_overlay*> ps;
773  B->panes( ps);
774 
775  inodes.clear();
776  // Loop through all the panes of B to insert the inodes into a list
777  for ( std::vector<RFC_Pane_overlay*>::iterator
778  pit=ps.begin(); pit!=ps.end(); ++pit){
779  // Loop through the vertices.
780  for ( HDS::Vertex_iterator vit=(*pit)->hds().vertices_begin();
781  vit!=(*pit)->hds().vertices_end(); ++vit)
782  if ( vit->halfedge() && vit->halfedge()->destination() == &*vit
783  && acc.is_primary( &*vit)) {
784  INode *i = acc.get_inode( &*vit); RFC_assertion( i);
785  i->prev_link[GREEN]=i->next_link[GREEN]=NULL;
786  inodes.push_back( i);
787  }
788 
789  for ( HDS::Halfedge_iterator hit=(*pit)->hds().halfedges_begin();
790  hit!=(*pit)->hds().halfedges_end(); ++hit) {
791  INode_list &il = acc.get_inode_list( &*hit);
792  for ( INode_list::iterator it=il.begin(); it!=il.end(); ++it) {
793  INode *i = &*it; RFC_assertion( i);
794  i->prev_link[GREEN]=i->next_link[GREEN]=NULL;
795  inodes.push_back( i);
796  }
797  }
798  }
799 
800  int count = 1;
801  // Loop through all the panes of B
802  for ( std::vector<RFC_Pane_overlay*>::iterator
803  pit=ps.begin(); pit!=ps.end(); ++pit) {
804  // Loop through the real faces of each pane.
805  for ( HDS::Facet_iterator fit=(*pit)->hds().facets_begin();
806  fit!=(*pit)->hds().facets_end(); ++fit, ++count) {
807  // if ( !acc.is_master( &*fit)) continue;
808  Halfedge *b = acc.get_halfedge( &*fit), *h=b;
809  do {
811  if ( i) insert_node_in_green_edge( i, count);
812 
813  INode_list &il = acc.get_inode_list( h);
814  if ( !il.empty()) {
816  // Loop through the intersections on the edges
817  INode_list::iterator v = il.begin(), vend = il.end();
818  for ( ; v != vend; ++v)
819  insert_node_in_green_edge( &*v, count);
820  }
821  else {
823  if ( !ilr.empty()) {
824  INode_list::reverse_iterator vr=ilr.rbegin(),vrend=ilr.rend();
825  for ( ; vr != vrend; ++vr)
826  insert_node_in_green_edge(&*vr, count);
827  }
828  }
829  // Increment the iterator
830  } while ( (h = acc.get_next(h)) != b);
831  }
832  }
833 
834  // Loop through all the inodes
835  for (std::list<INode*>::iterator it=inodes.begin(); it!=inodes.end(); ++it) {
836  INode *i=*it;
837  if ( i->parent_type( GREEN) == PARENT_EDGE) {
839  if ( il.empty()) {
840  while ( i->prev_link[GREEN]) { i = i->prev_link[GREEN]; }
841 
842  for (;;) {
843  INode *j = i->next_link[GREEN];
844  il.push_back(*i);
845  if ( j) i=j; else break;
846  }
847  }
848  }
849  }
850 }
851 
852 // The helper for sort_on_green_edges. It inserts a node v into the green
853 // edge v->green_halfedge(). Tag is for marking the buffer. We assume
854 // that each green(blue) edge intersects a blue(green) face at most twice.
855 void Overlay::
857  switch ( v->parent_type( GREEN)) {
858  case PARENT_VERTEX: {
860  return;
861  }
862  case PARENT_EDGE: {
863  Halfedge *g = v->halfedge( GREEN), *gopp=acc.get_opposite(g);
864  if ( !acc.is_border(gopp) && g>gopp) {
865  g = gopp;
866  v->set_parent( gopp, Point_2( 1.-v->nat_coor(GREEN)[0],0.), GREEN);
867  }
868  INode *y = acc.get_buffered_inode( g, tag);
869 
870  if ( y ) {
871  INode *x = v;
872 
873  if ( y->nat_coor(GREEN)[0] > x->nat_coor(GREEN)[0]) {
874  RFC_assertion(x->next_link[GREEN] == NULL || x->next_link[GREEN] == y);
875  RFC_assertion(y->prev_link[GREEN] == NULL || y->prev_link[GREEN] == x);
876  x->next_link[GREEN] = y; y->prev_link[GREEN] = x;
877  }
878  else {
879  RFC_assertion(x->prev_link[GREEN] == NULL || x->prev_link[GREEN] == y);
880  RFC_assertion(y->next_link[GREEN] == NULL || y->next_link[GREEN] == x);
881  x->prev_link[GREEN] = y; y->next_link[GREEN] = x;
882  }
883  }
884  // Otherwise, store the node
885  else
886  acc.set_buffered_inode( g, tag, v);
887  }
888  case PARENT_FACE:
889  return;
890  default:
891  RFC_assertion(false);
892  }
893 }
894 
895 // This is step 3 of the algorithm. It computes the associates of the
896 // green vertices in B.
897 void Overlay::
899  std::vector<RFC_Pane_overlay*> ps;
900  B->panes( ps); // Process all the panes including extension panes.
901 
902  // Loop through all panes of B
903  for (std::vector<RFC_Pane_overlay*>::iterator
904  pit=ps.begin(); pit!=ps.end(); ++pit) {
905  // Loop through the core faces of each pane.
906  for ( HDS::Facet_iterator fit=(*pit)->hds().facets_begin();
907  fit!=(*pit)->hds().facets_end(); ++fit) {
908 
909  Halfedge *b = acc.get_halfedge( &*fit);
911  Halfedge *h=b;
912 
913  do {
915  if ( i && i->parent_type( GREEN)!=PARENT_FACE)
917 
918  INode_list &il = acc.get_inode_list( h);
919 
920  if ( ! il.empty()) {
921  // Loop through the intersections on the edges
922  INode_list::iterator v = il.begin(), vend = il.end();
923  for ( ; v != vend; ++v) project_adjacent_green_vertices( &*v, b);
924  }
925  else {
927  if ( !ilr.empty()) {
928  INode_list::reverse_iterator vr=ilr.rbegin(),vrend=ilr.rend();
929  for ( ; vr!=vrend; ++vr) project_adjacent_green_vertices(&*vr,b);
930  }
931  }
932  // Increment the iterator
933  } while ( (h = acc.get_next(h)) != b);
934  }
935  }
936 }
937 
939 void Overlay::
941  std::queue< INode*> q;
942 
943  // From every known subnode, projects its adjacent green vertices
944  // onto blue faces and creates new subnodes for the green vertices.
945  do {
946  Halfedge *g = i->halfedge(GREEN), *gopp, *g0=g;
947  Parent_type igp = i->parent_type( GREEN);
948  // Loop through all the incident halfedges.
949  do {
950  gopp = acc.get_opposite( g);
952 
953  INode_list &il = acc.get_inode_list( g);
954  INode_list &ilr = acc.get_inode_list( gopp);
955 
956  // If there is any subnode between i and dst, skip the edge.
957  if ( igp == PARENT_VERTEX) {
958  if (!il.empty() || !ilr.empty())
959  continue;
960  }
961  else if ( igp == PARENT_EDGE) {
962  INode *j;
963  if ( !il.empty()) {
964  if ( &il.back() != i) continue;
965  j = ( il.size() > 1 ? i->prev_link[GREEN] :
966  acc.get_inode( acc.get_origin( g)));
967  }
968  else {
969  if ( &ilr.front() != i) continue;
970  j = ( ilr.size() > 1 ? i->next_link[GREEN] :
971  acc.get_inode( acc.get_origin( g)));
972  }
973  if ( j && contains( b, PARENT_FACE,
974  j->halfedge( BLUE), j->parent_type( BLUE)))
975  continue;
976  }
977 
978  // If dst has already been projected, skip the edge.
979  INode *x=NULL;
980  if ( (x=acc.get_inode( dst)) != NULL) {
983  i->halfedge(BLUE), i->parent_type(BLUE)));
984  continue;
985  }
986 
987  // Determine whether the vertex projects onto the blue face, and if so,
988  // create a new subnode at it and insert the subnode into the queue.
989  Halfedge *b1 = b; Parent_type t=PARENT_FACE;
990  Point_2 nc;
991  const RFC_Pane_overlay *gpane = acc.get_pane(g);
992  Vector_3 v1 = gpane->get_normal( g, g->destination());
994  &b1, &t, v1, &nc, eps_p)) {
995  Vector_3 v2 = op.get_face_normal( b1, nc);
996  if (v2 != Vector_3(0,0,0)) v2 = v2 / std::sqrt( v2*v2);
997 
998  if ( logical_xor( is_opposite, v1 * v2 < 0.15)) continue;
999  RFC_assertion( nc[0] != 0. && nc[1] != 0.);
1000 
1001  x = new INode();
1002 
1003  x->set_parent( b1, nc, BLUE);
1004  x->set_parent( gopp, Point_2(0,0), GREEN);
1005  // Check whether consistency rules are satisfied
1006  if ( verify_inode( x)) {
1007  inodes.push_back( x);
1008  acc.set_inode( dst, x);
1009  q.push( x);
1010  }
1011  else
1012  delete x;
1013  }
1014  RFC_assertion( igp != PARENT_FACE); // Must have been projected.
1015  } while ( ( g = ( igp==PARENT_VERTEX ? acc.get_next(gopp) : gopp)) != g0);
1016  if ( !q.empty()) { i = q.front(); q.pop(); } else i = NULL;
1017  } while (i);
1018 
1019 }
1020 
1021 bool Overlay::
1024 
1025  Halfedge *g = i->halfedge(GREEN), *gopp, *g0=g;
1026  // Loop through all the incident halfedges.
1027  do {
1028  gopp = acc.get_opposite( g);
1029 
1030  INode_list &il = acc.get_inode_list( g);
1031  INode_list &ilr = acc.get_inode_list( gopp);
1032 
1033  // If there is any subnode between i and dst, skip the edge.
1034  INode *j;
1035  if ( !il.empty()) {
1036  if ( &il.back() != i) continue;
1037  j = ( il.size() > 1 ? i->prev_link[GREEN] :
1038  acc.get_inode( acc.get_origin( g)));
1039  }
1040  else if ( !ilr.empty()) {
1041  if ( &ilr.front() != i) continue;
1042  j = ( ilr.size() > 1 ? i->next_link[GREEN] :
1043  acc.get_inode( acc.get_origin( g)));
1044  }
1045  else
1046  j = acc.get_inode( acc.get_destination(g));
1047 
1048  if ( j && !contains( i->halfedge( BLUE), PARENT_FACE,
1049  j->halfedge( BLUE), j->parent_type( BLUE)))
1050  return false;
1051  } while ( ( g = acc.get_next(gopp)) != g0);
1052 
1053  return true;
1054 }
1055 
1056 // The return value indicates whether this call is conclusive.
1057 bool Overlay::
1059  Halfedge *g2,
1060  Real start,
1061  Real *cb,
1062  Real *cg,
1063  Halfedge **g,
1064  Parent_type *t,
1065  bool *found,
1066  int snapcode,
1067  const Vertex *anchor, bool panic) {
1068  RFC_assertion( !g2->is_border());
1069 
1070  Real tcb, tcg; // Parameterization of intersection on b and g2
1071  Real orient_match; // To what degree [0..1] b and g2 are counterclockwise
1072  Real normal_match; // To what degree [0..1] the intersection have same normal
1073 
1074  // Tolerance for normal matching
1075  const Real tol_nm_large = 0.6, tol_nm_small=0.3; // about 50 and 80 degrees
1076  const Real tol_nm = panic ? tol_nm_small : tol_nm_large;
1077  const Real tol_proj=0.5, tol_snap=0.2;
1078 
1079  bool do_intersect = op.intersect( b, g2, start, &tcb, &tcg, &orient_match,
1080  &normal_match, is_opposite, eps_e);
1081  do_intersect &= (normal_match >= tol_nm);
1082 
1083  if ( verbose && panic) {
1084  std::cerr << "INFO: Intersection with green edge ("
1085  << g2->origin()->point() << "," << g2->destination()->point()
1086  << ") is at bparam=" << tcb << ", gparam=" << tcg << std::endl;
1087 
1088  if ( tcb<HUGE_VAL) {
1089  std::cerr << "\t inner product of normals equal to "
1090  << normal_match << std::endl;
1091 
1092  if ( normal_match<tol_nm_large) {
1093  std::cerr << "WARNING: Intersection was rejected due to normal mismatch under tolerance "
1094  << tol_nm_large << std::endl;
1095 
1096  if ( normal_match > tol_nm_small) {
1097  std::cerr << "WARNING: Trying with reduced normal-matching tolerance of "
1098  << tol_nm_small << std::endl;
1099  }
1100  }
1101  }
1102  }
1103 
1104  if ( do_intersect && tcb == 0) {
1105  // Inconsistency detected. It has backfired!
1106  // Or we need to snap to feature edge if nothing else works.
1107  *cb = 0.; *g = g2; *cg = tcg; *found=false;
1108  *t = ( tcg==0 || tcg==1) ? PARENT_VERTEX : PARENT_EDGE;
1109 
1110  return true;
1111  }
1112 
1113  if ( (tcb*eps_e > 1.) || orient_match < -eps_p ||
1114  normal_match < tol_nm || tcb<0.) {
1115  if ( *cb == HUGE_VAL) *g = g2; // Keep a record of the last intersection.
1116 
1117  // Do not treat it as fatal inconsistency because this might
1118  // happen at locations with large curvature and trying to repair it
1119  // can fail the algorithm. Instead, we simply ignore this intersection.
1120  return false;
1121  }
1122 
1123  if ( verbose && snapcode == 7 && tcg > tol_snap && tcg < 1-tol_snap ) {
1124  std::cerr << "WARNING: Blue edge (" << b->origin()->point()
1125  << ", " << b->destination()->point()
1126  << " appears to walk over a green corner "
1127  << g2->prev()->origin()->point()
1128  << " in an ambiguous way. This may cause overlay to failure. "
1129  << std::endl;
1130  }
1131 
1132  if ( do_intersect) {
1133  bool case1;
1134  if ( ( case1 = tcg == 1. || snapcode==6 || snapcode==7 &&
1135  op.normalmatch(b, g2->next()) > op.normalmatch( b, g2->prev())) ||
1136  tcg == 0. || snapcode==5 || snapcode==7 &&
1137  op.normalmatch(b, g2->next()) < op.normalmatch( b, g2->prev()) ||
1138  ( case1 = *found && tcg>0.5 &&
1139  contains( *g, *t, acc.get_next(g2), PARENT_VERTEX)) ||
1140  *found && tcg<0.5 && contains( *g, *t, g2, PARENT_VERTEX)) {
1141  *g = case1 ? acc.get_next(g2) : g2; *t = PARENT_VERTEX; *cg = 0.;
1142  if ( *found && *cb >1 && *cb < 1+tol_proj || tcb == 1) *cb = 1;
1143  else if ( !*found || tcb < *cb) *cb = tcb;
1144 
1145  *found = true;
1146  }
1147  else if ( !*found || !snapcode && tcb < *cb ||
1148  snapcode && std::abs(0.5-tcg)>std::abs(0.5-*cg))
1149  { *g = g2; *t = PARENT_EDGE; *cg = tcg; *cb = tcb; *found = true; }
1150  }
1151  else if ( tcg >=0. && tcg <= 1.) {
1152  RFC_assertion( tcb > 1.); // Otherwise, they would have intersected.
1153 
1154  bool case1;
1155  if ( ( case1 = tcg == 1. || snapcode==6 || snapcode==7 &&
1156  op.normalmatch(b, g2->next()) > op.normalmatch( b, g2->prev())) ||
1157  tcg == 0. || snapcode==5 || snapcode==7 &&
1158  op.normalmatch(b, g2->next()) < op.normalmatch( b, g2->prev()) ||
1159  *found && *t != PARENT_VERTEX && g2->facet()!=(*g)->facet() &&
1160  ( ( case1 = tcg>0.5 && contains( *g, *t, acc.get_next(g2), PARENT_VERTEX)) ||
1161  tcg<0.5 && contains( *g, *t, g2, PARENT_VERTEX))) {
1162 
1163  if ( *found && *cb <= 1)
1164  { *g = case1 ? g2->next() : g2; *t = PARENT_VERTEX; *cg = 0.; *cb = 1; }
1165  else if ( case1) {
1166  *g = g2->next(); *cg = 0;
1167  *t = (acc.get_destination( *g) == anchor) ? PARENT_EDGE : PARENT_FACE;
1168 
1169  if ( !*found || tcb < *cb) *cb = tcb;
1170  }
1171  else {
1172  *g = g2->prev(); *cg = 1.;
1173  *t = (acc.get_origin( *g) == anchor) ? PARENT_EDGE : PARENT_FACE;
1174 
1175  if ( !*found || tcb < *cb) *cb = tcb;
1176  }
1177 
1178  *found = true;
1179  }
1180  else if ( !*found || !snapcode && tcb < *cb ||
1181  snapcode && std::abs(0.5-tcg)>std::abs(0.5-*cg))
1182  { *cg = tcg; *g = g2; *t = PARENT_FACE; *cb = tcb; *found = true; }
1183  }
1184  else if ( !*found && tcb>=0) {
1185  bool case1;
1186  if ( *cb > 0 && *cb < HUGE_VAL &&
1187  *t != PARENT_VERTEX && g2->facet() != (*g)->facet() &&
1188  ( ( case1 = tcg>0.5 && contains( *g, *t, acc.get_next(g2), PARENT_VERTEX)) ||
1189  tcg<0.5 && contains( *g, *t, g2, PARENT_VERTEX))) {
1190 
1191  if ( tcb > 1 && *cb >1) {
1192  *g = case1 ? g2->next() : g2->prev(); *t = PARENT_EDGE; *cg = case1 ? 0. : 1.;
1193  if ( tcb < *cb) *cb = tcb;
1194  }
1195  else {
1196  *g = case1 ? acc.get_next(g2) : g2; *t = PARENT_VERTEX; *cg = 0.;
1197  if ( tcb ==1 || tcb >1 && tcb < 1+tol_proj && *cb < 1 ||
1198  tcb<=1 && *cb > 1 && *cb < 1+tol_proj)
1199  *cb = 1;
1200  else if ( tcb < *cb) *cb = tcb;
1201  }
1202  }
1203  else if ( *cb == HUGE_VAL ||
1204  *cg < tcg && tcg < 0 || *cg > tcg && tcg > 1) {
1205  // NOTE: cg is not used outside intersect_link if *cb>1, but we
1206  // need to keep the value of tcg for later comparisons
1207  if ( tcg <0 && tcb>1 && acc.get_origin( g2->prev()) == anchor)
1208  { *g = g2->prev(); *t = PARENT_EDGE; }
1209  else if ( tcg>1 && tcb>1 && acc.get_destination( g2->next()) == anchor)
1210  { *g = g2->next(); *t = PARENT_EDGE; }
1211  else
1212  { *g = g2; *t = PARENT_FACE; }
1213 
1214  *cb = tcb; *cg = tcg;
1215  }
1216  }
1217 
1218  return false;
1219 }
1220 
1221 // The return value indicates whether this call is conclusive.
1222 bool Overlay::
1224  Real *cg,
1225  Halfedge **g,
1226  Parent_type *t) {
1227  if ( *cb > 1.) {
1228  if ( *cg>1) { *cg = 1; } else if ( *cg <0) { *cg = 0.; }
1229  return true; // Preserve the parent-type.
1230  }
1231  else {
1232  // Otherwise, there is an inconsistency.
1233  if ( *cb <=0.) *cb = 0.;
1234 
1235  if ( *cg > 0. && *cg < 1.){ *t = PARENT_EDGE; }
1236  else if ( *cg >= 1.)
1237  { *g = acc.get_next(*g); *t = PARENT_VERTEX; *cg = 0.; }
1238  else if ( *cg <= 0.)
1239  { *t = PARENT_VERTEX; *cg = 0.; }
1240  return false;
1241  }
1242 }
1243 
1244 // This function computes the intersection of a halfedge b
1245 // with the edges in Lk( g1,t1)-Lk( (g0,t0),(g1,t1)).
1246 // It takes O(n) time, where n is the number of incident
1247 // edges of the green_parent of (g1,t1). It returns the intersection
1248 // point on both b and g, and the parent of the intersection.
1249 // This subroutine is used in intersect_blue_with_green.
1250 bool Overlay::
1252  const Halfedge *b,
1253  const Halfedge *g0,
1254  const Parent_type t0,
1255  Halfedge *g1,
1256  const Parent_type t1,
1257  Real start,
1258  Real *cb,
1259  Real *cg,
1260  Halfedge **g,
1261  Parent_type *t, int trytime) {
1262 
1263  bool found = false, is_feature = acc.is_feature_1(b);
1264  bool is_border= acc.is_border(b) || acc.is_border(acc.get_opposite(b));
1265  *cb = *cg = HUGE_VAL;
1266  *g = NULL;
1267 
1268  switch ( t1) {
1269  case PARENT_FACE: {
1270  RFC_assertion( !g1->is_border());
1271  // Loop through the edges of the face
1272  Halfedge *g2 = g1;
1273  do {
1274  int snapcode = is_feature ? 4 : 0;
1275 
1276  if ( intersect_link_helper( b, g2, start, cb, cg, g, t, &found,
1277  snapcode, NULL, trytime)) {
1278  if ( found) return true;
1279  else return intersect_link_helper2( cb, cg, g, t);
1280  }
1281  } while ( ( g2 = g2->next()) != g1);
1282 
1283  break;
1284  }
1285  case PARENT_EDGE: {
1286  Halfedge *g1_0=g1;
1287 
1288  // if g1 intersects b from left to right
1289  do {
1290  if ( g1->is_border() || contains( g1, PARENT_FACE, g0, t0)) continue;
1291  Halfedge *g2 = g1->next();
1292 
1293  do {
1294  int snapcode = 0;
1295  if (is_feature) {
1296  snapcode = 4;
1297  if ( is_border && acc.is_border( acc.get_opposite(g1)) ||
1298  !is_border && acc.is_feature_1( g1)) {
1299  if ( g2->prev()==g1) snapcode += 1;
1300  else if (g2->next()==g1) snapcode += 2;
1301  }
1302  }
1303 
1304  if ( intersect_link_helper( b, g2, start, cb, cg, g, t, &found,
1305  snapcode, NULL, trytime)) {
1306  if ( found) return true;
1307  else return intersect_link_helper2( cb, cg, g, t);
1308  }
1309  } while ( ( g2 = g2->next()) != g1);
1310  } while ( ( g1 = acc.get_opposite(g1)) != g1_0);
1311 
1312  break;
1313  }
1314  case PARENT_VERTEX: {
1315  Halfedge *g1_0=g1, *g1_1;
1316  Vertex *v = acc.get_origin(g1);
1317 
1318  do {
1319  g1_1 = acc.get_prev(g1);
1320  if ( g1->is_border() || contains( g1, PARENT_FACE, g0, t0)) continue;
1321  Halfedge *g2 = g1->next();
1322  do {
1323  int snapcode = 0;
1324  if (is_feature) {
1325  snapcode = 4;
1326 
1327  if ( is_border && acc.is_border( acc.get_opposite(g2->prev())) ||
1328  !is_border && acc.is_feature_1( g2->prev()) &&
1329  contains(g2->prev(), PARENT_EDGE, g1, PARENT_VERTEX))
1330  snapcode += 1;
1331  if ( is_border && acc.is_border( acc.get_opposite(g2->next())) ||
1332  !is_border && acc.is_feature_1( g2->next()) &&
1333  contains(g2->next(), PARENT_EDGE, g1, PARENT_VERTEX))
1334  snapcode += 2;
1335  }
1336 
1337  if ( intersect_link_helper( b, g2, start, cb, cg, g, t, &found,
1338  snapcode, v, trytime)) {
1339  if ( found) return true;
1340  else return intersect_link_helper2( cb, cg, g, t);
1341  }
1342  } while ( ( g2 = g2->next()) != g1_1);
1343  } while ( ( g1 = acc.get_opposite(g1_1)) != g1_0);
1344 
1345  break;
1346  }
1347  default:
1348  RFC_assertion( false);
1349  break;
1350  }
1351 
1352  if (found) return true;
1353  if ( *cb < HUGE_VAL) return intersect_link_helper2( cb, cg, g, t);
1354 
1355  if ( trytime==0) {
1356  // Print out error messages
1357  std::cerr << "WARNING: Encountered inconsistency when intersecting blue edge ("
1358  << acc.get_pane(b)->get_index(b->origin())+1 << ","
1359  << acc.get_pane(b)->get_index(b->destination())+1 << ") in pane "
1360  << acc.get_pane(b)->id() << " at \n\t("
1361  << b->origin()->point() << "), (" << b->destination()->point()
1362  << ") \nwith the link of the ";
1363  if ( t1 == PARENT_FACE) std::cerr << "green face incident on";
1364  if ( t1 == PARENT_EDGE) std::cerr << "green";
1365  if ( t1 == PARENT_VERTEX) std::cerr << "source vertex of green";
1366  std::cerr << " halfedge (" << acc.get_pane(g1)->get_index(g1->origin())+1
1367  << "," << acc.get_pane(g1)->get_index(g1->destination())+1
1368  << ") in pane " << acc.get_pane(g1)->id() << " at \n\t("
1369  << g1->origin()->point() << "), ("
1370  << g1->destination()->point() << ")." << std::endl;
1371 
1372  // One more try with print info
1373  intersect_link( x, b, g0, t0, g1, t1, start, cb, cg, g, t, 1);
1374 
1375  if ( *cb < HUGE_VAL) {
1376  std::cerr << "WARNING: Input meshes appear to have severe normal mismatch." << std::endl;
1377  std::cerr << "WARNING: Trying to continue with relaxed normal matching.\n\n" << std::endl;
1378  }
1379  else {
1380  // Continue with projecting onto face
1381  *cb = HUGE_VAL; *cg = HUGE_VAL; *t = PARENT_FACE;
1382  if ( *g == NULL || t1==PARENT_VERTEX) *g = g1;
1383  std::cerr << "WARNING: Could not find edge intersection." << std::endl;
1384  std::cerr << "WARNING: Trying to recover with point projection.\n\n" << std::endl;
1385  }
1386  }
1387 
1388  return false;
1389 }
1390 
1391 // Determining the parent of a directed sub-edge between two inodes.
1394  const INode &i1,
1395  const int color) const {
1396  Halfedge *h0 = i0.halfedge( color);
1397  Halfedge *h1 = i1.halfedge( color);
1398 
1399  Parent_type t0 = i0.parent_type( color);
1400  Parent_type t1 = i1.parent_type( color);
1401 
1402  if ( t1 == PARENT_FACE) {
1403  if ( !acc.is_border( h1) && contains( h1, PARENT_FACE, h0, t0))
1404  return Host_face( h1, PARENT_FACE);
1405  else
1406  return Host_face( NULL, PARENT_NONE);
1407  }
1408 
1409  switch ( t0) {
1410  case PARENT_VERTEX: {
1411  Halfedge *h = h0;
1412  // First check whether they lie on the same edge
1413  do {
1414  if ( t1 == PARENT_EDGE && (h == h1 || acc.get_opposite(h) == h1) ||
1415  t1 == PARENT_VERTEX && acc.get_destination(h)==acc.get_origin(h1)) {
1416  return Host_face( h, PARENT_EDGE);
1417  }
1418  RFC_assertion( t1 != PARENT_VERTEX ||
1419  acc.get_origin(h0) != acc.get_origin(h1));
1420  } while ( (h=acc.get_next_around_origin(h)) != h0);
1421  // If not, check whether they lie on the same face
1422  do {
1423  if ( !acc.is_border( h) && contains(h, PARENT_FACE, h1, t1))
1424  return Host_face( h, PARENT_FACE);
1425  } while ( (h=acc.get_next_around_origin(h)) != h0);
1426  break;
1427  }
1428  case PARENT_EDGE: {
1429  Halfedge *hopp=acc.get_opposite(h0);
1430  if ( t1 == PARENT_EDGE && ( h0 == h1 || hopp == h1)) {
1431  Real nc0=i0.nat_coor( color)[0], nc1=i1.nat_coor( color)[0];
1432  if ( h0 == h1 && nc0<nc1 || hopp == h1 && 1.-nc0<nc1)
1433  return Host_face( h0, PARENT_EDGE);
1434  else
1435  return Host_face( hopp, PARENT_EDGE);
1436  }
1437  if ( t1 == PARENT_VERTEX) {
1438  if (acc.get_destination(h0) == acc.get_origin(h1))
1439  return Host_face( h0, PARENT_EDGE);
1440  else if (acc.get_origin(h0) == acc.get_origin(h1))
1441  return Host_face( hopp, PARENT_EDGE);
1442  }
1443  if ( ! acc.is_border(h0) && contains( h0, PARENT_FACE, h1, t1))
1444  return Host_face( h0, PARENT_FACE);
1445  if ( ! acc.is_border(hopp) && contains( hopp, PARENT_FACE, h1, t1))
1446  return Host_face( hopp, PARENT_FACE);
1447  break;
1448  }
1449  case PARENT_FACE: {
1450  RFC_assertion( ! acc.is_border(h0));
1451  if ( contains(h0, PARENT_FACE, h1, t1))
1452  return Host_face(h0, PARENT_FACE);
1453  break;
1454  }
1455  default:
1456  RFC_assertion( false);
1457  break;
1458  }
1459  return Host_face( NULL, PARENT_NONE);
1460 }
1461 
1462 // Determines the parents for a halfedge and its opposite.
1465  const INode &i1,
1466  const int color) const {
1467  Host_face f = get_edge_parent( i0, i1, color);
1468  Halfedge *g = f.halfedge();
1469  RFC_assertion( !acc.is_border(g));
1470 
1471  // There are two cases for f:
1472  // 1. g is not a border edge and the parent type is PARENT_FACE
1473  // 2. g is not a border edge and the parent type is PARENT_EDGE
1474 
1475  switch ( f.parent_type()) {
1476  case PARENT_FACE:
1477  return std::make_pair( g, g);
1478  case PARENT_EDGE:
1479  return std::make_pair( g, acc.get_opposite(g));
1480  default:
1481  RFC_assertion( false);
1482  return std::make_pair( (Halfedge*)NULL, (Halfedge*)NULL);
1483  }
1484 }
1485 
1486 // Checking whether an object <e1,t1> contains another object <e2,t2>.
1487 bool
1489  const Halfedge *e2, const Parent_type t2) const {
1490  RFC_precondition( e1!=NULL);
1491  if ( e2 == NULL) return false;
1492 
1493  switch ( t1) {
1494  case PARENT_FACE: {
1495  const Facet *f1=acc.get_facet(e1);
1496  RFC_assertion( f1!=NULL);
1497  switch( t2) {
1498  case PARENT_FACE: {
1499  RFC_assertion( acc.get_facet(e2));
1500  return f1 == acc.get_facet(e2);
1501  }
1502  case PARENT_EDGE: {
1503  return f1 == acc.get_facet(e2) ||
1504  f1 == acc.get_facet( acc.get_opposite(e2));
1505  }
1506  case PARENT_VERTEX: {
1507  // Is true if any edge have acc.get_origin(e2) as an endpoint.
1508  const Vertex *v2=acc.get_origin(e2);
1509  const Halfedge *h = e1;
1510  do {
1511  if ( acc.get_destination(h) == v2) return true;
1512  } while ( ( h = acc.get_next(h)) != e1);
1513  break;
1514  }
1515  default:
1516  RFC_assertion( false);
1517  break;
1518  }
1519  break;
1520  }
1521  case PARENT_EDGE:
1522  if ( t2 == PARENT_EDGE)
1523  return ( e1 == e2 || e1 == acc.get_opposite(e2));
1524  else if ( t2 == PARENT_VERTEX) {
1525  const Vertex *v2=acc.get_origin(e2);
1526  return acc.get_origin(e1) == v2 || acc.get_destination(e1) == v2;
1527  }
1528  break;
1529  case PARENT_VERTEX:
1530  return t2 == PARENT_VERTEX && acc.get_origin(e1) == acc.get_origin(e2);
1531  default:
1532  RFC_assertion( false);
1533  break;
1534  }
1535  return false;
1536 }
1537 
1538 //=========== Subroutines for outputting the intermediate results
1539 // Write out all the inodes in Tecplot format.
1540 void Overlay::
1541 write_inodes_tec(std::ostream &os, const char *color) {
1542  set_ascii_mode(os);
1543 
1544  int n=0;
1545  std::list<INode*>::iterator it = inodes.begin(), iend = inodes.end();
1546  for ( ; it != iend; ++it,++n) {
1547  if ( n%50==0) {
1548  os << "GEOMETRY T=LINE3D";
1549  if ( color) os << " C=" << color;
1550  os << " LT=0.2" << std::endl;
1551  os << std::min(int(inodes.size()-n),int(50)) << std::endl;
1552  }
1553  INode *i = *it;
1554  os << 2 << ' ' << op.get_point( i->halfedge(BLUE), i->nat_coor( BLUE))
1555  << ' ' << op.get_point( i->halfedge(GREEN), i->nat_coor( GREEN))
1556  << std::endl;
1557  }
1558 }
1559 
1560 void Overlay::
1561 write_inodes_vec( std::ostream &os) {
1562  set_ascii_mode(os);
1563 
1564  int n = inodes.size();
1565 
1566  os << "VECT\n";
1567  os << n << ' ' << n*2 << ' ' << 0 << '\n';
1568 
1569  int i;
1570  // Print the number of vertices in each inode
1571  for ( i=n; i>0; --i) os << 2 << '\n';
1572  for ( i=n; i>0; --i) os << 0 << '\n';
1573 
1574  // Print the coordinates of each node
1575  std::list<INode*>::iterator it = inodes.begin(), iend = inodes.end();
1576  for ( ; it != iend; ++it) {
1577  INode *i = *it;
1578  os << op.get_point( i->halfedge(BLUE), i->nat_coor( BLUE))
1579  << ' ' << op.get_point( i->halfedge(GREEN), i->nat_coor( GREEN))
1580  << std::endl;
1581  }
1582 }
1583 
1584 std::pair<const INode *, const Overlay::Halfedge*>
1585 Overlay::get_next_inode_ccw(const INode *v0, const INode *v1, int color) const
1586 {
1587  INode *v2=NULL;
1588  switch( v1->parent_type( color)) {
1589  case PARENT_FACE:
1590  // Rule 1: When making turns, it must be at an edge/vertex.
1591  return std::pair<const INode *, const Halfedge*>(NULL,NULL);
1592  case PARENT_EDGE: {
1593  Host_face hf = get_edge_parent( *v0, *v1, color);
1594  if ( hf.parent_type() == PARENT_EDGE) {
1595  // Rule 2: No three vertices on the same edge can be in the same subface.
1596  return std::pair<const INode *, const Halfedge*>(NULL,NULL);
1597  }
1598  else {
1600  // next inode is the next one along the edge
1601  Halfedge *h = v1->halfedge( color);
1602  if ( h->facet() != hf.halfedge()->facet()) {
1603  h = acc.get_opposite( h);
1604  RFC_assertion( h->facet() == hf.halfedge()->facet());
1605  }
1606 
1607  INode_list &il = acc.get_inode_list( h);
1608  if ( !il.empty()) {
1609  if ( v1 == &il.back())
1610  v2 = acc.get_inode(acc.get_destination( h));
1611  else
1612  v2 = v1->next_link[color];
1613  }
1614  else {
1616  RFC_assertion( !ilr.empty());
1617  if ( v1 == &ilr.front())
1618  v2 = acc.get_inode(acc.get_destination( h));
1619  else
1620  v2 = v1->prev_link[color];
1621  }
1622  RFC_assertion( v2);
1623  return std::pair<const INode*, const Halfedge*>(v2, h);
1624  }
1625  }
1626  case PARENT_VERTEX: {
1627  Host_face hf = get_edge_parent( *v0, *v1, color);
1628 
1629  Halfedge *h = v1->halfedge(color);
1630  while ( h->facet() != hf.halfedge()->facet()) {
1631  h = acc.get_next_around_origin( h);
1632  RFC_assertion( h != v1->halfedge(color));
1633  }
1634 
1635  INode_list &il = acc.get_inode_list( h);
1636  if ( !il.empty())
1637  v2 = &il.front();
1638  else {
1640  if ( !ilr.empty())
1641  v2 = &ilr.back();
1642  else
1643  v2 = acc.get_inode( acc.get_destination( h));
1644  }
1645  RFC_assertion( v2);
1646  return std::pair<const INode*, const Halfedge*>(v2, h);
1647  }
1648  default:
1649  RFC_assertion( false);
1650  return std::pair<const INode *, const Halfedge*>(NULL,NULL);
1651  }
1652 }
1653 
1654 std::pair<const INode *, const Overlay::Halfedge*>
1655 Overlay::get_next_inode_cw(const INode *v0, const INode *v1, int color) const
1656 {
1657  INode *v2=NULL;
1658  switch( v1->parent_type( color)) {
1659  case PARENT_FACE:
1660  // Rule 1: When making turns, it must be at an edge/vertex.
1661  return std::pair<const INode *, const Halfedge*>(NULL,NULL);
1662  case PARENT_EDGE: {
1663  Host_face hf = get_edge_parent( *v0, *v1, color);
1664  if ( hf.parent_type() == PARENT_EDGE) {
1665  // Rule 2: No three vertices on the same edge can be in the same subface.
1666  return std::pair<const INode *, const Halfedge*>(NULL,NULL);
1667  }
1668  else {
1670  // next inode is the next one along the edge
1671  Halfedge *h = v1->halfedge( color);
1672  if ( h->facet() != hf.halfedge()->facet()) {
1673  h = acc.get_opposite( h);
1674  RFC_assertion( h->facet() == hf.halfedge()->facet());
1675  }
1676 
1677  INode_list &il = acc.get_inode_list( h);
1678  if ( !il.empty()) {
1679  if ( v1 == &il.front())
1680  v2 = acc.get_inode(acc.get_origin( h));
1681  else
1682  v2 = v1->prev_link[color],h->prev();
1683  }
1684  else {
1686  RFC_assertion( !ilr.empty());
1687  if ( v1 == &ilr.back())
1688  v2 = acc.get_inode(acc.get_origin( h));
1689  else
1690  v2 = v1->next_link[color],h->prev();
1691  }
1692  return std::pair<const INode*, const Halfedge*>(v2, h);
1693  }
1694  }
1695  case PARENT_VERTEX: {
1696  Host_face hf = get_edge_parent( *v0, *v1, color);
1697 
1698  Halfedge *h = v1->halfedge(color);
1699  Halfedge *j = ( (hf.parent_type() == PARENT_EDGE) ?
1700  acc.get_opposite(hf.halfedge()) : hf.halfedge());
1701 
1702  while ( h->facet() != j->facet()) {
1703  h = acc.get_next_around_origin( h);
1704  RFC_assertion( h != v1->halfedge(color));
1705  }
1706  h = h->prev();
1707 
1708  INode *v2;
1709  INode_list &il = acc.get_inode_list( h);
1710  if ( !il.empty())
1711  v2 = &il.back();
1712  else {
1714  if ( !ilr.empty())
1715  v2 = &ilr.front();
1716  else
1717  v2 = acc.get_inode( acc.get_origin( h));
1718  }
1719  return std::pair<const INode*, const Halfedge*>(v2, h);
1720  }
1721  default:
1722  RFC_assertion( false);
1723  return std::pair<const INode *, const Halfedge*>(NULL,NULL);
1724  }
1725 }
1726 
1727 const INode *
1728 Overlay::get_next_inode( const INode *v0, const INode *v1, int color) const {
1729  // First, find the blue face that contain both inodes.
1730  std::pair<const INode*,const Halfedge*> b, g;
1731 
1732  b = get_next_inode_ccw( v0, v1, color);
1733  if ( !is_opposite)
1734  g = get_next_inode_ccw( v0, v1, !color);
1735  else
1736  g = get_next_inode_cw( v0, v1, !color);
1737 
1738  if ( g.first==NULL) return b.first;
1739  if ( b.first!=NULL) {
1740  const Host_face bf = get_edge_parent( *v1, *b.first, !color);
1741 
1742  if ( !acc.is_border( g.second) &&
1743  contains( g.second, PARENT_FACE, bf.halfedge(), bf.parent_type()))
1744  // If the blue one is contained in the green face, return the blue one
1745  return b.first;
1746  }
1747 
1748  return g.first;
1749 }
1750 
1751 // The following subroutine subdivides a given face into a number of
1752 // sub faces. The input face is given by a list of inodes in CCW order,
1753 // and the output subfaces are given by a list of faces, each of which
1754 // is represented by a vectors of inodes.
1755 // At input, the nodes in the face between face.begin() and
1756 // last_checked (inclusively) are known belong to the same sub-face.
1757 // Return true if the face is not closed.
1758 bool
1760  INode_const_list::const_iterator last_checked,
1761  Subface_list &sub_faces,
1762  int color, int depth) const {
1763  if ( face.size() < 3) return true; // Do nothing
1764  RFC_assertion( last_checked != face.begin() && last_checked != face.end() && depth < 1000);
1765 
1766  INode_const_list::const_iterator it=last_checked, iend=face.end(),inext;
1767  const INode *v0 = *(--last_checked), *v1 = *it, *v2;
1768  // v0 and v1 are the last pair of adjacent nodes that are known belonging
1769  // to the sub-face of previous nodes in the node list.
1770 
1771  for ( RFC_assertion_code(unsigned int c=0);;RFC_assertion(++c<face.size())) {
1772  inext = it; ++inext; // Equivalent to inext = it + 1;
1773  if ( inext == iend) { // All nodes in the list are processed.
1774  if ( face.front() == get_next_inode( v0, v1, color)) {
1775  // Insert a new item in the sub-face list.
1776  sub_faces.push_back( std::vector< const INode*>());
1777  std::vector< const INode*> &vec = sub_faces.back();
1778  vec.reserve( face.size());
1779  vec.insert( vec.end(),face.begin(), face.end());
1780  return false;
1781  }
1782  return true;
1783  }
1784  else {
1785  v2 = get_next_inode( v0, v1, color);
1786  if ( !v2) {
1787  INode_const_list sub2( it, face.end());
1788  subdivide( sub2, ++sub2.begin(), sub_faces, color, depth+1);
1789  return true;
1790  }
1791  v0 = v1; v1 = v2;
1792  if ( v2 != *inext) break; // the face is split at v2
1793 
1794  it = inext;
1795  }
1796  }
1797 
1798  // The sub-face is a proper subset of given face. We split it into two parts.
1799  // Create a binary tree structure for the nodes.
1800  typedef std::map< const INode *, INode_const_list::const_iterator> IMap;
1801  IMap imap;
1802  for ( INode_const_list::const_iterator i = face.begin(); i!=iend; ++i)
1803  imap.insert( std::make_pair( *i, i));
1804 
1805  IMap::const_iterator mit;
1806  // Create two sub lists
1807  std::list< const INode *> sub1, sub2;
1808  sub1.insert( sub1.end(), face.begin(), inext);
1809 
1810  // Find the end of the chain that cuts the face
1811  for ( RFC_assertion_code( int count=0);;RFC_assertion(++count<100)) {
1812  if ( (mit=imap.find( v1)) == imap.end()) {
1813  sub1.push_back( v1);
1814  sub2.push_front( v1);
1815  v2 = get_next_inode( v0, v1, color);
1816  if (v2) { v0=v1; v1 = v2; } else break;
1817  }
1818  else {
1819  break;
1820  }
1821  }
1822 
1823  bool ret1=true, ret2=true;
1824  // Cut the face along the inodes (*mit->second,sub2.front,...,sub2.end(),*it)
1825  INode_const_list::const_iterator sub_it1 = --sub1.end();
1826  if (v2 && mit->second != face.begin())
1827  { sub1.insert( sub1.end(), mit->second, iend); ++sub_it1; }
1828  if (v2) ret1 = subdivide( sub1, sub_it1, sub_faces, color, depth+1);
1829  sub1.clear();
1830 
1831  if ( v2) sub2.push_front( *mit->second);
1832  if ( v2 && mit->second != face.begin())
1833  { sub2.insert(sub2.end(),it,mit->second); }
1834  else
1835  { sub2.insert(sub2.end(),it,iend); }
1836  ret2 = subdivide( sub2, ++sub2.begin(), sub_faces, color, depth+1);
1837  return ret1 || ret2;
1838 }
1839 
1841 Overlay::get_parent_face( const Subface &sf, int color) {
1842  RFC_assertion( sf.size()>0);
1843 
1844  Host_face f = get_edge_parent( *sf[0], *sf[1], color);
1845  if ( !f.halfedge()->is_border() &&
1846  contains( f.halfedge(), PARENT_FACE,
1847  sf[2]->halfedge(color), sf[2]->parent_type(color)))
1848  return f.halfedge();
1849  else
1850  return acc.get_opposite(f.halfedge());
1851 }
1852 
1853 Point_2
1855  const Halfedge *h, int color) const {
1856  const Halfedge *hi = i.halfedge( color);
1857  Point_2 nc; i.nat_coor( color, nc);
1858 
1859  if ( hi->facet() != h->facet()) {
1860  switch ( i.parent_type( color)) {
1861  case PARENT_VERTEX: {
1862  const Vertex *v = acc.get_origin( hi);
1863  hi = h;
1864  while ( acc.get_origin( hi) != v)
1865  { hi = acc.get_next( hi); RFC_assertion( hi != h); }
1866  break;
1867  }
1868  case PARENT_EDGE: {
1869  const Halfedge *hj = acc.get_opposite( hi);
1870  if ( hj->facet() == h->facet()) {
1871  hi = hj; nc = Point_2( 1.-nc[0], 0.); break;
1872  }
1873  // Otherwise, it is in an extension edge and we treat it as a face.
1874  }
1875  default: {
1876  RFC_assertion( acc.is_border( hi));
1877 
1878  // In the extension region
1879  while ( acc.get_opposite( hi) != h)
1880  { hi = acc.get_next(hi); RFC_assertion( hi != i.halfedge(color)); }
1881 
1882  return Point_2(1.-get_nat_coor(i, Generic_element(4), hi, color)[0],0.);
1883  }
1884  }
1885  }
1886 
1887  switch( e.size_of_edges()) {
1888  case 3: {
1889  if ( hi == h)
1890  return nc;
1891  else if ( hi == h->prev()) {
1892  return Point_2( nc[1], 1.-nc[0]-nc[1]);
1893  }
1894  else {
1895  RFC_assertion( hi == h->next());
1896  return Point_2( 1.-nc[0]-nc[1], nc[0]);
1897  }
1898  }
1899  case 4: {
1900  if ( hi == h)
1901  return nc;
1902  else if ( hi == h->prev()) {
1903  return Point_2( nc[1], 1-nc[0]);
1904  }
1905  else if ( hi == h->next()) {
1906  return Point_2( 1-nc[1], nc[0]);
1907  }
1908  else {
1909  RFC_assertion( hi == h->next()->next());
1910  return Point_2( 1-nc[0], 1-nc[1]);
1911  }
1912  }
1913  default: {
1914  RFC_assertion( false);
1915  }
1916  }
1917  return Point_2(0,0);
1918 }
1919 
1920 // Construct a list of nodes for the blue face
1921 void
1923  INode_const_list &nodes) {
1924  const Halfedge *b = acc.get_halfedge(f);
1925  if ( acc.is_border(b)) {
1926  // Make sure the opposite of b is a border edge
1927  while ( !acc.get_opposite(b)->is_border()) b=acc.get_next(b);
1928  }
1929  const Halfedge *h=b;
1930  do {
1931  const INode *i=acc.get_inode( acc.get_origin(h));
1932  if ( i) nodes.push_back( i);
1933 
1934  const INode_list &il = acc.get_inode_list( h);
1935 
1936  if ( ! il.empty()) {
1937  // Loop through the intersections on the edges
1938  INode_list::const_iterator v = il.begin(), vend = il.end();
1939  for ( ; v != vend; ++v) nodes.push_back( &*v);
1940  }
1941  else {
1942  const INode_list &ilr = acc.get_inode_list( acc.get_opposite(h));
1943  if ( !ilr.empty()) {
1944  INode_list::const_reverse_iterator vr=ilr.rbegin(),vrend=ilr.rend();
1945  for ( ; vr!=vrend; ++vr) nodes.push_back(&*vr);
1946  }
1947  }
1948 
1949  // Increment the iterator
1950  } while ( (h = acc.get_next(h)) != b);
1951 
1952  return;
1953 }
1954 
1955 void
1956 Overlay::write_overlay_tec( std::ostream &os, const COM::Window *w) {
1957  int color = (w==B->base()) ? BLUE : GREEN;
1958  int num_faces=0;
1959  // Loop through all the original blue faces
1960  std::vector<RFC_Pane_overlay*> ps;
1961  if ( color==GREEN) G->panes( ps); else B->panes( ps);
1962  // Loop through all the panes of G
1963  for (std::vector<RFC_Pane_overlay*>::iterator
1964  pit=ps.begin(); pit != ps.end(); ++pit) {
1965  // Loop through the faces of each pane.
1966  for ( HDS::Facet_iterator fit=(*pit)->hds().facets_begin();
1967  fit!=(*pit)->hds().facets_end(); ++fit) {
1968 
1969  // Construct a list of nodes for the blue face
1970  INode_const_list nodes;
1971  get_inodes_of_face( &*fit, nodes);
1972  if ( nodes.size() <= 2) continue;
1973 
1974  Subface_list sub_faces;
1975  // subdivide the face
1976  RFC_assertion_code( bool ret = )
1977  subdivide( nodes, ++nodes.begin(), sub_faces, color);
1978  RFC_assertion( !ret);
1979 
1980  // output the subfaces of the blue face
1981  num_faces += sub_faces.size();
1982  Subface_list::iterator sfit = sub_faces.begin(), sfend=sub_faces.end();
1983  os << "GEOMETRY T=LINE3D C=BLACK"
1984  << " LT=0.15\n" << sub_faces.size() << std::endl;
1985  for ( ; sfit != sfend; ++sfit) {
1986  // Loop through the points in the sub face
1987  os << sfit->size()+1 << " ";
1988  for ( Subface_list::value_type::iterator
1989  vit=sfit->begin(); vit!=sfit->end(); ++vit) {
1990  os << op.get_point( (*vit)->halfedge( color),
1991  (*vit)->nat_coor( color))
1992  << std::endl;
1993  }
1994  os << op.get_point( (*sfit->begin())->halfedge( color),
1995  (*sfit->begin())->nat_coor( color))
1996  << std::endl;
1997  }
1998  }
1999  }
2000  if ( verbose)
2001  std::cout << "\tTotal number of sub-faces in the overlay is "
2002  << num_faces << std::endl;
2003 }
2004 
2005 void
2006 Overlay::write_overlay_off( std::ostream &os, const COM::Window *w) {
2007  int color = (w==B->base()) ? BLUE : GREEN;
2008  os << "OFF" << std::endl;
2009  set_ascii_mode(os);
2010 
2011  // Loop through all the original blue faces
2012  std::vector<RFC_Pane_overlay*> ps;
2013  if ( color==GREEN) G->panes( ps); else B->panes( ps);
2014 
2015  int nfaces = 0;
2016 
2017  // Loop through all the panes of the window to count the number of faces
2018  for (std::vector<RFC_Pane_overlay*>::iterator
2019  pit=ps.begin(); pit != ps.end(); ++pit) {
2020  // Loop through the faces of each pane.
2021  for ( HDS::Facet_iterator fit=(*pit)->hds().facets_begin();
2022  fit!=(*pit)->hds().facets_end(); ++fit) {
2023 
2024  // Construct a list of nodes for the blue face
2025  INode_const_list nodes;
2026  get_inodes_of_face( &*fit, nodes);
2027  if ( nodes.size() <= 2) continue;
2028 
2029  Subface_list sub_faces;
2030  // subdivide the face
2031  RFC_assertion_code( bool ret = )
2032  subdivide( nodes, ++nodes.begin(), sub_faces, color);
2033  RFC_assertion( !ret);
2034 
2035  // output the subfaces of the blue face
2036  nfaces += sub_faces.size();
2037  }
2038  }
2039 
2040  os << inodes.size() << ' ' << nfaces << " 0" << std::endl;
2041 
2042  // Assign ids for the vertices
2043  int id=0;
2044  std::map< const void*, int> ids;
2045  for ( std::list< INode*>::const_iterator
2046  i = inodes.begin(); i != inodes.end(); ++i) {
2047  os << op.get_point( (*i)->halfedge( color),
2048  (*i)->nat_coor( color))
2049  << std::endl;
2050  ids[*i] = id++;
2051  }
2052 
2053  // Loop through all the original blue faces
2054  for (std::vector<RFC_Pane_overlay*>::iterator
2055  pit=ps.begin(); pit != ps.end(); ++pit) {
2056  // Loop through the faces of each pane.
2057  for ( HDS::Facet_iterator fit=(*pit)->hds().facets_begin();
2058  fit!=(*pit)->hds().facets_end(); ++fit) {
2059 
2060  // Construct a list of nodes for the blue face
2061  INode_const_list nodes;
2062  get_inodes_of_face( &*fit, nodes);
2063  if ( nodes.size() <= 2) continue;
2064 
2065  Subface_list sub_faces;
2066  // subdivide the face
2067  RFC_assertion_code( bool ret = )
2068  subdivide( nodes, ++nodes.begin(), sub_faces, color);
2069  RFC_assertion( !ret);
2070 
2071  // output the subfaces of the blue face
2072  Subface_list::iterator sfit = sub_faces.begin(), sfend=sub_faces.end();
2073 
2074  for ( ; sfit != sfend; ++sfit) {
2075  // Loop through the points in the sub face
2076  os << sfit->size();
2077  for ( Subface_list::value_type::iterator
2078  vit=sfit->begin(); vit!=sfit->end(); ++vit) {
2079  os << " " << ids[*vit];
2080  }
2081  os << std::endl;
2082  }
2083  }
2084  }
2085 
2086  if ( verbose)
2087  std::cout << "\tTotal number of sub-faces in the overlay is "
2088  << nfaces << std::endl;
2089 }
2090 
2092 
2093 
2094 
2095 
2096 
2097 
std::string name() const
The name of the window.
void number_subnodes()
Definition: Overlay_IO.C:236
Vertex * get_origin(Halfedge *h) const
Definition: HDS_accessor.h:87
Halfedge * get_next(Halfedge *h) const
Definition: HDS_accessor.h:108
std::reverse_iterator< const_iterator > const_reverse_iterator
std::list< const INode * > INode_const_list
Definition: Overlay.h:63
const INode * get_next_inode(const INode *v1, const INode *v2, int) const
Definition: Overlay.C:1728
Parent_type parent_type(const int color) const
Definition: HDS_overlay.h:350
bool intersect(const Halfedge *b, const Halfedge *g, Real start, Real *c1, Real *c2, Real *dir, Real *dir_match, bool is_opposite, Real eps_e) const
std::pair< const Halfedge *, const Halfedge * > Parent_pair
Definition: Overlay.h:62
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
double xmax() const
Halfedge * get_prev(Halfedge *h) const
Definition: HDS_accessor.h:105
INode * get_buffered_inode(Halfedge *h, int tag) const
Definition: HDS_accessor.h:383
bool is_primary(const Vertex *v) const
Definition: HDS_accessor.h:187
Halfedge_overlay * halfedge() const
Definition: HDS_overlay.h:295
void number_subfaces()
Definition: Overlay_IO.C:281
Definition: face.h:90
Halfedge * get_opposite(Halfedge *h) const
Definition: HDS_accessor.h:99
Real eps_e
Definition: Overlay.h:291
void int int REAL REAL * y
Definition: read.cpp:74
void write_overlay_off(std::ostream &, const COM::Window *)
Definition: Overlay.C:2006
std::reverse_iterator< iterator > reverse_iterator
Vertex_overlay * destination()
Definition: HDS_overlay.h:137
#define COM_assertion_msg(EX, msg)
RFC_Pane_overlay * get_pane(Vertex *v) const
Definition: HDS_accessor.h:128
void project_adjacent_green_vertices(const INode *, Halfedge *)
Helper for associate_green_vertices().
Definition: Overlay.C:940
bool is_opposite
Definition: Overlay.h:286
Overlay(const COM::Window *w1, const COM::Window *w2, const char *pre)
Definition: Overlay.C:46
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
size_type size() const
INode * overlay_init()
Definition: Overlay_init.C:48
void write_inodes_tec(std::ostream &os, const char *color)
Definition: Overlay.C:1541
bool is_feature_1(const Halfedge *h) const
Definition: HDS_accessor.h:184
boolean empty(T_VertexSet s)
Halfedge * get_parent_face(const Subface &sf, int color)
Definition: Overlay.C:1841
bool marked(const Halfedge *h) const
Definition: HDS_accessor.h:299
bool do_intersect(const Line_2< R > &p1, const Line_2< R > &p2)
double Real
Definition: mapbasic.h:322
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
double xmin() const
double zmin() const
double sqrt(double d)
Definition: double.h:73
void push_back(T &x)
SURF::Generic_element_2 Generic_element
Definition: rfc_basic.h:46
bool is_border() const
Definition: HDS_overlay.h:131
INode * get_inode(Vertex *v) const
Definition: HDS_accessor.h:370
int overlay()
Definition: Overlay.C:73
const Color GREEN
Definition: Color.C:59
Real normalmatch(const Halfedge *b, const Halfedge *g) const
void push_front(T &x)
Host_face get_edge_parent(const INode &i0, const INode &i1, const int color) const
Definition: Overlay.C:1393
Vector_3 get_face_normal(const Halfedge *b, const Point_2 &nc, int scheme=0) const
void insert_node_in_green_edge(INode *v, int tag)
Definition: Overlay.C:856
Real eps_p
Definition: Overlay.h:292
Parent_type parent_type() const
Definition: HDS_overlay.h:297
void panes(std::vector< Pane * > &ps)
Get a vector of local panes contained in the window.
Halfedge * get_halfedge(Vertex *v) const
Definition: HDS_accessor.h:75
bool is_feature_0(const Vertex *v) const
Definition: HDS_accessor.h:179
A window is a collection of panes.
Vertex_overlay * origin()
Definition: HDS_overlay.h:135
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to and or **sell copies of the and to permit persons to whom the **Software is furnished to do subject to the following this list of conditions and the following disclaimers ****Redistributions in binary form must reproduce the above **copyright this list of conditions and the following **disclaimers in the documentation and or other materials **provided with the distribution ****Neither the names of the Center for Simulation of Advanced the University of nor the names of its **contributors may be used to endorse or promote products derived **from this Software without specific prior written permission ****THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE v
Definition: roccomf90.h:20
bool is_on_feature(const Vertex *v) const
Definition: HDS_accessor.h:174
void get_inodes_of_face(const Facet *f, INode_const_list &nodes)
Definition: Overlay.C:1922
bool intersect_link(const INode *x, const Halfedge *b, const Halfedge *g0, const Parent_type t0, Halfedge *g1, const Parent_type t1, Real start, Real *cb, Real *cg, Halfedge **g, Parent_type *t, int tryindex=0)
Definition: Overlay.C:1251
void snap_blue_ridge_edge(const Halfedge *b, const Halfedge *g, Real *cb, Real *cg, Parent_type *t, Real tol=0.1) const
#define RFC_END_NAME_SPACE
Definition: rfc_basic.h:29
void insert_edge_into_queue(Halfedge *h, INode *v, std::queue< Halfedge * > &q, std::queue< Halfedge * > &q_rdg, std::queue< Halfedge * > &q_crn)
Definition: Overlay.C:486
double ymax() const
bool empty() const
Parent_type
Definition: rfc_basic.h:49
const Point & point() const
void set_buffered_inode(Halfedge *h, int tag, INode *i) const
Definition: HDS_accessor.h:386
void match_features_0()
Definition: Overlay_0d.C:51
Halfedge_overlay * prev()
Definition: HDS_overlay.h:123
**********************************************************************Rocstar Simulation Suite Illinois Rocstar LLC All rights reserved ****Illinois Rocstar LLC IL **www illinoisrocstar com **sales illinoisrocstar com WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **Arising OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE **********************************************************************INTERFACE SUBROUTINE knode iend
const Point_2S & nat_coor(const int color) const
Definition: HDS_overlay.h:327
RFC_Window_overlay * G
Definition: Overlay.h:281
int size_of_faces() const
Get the total number of faces contained the window.
void write_inodes_vec(std::ostream &os)
Definition: Overlay.C:1561
Facet * get_facet(Halfedge *h) const
Definition: HDS_accessor.h:111
const COM::Window * base() const
Get a reference to the base COM::Window object.
void intersect_blue_with_green()
Definition: Overlay.C:572
blockLoc i
Definition: read.cpp:79
void sort_on_green_edges()
Definition: Overlay.C:771
#define RFC_BEGIN_NAME_SPACE
Definition: rfc_basic.h:28
void int int REAL * x
Definition: read.cpp:74
double zmax() const
const NT & n
std::vector< const INode * > Subface
Definition: Overlay.h:64
INode_list & get_inode_list(Halfedge *h) const
Definition: HDS_accessor.h:377
int count_edges(const Halfedge *e) const
Definition: Overlay.h:224
const Color BLUE
Definition: Color.C:62
bool do_match(const Bbox_3 &bb, double tol) const
void snap_blue_ridge_vertex(const Vertex *v, Halfedge **g, Parent_type *t, Point_2 *nc, Real tol=0.1) const
bool verify_inode(const INode *i)
Definition: Overlay.C:1022
void write_overlay_tec(std::ostream &, const COM::Window *)
Definition: Overlay.C:1956
Real sq_length(const Halfedge &h) const
Definition: Overlay.C:178
reverse_iterator rbegin()
bool project_onto_element(const Point_3 &p, Halfedge **g, Parent_type *pt, Vector_3 dir, Point_2 *nc_out, const Real eps_p, Real eps_np=-1.) const
Halfedge * halfedge(const int color) const
Definition: HDS_overlay.h:357
bool intersect_link_helper2(Real *cb, Real *cg, Halfedge **g, Parent_type *t)
Definition: Overlay.C:1223
bool logical_xor(bool a, bool b) const
Definition: Overlay.h:277
HDS_accessor< Tag_true > acc
Definition: Overlay.h:284
Overlay_primitives op
Definition: Overlay.h:283
int size_of_nodes() const
Get the total number of nodes contained the window.
Halfedge_overlay * next()
Definition: HDS_overlay.h:120
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
bool subdivide(const INode_const_list &face, INode_const_list::const_iterator last_checked, Subface_list &sub_faces, int color, int depth=0) const
Definition: Overlay.C:1759
void detect_features()
The main entry of feature detection.
std::list< Subface > Subface_list
Definition: Overlay.h:65
#define RFC_assertion_code
Definition: rfc_basic.h:68
int get_index(const Vertex *v) const
j indices j
Definition: Indexing.h:6
Halfedge * get_next_around_origin(Halfedge *h) const
Definition: HDS_accessor.h:136
NT q
Point_2 get_nat_coor(const INode &i, const Generic_element &e, const Halfedge *h, int color) const
Definition: Overlay.C:1854
Parent_pair get_edge_pair_parents(const INode &i0, const INode &i1, const int color) const
Definition: Overlay.C:1464
double ymin() const
void mark(Halfedge *h) const
Definition: HDS_accessor.h:295
bool intersect_link_helper(const Halfedge *b, Halfedge *g2, Real start, Real *cb, Real *cg, Halfedge **g, Parent_type *t, bool *found, int snapcode, const Vertex *anchor, bool panic)
Definition: Overlay.C:1058
~Overlay()
Definition: Overlay.C:61
Point_3 get_point(const Halfedge *b, const Point_2S &nc) const
NT abs(const NT &x)
Definition: number_utils.h:130
void insert_node_in_blue_edge(INode &x, Halfedge *b)
Definition: Overlay.C:187
#define RFC_precondition
Definition: rfc_basic.h:63
Vertex * get_destination(Halfedge *h) const
Definition: HDS_accessor.h:93
Some basic geometric data types.
Definition: mapbasic.h:54
void set_tolerance(double tol)
Definition: Overlay.C:66
long double dist(long double *coord1, long double *coord2, int size)
bool verbose
Definition: Overlay.h:287
bool is_border(const Halfedge *h) const
Definition: HDS_accessor.h:153
void set_inode(Vertex *v, INode *i) const
Definition: HDS_accessor.h:374
std::pair< const INode *, const Halfedge * > get_next_inode_ccw(const INode *v0, const INode *v1, int color) const
Definition: Overlay.C:1585
Bbox_3 get_bounding_box() const
Get the bounding box of the window.
RFC_Window_overlay * B
Definition: Overlay.h:280
int id() const
IO::Mode set_ascii_mode(std::ios &i)
Definition: io.C:70
bool is_feature_1(const Halfedge *h) const
RFC_BEGIN_NAME_SPACE double get_wtime()
Definition: Timing.h:33
void set_parent(Halfedge *h, const Point_2 &p, int color)
Definition: HDS_overlay.h:337
bool verbose2
Definition: Overlay.h:288
Vector_3 & get_normal(int v)
void associate_green_vertices()
Definition: Overlay.C:898
reverse_iterator rend()
#define RFC_assertion
Definition: rfc_basic.h:65
reference front()
std::list< INode * > inodes
Definition: Overlay.h:282
Facet_overlay * facet()
Definition: HDS_overlay.h:129
SURF::Vector_2< Real > Point_2
Definition: rfc_basic.h:43
std::string out_pre
Definition: Overlay.h:289
std::pair< const INode *, const Halfedge * > get_next_inode_cw(const INode *v0, const INode *v1, int color) const
Definition: Overlay.C:1655
reference back()
bool is_queue_empty(std::queue< Halfedge * > &q, std::queue< Halfedge * > &q_rdg, std::queue< Halfedge * > &q_crn)
Definition: Overlay.C:546
bool contains(const Halfedge *e1, const Parent_type t1, const Halfedge *e2, const Parent_type t2) const
Definition: Overlay.C:1488