cgma
SurfaceOverlapTool.cpp
Go to the documentation of this file.
00001 //- Class: SurfaceOverlapTool
00002 //- Description: Utilities to debug imprinting/merging problems
00003 //- Owner: Steve Storm
00004 //- Created: 22 October 1999
00005 //- Overhauled: January 2003
00006 
00007 #include "RefEntityFactory.hpp"
00008 #include "SurfaceOverlapTool.hpp"
00009 #include "RefVertex.hpp"
00010 #include "RefEdge.hpp"
00011 #include "RefFace.hpp"
00012 #include "Body.hpp"
00013 #include "CoEdge.hpp"
00014 #include "BodySM.hpp"
00015 #include "RefGroup.hpp"
00016 #include "GeometryModifyTool.hpp"
00017 #include "GeometryQueryTool.hpp"
00018 #include "TopologyEntity.hpp"
00019 #include "Surface.hpp"
00020 #include "Curve.hpp"
00021 
00022 #include "CubitBox.hpp"
00023 #include "CubitUtil.hpp"
00024 
00025 #include "DLIList.hpp"
00026 #include "ProgressTool.hpp"
00027 #include "AppUtil.hpp"
00028 #include "SurfaceOverlapFacet.hpp"
00029 #include "CurveOverlapFacet.hpp"
00030 #include "TDSurfaceOverlap.hpp"
00031 #include "RTree.hpp"
00032 #include "AbstractTree.hpp"
00033 
00034 #include "GMem.hpp"
00035 #include "SettingHandler.hpp"
00036 
00037 #include "GfxPreview.hpp"
00038 #include "GfxDebug.hpp"
00039 #include "CpuTimer.hpp"
00040 
00041 #define NO_FACETS_FOR_ABSTRACTTREE 10
00042 
00043 SurfaceOverlapTool* SurfaceOverlapTool::instance_ = 0;
00044 double SurfaceOverlapTool::gapMin = 0.0;
00045 double SurfaceOverlapTool::gapMax = 0.01;
00046 double SurfaceOverlapTool::angleMin = 0.0;
00047 double SurfaceOverlapTool::angleMax = 5.0;
00048 int SurfaceOverlapTool::normalType = 1; // 1=any, 2=opposite, 3=same
00049 double SurfaceOverlapTool::overlapTolerance = .001;
00050 CubitBoolean SurfaceOverlapTool::groupResults = CUBIT_TRUE;
00051 CubitBoolean SurfaceOverlapTool::listPairs = CUBIT_TRUE;
00052 CubitBoolean SurfaceOverlapTool::displayPairs = CUBIT_TRUE;
00053 CubitBoolean SurfaceOverlapTool::imprintResults = CUBIT_FALSE;
00054 double SurfaceOverlapTool::facetAbsTol = 0.0; // Use default
00055 unsigned short SurfaceOverlapTool::facetAngTol = 15; // Seems to work pretty good
00056 CubitBoolean SurfaceOverlapTool::checkWithinBodies = CUBIT_FALSE;
00057 CubitBoolean SurfaceOverlapTool::checkAcrossBodies = CUBIT_TRUE;
00058 bool SurfaceOverlapTool::skipFacingSurfaces = CUBIT_FALSE; // skip the pair if the normals pass through eachother (normalType must == 2)
00059 
00060 // Constructor
00061 SurfaceOverlapTool* SurfaceOverlapTool::instance()
00062 {
00063    if( instance_ == NULL )
00064        instance_ = new SurfaceOverlapTool;
00065    return instance_;
00066 }
00067 
00068 SurfaceOverlapTool::SurfaceOverlapTool()
00069 {
00070   facetAbsTol = 0.0; // Use default
00071   facetAngTol = 10;  // Seems to work pretty good
00072   gapMin = 0.0;
00073   gapMax = 0.01;
00074   angleMin = 0.0;
00075   angleMax = 5.0;
00076   normalType = 1; // 1=any, 2=opposite, 3=same
00077   groupResults = CUBIT_TRUE;
00078   listPairs = CUBIT_TRUE;
00079   displayPairs = CUBIT_TRUE;
00080   overlapTolerance = .001;
00081   imprintResults = CUBIT_FALSE;
00082   checkWithinBodies = CUBIT_FALSE;
00083   checkAcrossBodies = CUBIT_TRUE;
00084   skipFacingSurfaces = CUBIT_FALSE;
00085 }
00086 
00087 // Destructor
00088 SurfaceOverlapTool::~SurfaceOverlapTool()
00089 {
00090 }
00091 
00092 CubitBoolean SurfaceOverlapTool::draw_overlapping_surface_pair( RefFace *ref_face_1,
00093                                                         RefFace *ref_face_2)
00094 {
00095   CubitBoolean abort = CUBIT_FALSE;
00096   CubitBoolean draw_overlap = CUBIT_TRUE;
00097   CubitBoolean overlap = check_overlap( ref_face_1, ref_face_2, 
00098                                         abort, draw_overlap );
00099 
00100   return overlap;
00101 }
00102 
00103 CubitStatus 
00104 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list, 
00105                                                DLIList<RefEntity*> &faces_to_draw,
00106                                                bool filter_slivers)
00107 {
00108    DLIList<RefFace*> list1, list2;
00109    return find_overlapping_surfaces( ref_face_list, list1, list2, faces_to_draw, CUBIT_TRUE,
00110      filter_slivers);
00111 }
00112 
00113 CubitStatus
00114 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<Body*> &body_list,
00115                                                DLIList<RefEntity*> &faces_to_draw,
00116                                                bool filter_slivers)
00117 {
00118   DLIList<RefFace*> list1, list2;
00119   return find_overlapping_surfaces( body_list, list1, list2, faces_to_draw, CUBIT_TRUE,
00120     filter_slivers);
00121 }
00122 
00123 
00124 CubitStatus
00125 SurfaceOverlapTool::find_candidate_surfaces_for_imprinting( DLIList<BodySM*> &body_list,
00126                                               DLIList<Surface*> &surface_list1,
00127                                               DLIList<Surface*> &surface_list2,
00128                                               double overlap_tol,
00129                                               bool filter_slivers)
00130 {
00131   //collect all the surfaces
00132   DLIList<Surface*> surface_list;
00133   int i;
00134   for( i=body_list.size(); i--; )
00135   {
00136     BodySM *body_sm = body_list.get_and_step();
00137     DLIList<Surface*> surfs;
00138     body_sm->surfaces_ignore_virtual( surfs, false );
00139 //    body_sm->surfaces( surfs );
00140     surface_list.merge_unique( surfs );
00141   }
00142 
00143   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
00144   if(overlap_tol > 0.0)
00145     tolerance = overlap_tol;
00146 
00147   // Populate the Surface AbstractTree
00148   AbstractTree<Surface*> *a_tree = new RTree<Surface*>( tolerance );
00149   surface_list.reset();
00150   for( i=surface_list.size(); i--; )
00151   {
00152     Surface *surface = surface_list.get_and_step();
00153     a_tree->add( surface );
00154   }
00155 
00156   std::map<Surface*, DLIList<SurfaceOverlapFacet*>* > surface_facet_map;
00157   std::map<Surface*, double > surface_to_area_map;
00158   std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* > a_tree_map;
00159 
00160   surface_list.reset();
00161   for( i=surface_list.size(); i--; )
00162   {
00163     Surface *surf1 = surface_list.get_and_step();
00164 
00165     BodySM *surf1_body = surf1->bodysm();
00166 
00167     // Remove this surface from AbstractTree so it is not found and never
00168     // found again
00169     a_tree->remove( surf1 );
00170 
00171     // Find RefFaces from AbstractTree that are within range of this surface
00172     CubitBox surf1_box = surf1->bounding_box();
00173     DLIList<Surface*> close_surfaces;
00174     a_tree->find( surf1_box, close_surfaces );
00175 
00176     int j;
00177     for( j=close_surfaces.size(); j--; )
00178     {
00179       Surface *surf2 = close_surfaces.get_and_step();
00180       BodySM *surf2_body = surf2->bodysm();
00181 
00182       //don't check for overlapping surfaces within bodies
00183       if( surf1_body == surf2_body )
00184         continue;
00185       
00186       // check for overlap, boundary contact, int contact, penetration, etc.
00187       if( check_surfs_for_imprinting( surf1, surf2, 
00188                          &surface_facet_map, 
00189                          &surface_to_area_map, 
00190                          &a_tree_map,
00191                          overlap_tol ) == CUBIT_TRUE )
00192       {
00193         surface_list1.append( surf1 );
00194         surface_list2.append( surf2 );
00195       }
00196 
00197     }
00198   }
00199 
00200   //clean up maps;
00201   std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* >::iterator tree_iter; 
00202   tree_iter = a_tree_map.begin();
00203   for(; tree_iter != a_tree_map.end(); tree_iter++ )
00204     delete tree_iter->second;
00205 
00206   std::map<Surface*, DLIList<SurfaceOverlapFacet*>* >::iterator sof_iter; 
00207   sof_iter = surface_facet_map.begin();
00208   for(; sof_iter != surface_facet_map.end(); sof_iter++)
00209   {
00210     DLIList<SurfaceOverlapFacet*> *tmp_list = sof_iter->second;
00211 
00212     //delete contents of list
00213     for( i=tmp_list->size(); i--; )
00214       delete tmp_list->get_and_step();
00215 
00216     //delete the list
00217     delete tmp_list;
00218   }
00219 
00220   delete a_tree;
00221 
00222   return CUBIT_SUCCESS;
00223 }
00224 
00225 CubitStatus
00226 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<Body*> &body_list,
00227                                               DLIList<RefFace*> &ref_face_list1,
00228                                               DLIList<RefFace*> &ref_face_list2,
00229                                               DLIList<RefEntity*> &faces_to_draw,
00230                                               CubitBoolean show_messages,
00231                                               bool filter_slivers)
00232 {
00233   CubitStatus status = CUBIT_SUCCESS;
00234 
00235   CubitBoolean group_results = CUBIT_FALSE;
00236   CubitBoolean list_pairs = CUBIT_FALSE;
00237   CubitBoolean imprint_results = CUBIT_FALSE;
00238 
00239   if( show_messages == CUBIT_TRUE )
00240   {
00241      group_results = groupResults;
00242      list_pairs = listPairs;
00243      imprint_results = imprintResults;
00244   }
00245 
00246   // Handle the special case of finding overlapping surfaces within a given 
00247   // body - we can do this MUCH faster than the general case (this is a 
00248   // rare case in general but at Cat we have an application for this!).
00249 
00250   // The usual case
00251   if( checkWithinBodies == CUBIT_FALSE ||
00252       (checkWithinBodies == CUBIT_TRUE && checkAcrossBodies == CUBIT_TRUE) )
00253   {
00254     // Utilize a straight surface list
00255     DLIList<RefFace*> ref_face_list;
00256     body_list.reset();
00257     int i;
00258     for( i=body_list.size(); i--; )
00259     {
00260       Body* body_ptr = body_list.get_and_step();
00261       DLIList<RefFace*> body_face_list;
00262       body_ptr->ref_faces( body_face_list );
00263       ref_face_list.merge_unique( body_face_list );
00264     }
00265 
00266     int prog_step = 0;
00267     if( show_messages )
00268     {
00269       prog_step = 10;
00270       PRINT_INFO( "Finding surface overlap...\n" );
00271       if( ref_face_list.size() > prog_step )
00272       {
00273         char message[128];
00274         sprintf(message, "Finding Surface Overlap On %d Surfaces", ref_face_list.size() );
00275         AppUtil::instance()->progress_tool()->start(0, ref_face_list.size(),
00276           "Progress", message, TRUE, TRUE );
00277       }
00278     }
00279 
00280     status = find_overlapping_surfaces( ref_face_list, ref_face_list1,
00281       ref_face_list2, faces_to_draw, list_pairs, prog_step, filter_slivers );
00282 
00283     if( show_messages && ref_face_list.size() > prog_step )
00284       AppUtil::instance()->progress_tool()->end();
00285   }
00286 
00287   // Special case - checking within bodies
00288   else
00289   {
00290     int prog_step = 5;
00291     if( show_messages )
00292     {
00293       PRINT_INFO( "Finding surface overlap...\n" );
00294       if( body_list.size() > prog_step )
00295       {
00296         char message[128];
00297         sprintf(message, "Finding Surface Overlap On %d Bodies", body_list.size() );
00298         AppUtil::instance()->progress_tool()->start(0, body_list.size(),
00299           "Progress", message, TRUE, TRUE );
00300       }
00301     }
00302 
00303     int i;
00304     body_list.reset();
00305     for( i=body_list.size(); i--; )
00306     {
00307       Body* body_ptr = body_list.get_and_step();
00308       DLIList<RefFace*> body_face_list;
00309       body_ptr->ref_faces( body_face_list );
00310 
00311       status = find_overlapping_surfaces( body_face_list, ref_face_list1,
00312         ref_face_list2, faces_to_draw, list_pairs, -1, filter_slivers );
00313 
00314       if( show_messages && body_list.size() > prog_step )
00315         AppUtil::instance()->progress_tool()->step();
00316 
00317       if( status == CUBIT_FAILURE )
00318         break;
00319     }
00320 
00321     if( show_messages && body_list.size() > prog_step )
00322         AppUtil::instance()->progress_tool()->end();
00323   }
00324 
00325   if( faces_to_draw.size() )
00326   {
00327     if( group_results == CUBIT_TRUE )
00328     {
00329       RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup( "surf_overlap" );
00330       new_group->add_ref_entity( faces_to_draw );
00331       CubitString name = new_group->entity_name();
00332       PRINT_INFO( "Found %d overlapping surface pairs (added to group '%s')\n", 
00333         ref_face_list1.size(), name.c_str() );
00334     }
00335     else if( show_messages )
00336       PRINT_INFO( "Found %d overlapping surface pairs\n", ref_face_list1.size() );
00337 
00338     if ( imprint_results )
00339     {
00340       CubitStatus stat = imprint(ref_face_list1, ref_face_list2);
00341       if ( stat != CUBIT_SUCCESS )
00342       {
00343         PRINT_WARNING("Imprinting overlaps was unsuccessful\n");
00344       }
00345     }
00346   }
00347   else if (show_messages )
00348     PRINT_INFO( "Found 0 overlapping surface pairs\n" );
00349 
00350   return status;
00351 }
00352 
00353 CubitStatus
00354 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list,
00355                                               DLIList<RefFace*> &ref_face_list1,
00356                                               DLIList<RefFace*> &ref_face_list2,
00357                                               DLIList<RefEntity*> &faces_to_draw,
00358                                               CubitBoolean show_messages, 
00359                                               bool filter_slivers)
00360 {
00361   CubitStatus status = CUBIT_SUCCESS;
00362 
00363   CubitBoolean group_results = CUBIT_FALSE;
00364   CubitBoolean list_pairs = CUBIT_FALSE;
00365   CubitBoolean imprint_results = CUBIT_FALSE;
00366 
00367   if( show_messages == CUBIT_TRUE )
00368   {
00369      group_results = groupResults;
00370      list_pairs = listPairs;
00371      imprint_results = imprintResults;
00372   }
00373 
00374   int prog_step = 10;
00375 
00376   if( show_messages )
00377   {
00378     PRINT_INFO( "Finding surface overlap...\n" );
00379     if( ref_face_list.size() > prog_step )
00380     {
00381       char message[128];
00382       sprintf(message, "Finding Surface Overlap On %d Surfaces", ref_face_list.size() );
00383       AppUtil::instance()->progress_tool()->start(0, ref_face_list.size(),
00384         "Progress", message, TRUE, TRUE );
00385     }
00386   }
00387   else
00388     prog_step = -1;
00389 
00390   status = find_overlapping_surfaces( ref_face_list, ref_face_list1,
00391     ref_face_list2, faces_to_draw, list_pairs, prog_step, filter_slivers );
00392 
00393   if( show_messages && ref_face_list.size() > prog_step )
00394     AppUtil::instance()->progress_tool()->end();
00395 
00396   if( faces_to_draw.size() )
00397   {
00398     if( group_results == CUBIT_TRUE )
00399     {
00400       RefGroup *new_group = RefEntityFactory::instance()->construct_RefGroup( "surf_overlap" );
00401       new_group->add_ref_entity( faces_to_draw );
00402       CubitString name = new_group->entity_name();
00403       PRINT_INFO( "Found %d overlapping surface pairs (added to group '%s')\n", 
00404         ref_face_list1.size(), name.c_str() );
00405     }
00406     else if( show_messages )
00407       PRINT_INFO( "Found %d overlapping surface pairs\n", ref_face_list1.size() );
00408 
00409     if ( imprint_results )
00410     {
00411       CubitStatus stat = imprint(ref_face_list1, ref_face_list2);
00412       if ( stat != CUBIT_SUCCESS )
00413       {
00414         PRINT_WARNING("Imprinting overlaps was unsuccessful\n");
00415       }
00416     }
00417   }
00418   else if (show_messages )
00419     PRINT_INFO( "Found 0 overlapping surface pairs\n" );
00420 
00421   return status;
00422 }
00423 
00424 CubitStatus
00425 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list,
00426                                               DLIList<RefFace*> &ref_face_list1,
00427                                               DLIList<RefFace*> &ref_face_list2,
00428                                               DLIList<RefEntity*> &pair_list,
00429                                               CubitBoolean list_pairs,
00430                                               int prog_step,
00431                                               bool filter_slivers)
00432 {
00433   int number_pairs = 0;
00434   CubitBoolean abort = CUBIT_FALSE;
00435   RefEntity* ref_entity;
00436 
00437   // Check each surface with each one later in the list
00438   RefFace *ref_face_ptr1, *ref_face_ptr2;
00439 
00440   // Populate the RefFace AbstractTree
00441   AbstractTree<RefFace*> *a_tree = new RTree<RefFace*>( gapMax );
00442   int i;
00443   ref_face_list.reset();
00444   for( i=ref_face_list.size(); i--; )
00445   {
00446     RefFace *ref_face_ptr = ref_face_list.get_and_step();
00447     a_tree->add( ref_face_ptr );
00448   }
00449 
00450   // Main loop for finding overlapping surfaces
00451   ref_face_list.reset();
00452   for( i=ref_face_list.size(); i--; )
00453   {
00454     // Cancel button pushed or cntrl-C
00455     if (AppUtil::instance()->interrupt()) 
00456     {
00457       PRINT_INFO("Find overlap operation aborted.\n");
00458       goto done;
00459     }
00460 
00461     ref_face_ptr1 = ref_face_list.get_and_step();
00462 
00463     // Remove this surface from AbstractTree so it is not found and never
00464     // found again
00465     a_tree->remove( ref_face_ptr1 );
00466 
00467     // Find RefFaces from AbstractTree that are within range of this surface
00468     CubitBox ref_face1_box = ref_face_ptr1->bounding_box();
00469     DLIList<RefFace*> close_ref_faces;
00470     a_tree->find( ref_face1_box, close_ref_faces );
00471 
00472     int j;
00473     for( j=close_ref_faces.size(); j--; )
00474     {
00475       // Cancel button pushed or cntrl-C
00476       if (AppUtil::instance()->interrupt()) 
00477       {
00478          PRINT_INFO("Find overlap operation aborted.\n");
00479          goto done;
00480       }
00481 
00482       ref_face_ptr2 = close_ref_faces.get_and_step();
00483 
00484       bool overlap = check_overlap( ref_face_ptr1, ref_face_ptr2, abort );
00485       if(overlap == CUBIT_TRUE && filter_slivers)
00486       {
00487         RefFace *f1, *f2;
00488         DLIList<RefEdge*> f1_edges, f2_edges, *f1_edge_list/* , *f2_edge_list */;
00489         ref_face_ptr1->ref_edges(f1_edges);
00490         ref_face_ptr2->ref_edges(f2_edges);
00491         if(f1_edges.size() > f2_edges.size())
00492         {
00493           f1 = ref_face_ptr2;
00494           f2 = ref_face_ptr1;
00495           f1_edge_list = &f2_edges;
00496         }
00497         else
00498         {
00499           f1 = ref_face_ptr1;
00500           f2 = ref_face_ptr2;
00501           f1_edge_list = &f1_edges;
00502         }
00503         int b;
00504         for(b=f1_edge_list->size(); b>0 && overlap; b--)
00505         {
00506           RefEdge *cur_edge = f1_edge_list->get_and_step();
00507           if(cur_edge->is_merged())
00508           {
00509             DLIList<RefFace*> face_list;
00510             cur_edge->ref_faces(face_list);
00511             if(face_list.is_in_list(f2))
00512             {
00513               CubitVector mid_pt;
00514               cur_edge->mid_point(mid_pt);
00515               CubitVector f1_norm = f1->normal_at(mid_pt); 
00516               CubitVector f2_norm = f2->normal_at(mid_pt); 
00517               DLIList<CoEdge*> f1_coedges, f2_coedges;
00518               cur_edge->get_co_edges(f1_coedges, f1);
00519               cur_edge->get_co_edges(f2_coedges, f2);
00520               if(f1_coedges.size() == 1 && f2_coedges.size() == 1)
00521               {
00522                 CoEdge *ce1 = f1_coedges.get();
00523                 CoEdge *ce2 = f2_coedges.get();
00524                 CubitVector curve_dir;
00525 
00526                 if( cur_edge->get_curve_ptr()->geometry_type() == STRAIGHT_CURVE_TYPE )
00527                   cur_edge->get_point_direction(mid_pt, curve_dir);
00528                 else
00529                   cur_edge->tangent( mid_pt, curve_dir );
00530 
00531                 CubitVector ce1_dir, ce2_dir;
00532                 if(ce1->get_sense() == CUBIT_REVERSED)
00533                   ce1_dir = -curve_dir;
00534                 else
00535                   ce1_dir = curve_dir;
00536                 if(ce2->get_sense() == CUBIT_REVERSED)
00537                   ce2_dir = -curve_dir;
00538                 else
00539                   ce2_dir = curve_dir;
00540                 CubitVector in_dir1 = f1_norm * ce1_dir;
00541                 CubitVector in_dir2 = f2_norm * ce2_dir;
00542                 if(in_dir1 % in_dir2 < 0.0)
00543                   overlap = false;
00544               }
00545             }
00546           }
00547         }
00548       }
00549       if(overlap)
00550       {
00551         if( abort == CUBIT_TRUE )
00552           goto done;
00553 
00554         if( list_pairs == CUBIT_TRUE )
00555           PRINT_INFO( " Surface %d and %d overlap\n", ref_face_ptr1->id(),
00556           ref_face_ptr2->id() );
00557         
00558         number_pairs++;
00559         
00560         ref_entity = CAST_TO(ref_face_ptr1,RefEntity);
00561         pair_list.append_unique( ref_entity );
00562         
00563         ref_entity = CAST_TO(ref_face_ptr2,RefEntity);
00564         pair_list.append_unique( ref_entity );
00565         
00566         ref_face_list1.append( ref_face_ptr1 );
00567         ref_face_list2.append( ref_face_ptr2 );
00568       }
00569 
00570       if( abort == CUBIT_TRUE )
00571         goto done;
00572     }
00573 
00574     // Free memory, since this surface will never be accessed again.  This
00575     // helps to reduce memory required.
00576     ref_face_ptr1->delete_TD( &TDSurfaceOverlap::is_surface_overlap );
00577 
00578     if( prog_step>0 && ref_face_list.size() > prog_step )
00579       AppUtil::instance()->progress_tool()->step();
00580   }
00581 
00582 done:  
00583 
00584   // Make sure all tool datas are deleted
00585   for( i=ref_face_list.size(); i--; )
00586     ref_face_list.get_and_step()->delete_TD( &TDSurfaceOverlap::is_surface_overlap );
00587 
00588   delete a_tree;
00589 
00590   return CUBIT_SUCCESS;
00591 }
00592 
00593 
00594 double SurfaceOverlapTool::find_area_overlap( SurfaceOverlapFacet *facet1, SurfaceOverlapFacet *facet2, const double facet_compare_tol )
00595 {
00596   double local_overlap_area = 0.0;
00597   double opp_low = 180.0 - angleMax;
00598   double opp_high = 180.0 - angleMin;
00599 
00600   // Check angle between triangles, must be within criteria
00601   double ang = facet1->angle( *facet2 ); 
00602 
00603   // Allow overlap for angles close to 180 and 0 degrees
00604 
00605   // normalType - 1=any, 2=opposite, 3=same
00606   //ang>=180.0-angt || ang<angt
00607   if( ((normalType==1 && ang>=opp_low && ang<=opp_high) ||
00608       (normalType==1 && ang>=angleMin && ang<=angleMax) ||
00609       (normalType==2 && ang>=opp_low && ang<=opp_high) ||
00610       (normalType==3 && ang>=angleMin && ang<=angleMax)) && 
00611       (normalType != 2 || !skipFacingSurfaces || !facet1->facing( *facet2 )))// check to make sure the surfaces are not facing 
00612   {
00613       // If triangle bounding boxes don't intersect - no overlap
00614       if( facet1->bbox_overlap( facet_compare_tol, *facet2 ) )
00615       {
00616           // Check distance between triangles, must be within criteria
00617           double dist = facet1->distance( *facet2 );
00618           if( dist >= gapMin && dist <= facet_compare_tol )
00619           {
00620               // Check for projected overlap
00621               // We want sum of area of ALL overlapping facets
00622               local_overlap_area = facet1->projected_overlap( *facet2 );
00623               return local_overlap_area;               
00624           }
00625       }
00626    }
00627    return local_overlap_area;
00628 }
00629 
00630 CubitBoolean SurfaceOverlapTool::extract_surf_facets( 
00631                                                      Surface *surface1, 
00632                                                      Surface *surface2, 
00633                                                      std::map<Surface*, DLIList<SurfaceOverlapFacet*>* > *facet_map,
00634                                                      const double tolerance,
00635                                                      const double facet_tol,
00636                                                      DLIList<SurfaceOverlapFacet*> *&facet_list1,
00637                                                      DLIList<SurfaceOverlapFacet*> *&facet_list2                                                      
00638                                                      )
00639 {
00640   int i;
00641   AnalyticGeometryTool::instance();
00642   
00643 
00644   std::map<Surface*, DLIList<SurfaceOverlapFacet*>* >::iterator facet_iterator;
00645 
00646 
00647   //see if surface is in map...if not we have to create faceting for it.
00648   if( facet_map )
00649     facet_iterator = facet_map->find( surface1 );
00650 
00651   if( facet_map == NULL || facet_iterator == facet_map->end() )
00652   {
00653     //for non-planar surfaces, facet wrt the smallest curve of the surface 
00654     double min_edge_length = 0.0;
00655 
00656     if( surface1->geometry_type() != PLANE_SURFACE_TYPE )
00657     {
00658       DLIList<Curve*> tmp_curves;
00659       surface1->curves( tmp_curves );
00660       CubitBox surface_box = surface1->bounding_box();
00661 
00662       //ignore curves that are really small
00663       double min_length_threshold = (surface_box.diagonal().length())*0.01;
00664       if( tmp_curves.size() )
00665       {
00666         min_edge_length = CUBIT_DBL_MAX; 
00667         double tmp_length; 
00668         for( i=tmp_curves.size(); i--; )
00669         {
00670           tmp_length = tmp_curves.get_and_step()->measure();
00671           if( tmp_length > min_length_threshold && tmp_length < min_edge_length )
00672             min_edge_length = tmp_length;
00673         }
00674       }
00675       if( min_edge_length == CUBIT_DBL_MAX )
00676         min_edge_length = 0.0;
00677       else
00678         min_edge_length *= 2;
00679     }
00680 
00681     facet_list1 = new DLIList<SurfaceOverlapFacet*>;
00682     GMem surface_graphics;
00683     surface1->get_geometry_query_engine()->get_graphics( surface1, &surface_graphics,
00684                                 0, facet_tol, 0 );                               
00685 
00686     GPoint* plist = surface_graphics.point_list();
00687     int* facet_list = surface_graphics.facet_list();
00688 
00689     GPoint p[3];
00690     for (i = 0; i < surface_graphics.fListCount; )
00691     {
00692       int sides = facet_list[i++];
00693       if (sides != 3)
00694       {
00695         PRINT_WARNING("Skipping n-sided polygone in triangle list"
00696                       " in TDSurfaceOverlap.\n");
00697         i += sides;
00698       }
00699       else
00700       {
00701         p[0] = plist[facet_list[i++]];
00702         p[1] = plist[facet_list[i++]];
00703         p[2] = plist[facet_list[i++]];
00704      
00705         SurfaceOverlapFacet *facet = new SurfaceOverlapFacet( p );        
00706         facet_list1->append( facet );
00707       }
00708     }
00709 
00710     if( facet_map )
00711       facet_map->insert( std::map<Surface*, 
00712         DLIList<SurfaceOverlapFacet*>*>::value_type( surface1, facet_list1 )); 
00713   }
00714   else
00715     facet_list1 = facet_iterator->second;
00716 
00717   //see if surface is in map...if not we have to create faceting for it.
00718   if( facet_map )
00719     facet_iterator = facet_map->find( surface2 );
00720 
00721   if( facet_map == NULL || facet_iterator == facet_map->end() )
00722   {
00723     //for non-planar surfaces, facet wrt the smallest curve of the surface 
00724     double min_edge_length = 0.0;
00725 
00726     if( surface2->geometry_type() != PLANE_SURFACE_TYPE )
00727     {
00728       DLIList<Curve*> tmp_curves;
00729       surface2->curves( tmp_curves );
00730       CubitBox surface_box = surface2->bounding_box();
00731 
00732       //ignore curves that are really small
00733       double min_length_threshold = (surface_box.diagonal().length())*0.01;
00734       if( tmp_curves.size() )
00735       {
00736         min_edge_length = CUBIT_DBL_MAX; 
00737         double tmp_length; 
00738         for( i=tmp_curves.size(); i--; )
00739         {
00740           tmp_length = tmp_curves.get_and_step()->measure();
00741           if( tmp_length > min_length_threshold && tmp_length < min_edge_length )
00742             min_edge_length = tmp_length;
00743         }
00744       }
00745       if( min_edge_length == CUBIT_DBL_MAX )
00746         min_edge_length = 0.0;
00747       else
00748         min_edge_length *= 2;
00749     }
00750 
00751     facet_list2 = new DLIList<SurfaceOverlapFacet*>;
00752     GMem surface_graphics;
00753     surface2->get_geometry_query_engine()->get_graphics( surface2, &surface_graphics, 
00754                                           0, facet_tol, 0 );                                
00755 
00756     GPoint* plist = surface_graphics.point_list();
00757     int* facet_list = surface_graphics.facet_list();
00758 
00759     GPoint p[3];
00760     for (i = 0; i < surface_graphics.fListCount; )
00761     {
00762       int sides = facet_list[i++];
00763       if (sides != 3)
00764       {
00765         PRINT_WARNING("Skipping n-sided polygone in triangle list"
00766                       " in TDSurfaceOverlap.\n");
00767         i += sides;
00768       }
00769       else
00770       {
00771         p[0] = plist[facet_list[i++]];
00772         p[1] = plist[facet_list[i++]];
00773         p[2] = plist[facet_list[i++]];
00774      
00775         SurfaceOverlapFacet *facet = new SurfaceOverlapFacet( p );            
00776         facet_list2->append( facet );
00777       }
00778     }
00779 
00780     if( facet_map )
00781       facet_map->insert( std::map<Surface*, 
00782         DLIList<SurfaceOverlapFacet*>*>::value_type( surface2, facet_list2 )); 
00783   }           
00784   else
00785     facet_list2 = facet_iterator->second;
00786 
00787   return CUBIT_TRUE;
00788 }
00789 
00790 CubitBoolean SurfaceOverlapTool::check_size_and_swap_surfs( 
00791                                                     Surface *&tmp_surf1, 
00792                                                     Surface *&tmp_surf2, 
00793                                                     const double tolerance,
00794                                                     const double facet_tol,
00795                                                     DLIList<SurfaceOverlapFacet*> *&facet_list1, 
00796                                                     DLIList<SurfaceOverlapFacet*> *&facet_list2, 
00797                                                     std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* > *&a_tree_map,
00798                                                     AbstractTree<SurfaceOverlapFacet*> *&a_tree2 )
00799 {
00800   
00801   // Compare facets
00802   int num_tri1 = facet_list1->size();
00803   if( !num_tri1 )
00804   {
00805     PRINT_WARNING( "Unable to facet surface\n" );
00806     return CUBIT_FALSE;
00807   }
00808   
00809   int num_tri2 = facet_list2->size();
00810   if( !num_tri2 )
00811   {
00812     PRINT_WARNING( "Unable to facet surface\n" );
00813     return CUBIT_FALSE;
00814   }
00815    
00816   // Compare least to most - possibly switch the lists
00817   Surface *temp_surf;
00818   if( facet_list1->size() > facet_list2->size() )
00819   {
00820     DLIList<SurfaceOverlapFacet*> *temp_list = facet_list1;
00821     facet_list1 = facet_list2;
00822     facet_list2 = temp_list;
00823     temp_surf = tmp_surf1;
00824     tmp_surf1 = tmp_surf2;
00825     tmp_surf2 = temp_surf;    
00826   }
00827 
00828   // Possibly use an AbstractTree for facet_list2
00829   int i;
00830   if( facet_list2->size() > NO_FACETS_FOR_ABSTRACTTREE )
00831   { 
00832     std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* >::iterator iter1, iter2; 
00833     // If the same size, use the existing AbstractTree if one has
00834     // one and the other doesn't.  This probably won't 
00835     // save time, but there is a miniscule chance it might.
00836     if( facet_list1->size() == facet_list2->size() )
00837     {
00838       //see if both are in the a_tree_map
00839       iter1 = a_tree_map->find( tmp_surf1 );  
00840       iter2 = a_tree_map->find( tmp_surf2 );  
00841 
00842       if( !(iter2 != a_tree_map->end()) && (iter1 != a_tree_map->end()) ) 
00843       {
00844         // Switch them, just to use the existing AbstractTree
00845         DLIList<SurfaceOverlapFacet*> *temp_list = facet_list1;
00846         facet_list1 = facet_list2;
00847         facet_list2 = temp_list;
00848         Surface *tmp_surf = tmp_surf1;
00849         tmp_surf1 = tmp_surf2;
00850         tmp_surf2 = tmp_surf;
00851         std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* >::iterator tmp_iter;
00852         tmp_iter = iter1;
00853         iter1 = iter2;
00854         iter2 = tmp_iter; 
00855       }
00856     }
00857   
00858     //populate tree if necessary
00859     iter2 = a_tree_map->find( tmp_surf2 ); 
00860     if( iter2 == a_tree_map->end() ) 
00861     {
00862       //a_tree = new RTree<SurfaceOverlapFacet*>( gapMax );
00863       a_tree2 = new RTree<SurfaceOverlapFacet*>( tolerance+facet_tol );
00864 
00865       for( i=facet_list2->size(); i--; )
00866         a_tree2->add( facet_list2->get_and_step() ); 
00867       
00868       a_tree_map->insert( std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>*>::value_type( tmp_surf2, a_tree2 ));
00869     }
00870     else
00871       a_tree2 = iter2->second;
00872   }
00873   return CUBIT_TRUE;
00874 }
00875 
00876 //Currently this function is only called when using tolerant imprinting.
00877 //It does not use the settings controlled by the user for this tool
00878 
00879 CubitBoolean SurfaceOverlapTool::check_surfs_for_imprinting( Surface *surface1, Surface *surface2,
00880               std::map<Surface*, DLIList<SurfaceOverlapFacet*>* > *facet_map,
00881               std::map<Surface*, double > *area_map,
00882               std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* > *a_tree_map,
00883               double overlap_tol)
00884 {
00885   if( surface1 == surface2 )
00886     return CUBIT_FALSE;
00887 
00888   // Initialize toelrances
00889   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
00890   if(overlap_tol > 0.0)
00891     tolerance = overlap_tol;
00892   double facet_tol = tolerance*10;
00893   //double facet_tol = 0.00025;
00894   
00895   // Extract graphics facets if not available in map
00896   DLIList<SurfaceOverlapFacet*> *facet_list1 = NULL;
00897   DLIList<SurfaceOverlapFacet*> *facet_list2 = NULL;
00898   extract_surf_facets( surface1, surface2, facet_map, tolerance, facet_tol, facet_list1, facet_list2 ); 
00899 
00900   // Swap first and second surfaces/facets to set smaller surface as first
00901   Surface *tmp_surf1 = surface1;
00902   Surface *tmp_surf2 = surface2;
00903   AbstractTree<SurfaceOverlapFacet*> *a_tree2 = NULL;
00904   if( CUBIT_FALSE == check_size_and_swap_surfs( tmp_surf1, tmp_surf2, tolerance, facet_tol, facet_list1, facet_list2, a_tree_map, a_tree2 ) )
00905   { 
00906     return CUBIT_FALSE;
00907   }
00908 
00909   // Calculate the tolerances for dist and area overlap comparision
00910   double facet_compare_tol = facet_tol+tolerance; // tolerance used in evaluating dist betwen facets
00911   double overlap_tolerance = tolerance * tolerance; // tolerance used in overlaping facets
00912   //calculate_tolerances_for_surf_intersection( tmp_surf1, tmp_surf2, facet_list1, facet_list2, area_map, facet_compare_tol, overlap_tolerance );
00913  
00914   // Check 1: check for boundary contact (boundary entities (curves & verts) of one surface touches other surface ) 
00915   if( check_boundary_contact( facet_list1, facet_list2, a_tree2, facet_compare_tol, overlap_tolerance ) )
00916   {
00917     return CUBIT_TRUE;
00918   }
00919 
00920   //if surfaces are not splines and are not of the same type, they won't overlap
00921   if( (surface1->geometry_type() != SPLINE_SURFACE_TYPE  &&
00922        surface2->geometry_type() != SPLINE_SURFACE_TYPE) &&
00923       (surface1->geometry_type() != surface2->geometry_type() )) 
00924     return CUBIT_FALSE;
00925 
00926   // Check 2: check for overlap between surfaces
00927   if( check_overlap( facet_list1, facet_list2, a_tree2, facet_compare_tol, overlap_tolerance ) )
00928   {
00929     return CUBIT_TRUE;
00930   }
00931 
00932 
00933 
00934 
00935   // Check 3: check for interior contact (interior of surface touches interior of other surface )
00936 
00937   // Check 4: check for peneration ( one surface penetrates other surface )
00938 
00939   return CUBIT_FALSE;
00940 }
00941 
00942 CubitBoolean SurfaceOverlapTool::calculate_tolerances_for_surf_intersection( 
00943                                                                             Surface *tmp_surf1, 
00944                                                                             Surface *tmp_surf2, 
00945                                                                             DLIList<SurfaceOverlapFacet*> *facet_list1, 
00946                                                                             DLIList<SurfaceOverlapFacet*> *facet_list2, 
00947                                                                             std::map<Surface*, double > *area_map, 
00948                                                                             double &facet_compare_tol, 
00949                                                                             double &overlap_tolerance )
00950 {
00951 
00952   
00953   //set ovelap tolerance to one thousandth of the smaller area.
00954   double face1_area, face2_area;
00955   if( area_map )
00956   {
00957     std::map<Surface*, double>::iterator area_iter;
00958     area_iter = area_map->find( tmp_surf1);
00959     if( area_iter == area_map->end() )
00960     {
00961       face1_area = tmp_surf1->measure();
00962       area_map->insert( std::map<Surface*, double>::value_type( tmp_surf1, face1_area ) ); 
00963     }
00964     else
00965       face1_area = area_iter->second; 
00966 
00967     area_iter = area_map->find( tmp_surf2);
00968     if( area_iter == area_map->end() )
00969     {
00970       face2_area = tmp_surf2->measure();
00971       area_map->insert( std::map<Surface*, double>::value_type( tmp_surf2, face2_area )); 
00972     }
00973     else
00974       face2_area = area_iter->second; 
00975   }
00976   else
00977   {
00978     face1_area = tmp_surf1->measure();
00979     face2_area = tmp_surf2->measure();
00980   }
00981 
00982   bool sample_deviation = false; 
00983   Surface *larger_surface = NULL;
00984   //if the surfaces are non planar and one is much bigger than the other one...
00985   //adjust the tolerance some
00986   if( (tmp_surf1->geometry_type() != PLANE_SURFACE_TYPE  &&
00987        tmp_surf2->geometry_type() != PLANE_SURFACE_TYPE) )
00988   {
00989     double length1 = tmp_surf1->bounding_box().diagonal().length();
00990     double length2 = tmp_surf2->bounding_box().diagonal().length();
00991     
00992     double ratio = 0;
00993     if(length1 > length2)
00994     {
00995       ratio = length1/length2;
00996       larger_surface = tmp_surf1;
00997     }
00998     else
00999     {
01000       ratio = length2/length1;
01001       larger_surface = tmp_surf2;
01002     }
01003    
01004     if( ratio > 50 )
01005       sample_deviation = true;
01006   }
01007 
01008   if( face1_area < face2_area )
01009     overlap_tolerance = face1_area * 0.001;
01010   else
01011     overlap_tolerance = face2_area * 0.001;
01012 
01013 
01014   //If you're comparing overlap between a large surface and a very small one, 
01015   //you might have to adjust tolerances because of the faceting.  Here we try 
01016   //to determine the deviation of the faceting of the larger surface.  I 
01017   //take the mid point of the smallest edge on the facet, thinking the smallest 
01018   //edge is approximating high curvature so it would deviate the most and thus
01019   //provide the safest tolerance.
01020   int i;
01021   if( sample_deviation )
01022   {
01023     DLIList<SurfaceOverlapFacet*> *tmp_facet_list = NULL;
01024     if( larger_surface == tmp_surf1 )
01025       tmp_facet_list = facet_list1;
01026     else
01027       tmp_facet_list = facet_list2;
01028 
01029     for( i=tmp_facet_list->size(); i--; )
01030     {
01031       SurfaceOverlapFacet *tmp_facet = tmp_facet_list->get_and_step();
01032         //we used to be lucky, where one seventh of the facets would give us a 
01033         //decent tolerance...this doesn't work now....not robust enough
01034 //      if( (i%7) == 0)  // commenting this out....sometimes you haveto 
01035 //      {
01036         CubitVector point = tmp_facet->smallest_edge_midpoint(); 
01037         //determine distance between surface and centroid 
01038 
01039         CubitVector tmp_point;
01040         larger_surface->closest_point_trimmed( point, tmp_point );  
01041         double tmp_distance = point.distance_between( tmp_point ); 
01042         if( tmp_distance > facet_compare_tol )
01043         {
01044           facet_compare_tol = tmp_distance;
01045         }
01046 //      }
01047     }
01048   }
01049   else
01050   {
01051     for( i=facet_list1->size(); i--; )
01052       facet_compare_tol += facet_list1->get_and_step()->bounding_box().diagonal().length();
01053 
01054     for( i=facet_list2->size(); i--; )
01055       facet_compare_tol += facet_list2->get_and_step()->bounding_box().diagonal().length();
01056 
01057     if( facet_list1->size() || facet_list2->size() )
01058     {
01059       facet_compare_tol /= (facet_list1->size() + facet_list2->size() );
01060       facet_compare_tol *= 0.0025;
01061     }
01062   }
01063   
01064   //if the merge tolerance is a larger, use it
01065   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
01066   if( tolerance > facet_compare_tol )
01067     facet_compare_tol = tolerance;
01068 
01069   return CUBIT_TRUE;
01070 }
01071 
01072 CubitBoolean SurfaceOverlapTool::check_overlap(  
01073   DLIList<SurfaceOverlapFacet*> *facet_list1, 
01074   DLIList<SurfaceOverlapFacet*> *facet_list2, 
01075   AbstractTree<SurfaceOverlapFacet*> *a_tree, 
01076   const double facet_tol, 
01077   const double tolerance )
01078 {
01079   int i, j;
01080   double area = 0;
01081   facet_list1->reset();
01082   double overlap_tol = tolerance * tolerance;
01083 
01084   for( i=facet_list1->size(); i--; )
01085   {
01086     SurfaceOverlapFacet *facet1 = facet_list1->get_and_step();
01087     
01088     CubitBox facet1_bbox = facet1->bounding_box();
01089     DLIList<SurfaceOverlapFacet*> close_facets;
01090     if( a_tree )
01091     {
01092       a_tree->find( facet1_bbox, close_facets );
01093       facet_list2 = &close_facets;
01094     }
01095 
01096     double facet1_perimeter = facet1->perimeter();
01097     
01098     facet_list2->reset();
01099     for( j=facet_list2->size(); j--; )
01100     {
01101       SurfaceOverlapFacet *facet2 = facet_list2->get_and_step();       
01102       
01103       // Check angle between triangles, must be within criteria
01104       double ang = facet1->angle( *facet2 );               
01105       
01106       //rough estimate...must be less than half of 45
01107       if( fabs( 180-ang) < 23.5 || ang < 23.5 )       
01108       {
01109         //make sure midpoint and one other point are within facet_tol+tolerance of plane 
01110         //defined by larger facet
01111         bool within_parallel_tol = false;
01112 
01113         if( facet1_perimeter > facet2->perimeter() )        
01114           within_parallel_tol = facet1->facet_points_within_tol( facet2, (facet_tol+tolerance) );       
01115         else
01116           within_parallel_tol = facet2->facet_points_within_tol( facet1, (facet_tol+tolerance) );
01117         
01118         if( within_parallel_tol )
01119         {
01120           // Check distance between triangles, must be within criteria
01121           double dist = facet1->distance( *facet2 );
01122           if( dist <= facet_tol+tolerance )
01123           {
01124             // Check for projected overlap
01125             // We want sum of area of ALL overlapping facets
01126             area += facet1->projected_overlap( *facet2 );
01127             if( area > overlap_tol )                  
01128             {
01129               return CUBIT_TRUE;
01130             }                
01131           }
01132         }
01133       }
01134     }
01135   }
01136 
01137   return CUBIT_FALSE;
01138 }
01139 
01140 CubitBoolean SurfaceOverlapTool::check_boundary_contact( 
01141   DLIList<SurfaceOverlapFacet*> *facet_list1, 
01142   DLIList<SurfaceOverlapFacet*> *facet_list2, 
01143   AbstractTree<SurfaceOverlapFacet*> *a_tree, 
01144   const double facet_compare_tol, 
01145   const double tmp_overlap_tol )
01146 {
01147   int i, j;
01148   facet_list1->reset();
01149   for( i=facet_list1->size(); i--; )
01150   {
01151     SurfaceOverlapFacet *facet1 = facet_list1->get_and_step();
01152     
01153     CubitBox facet1_bbox = facet1->bounding_box();
01154     DLIList<SurfaceOverlapFacet*> close_facets;
01155     if( a_tree )
01156     {
01157       a_tree->find( facet1_bbox, close_facets );
01158       facet_list2 = &close_facets;
01159     }
01160     
01161     facet_list2->reset();
01162     for( j=facet_list2->size(); j--; )
01163     {
01164       SurfaceOverlapFacet *facet2 = facet_list2->get_and_step();
01165            
01166      // Check boundary contact
01167      // If triangle bounding boxes don't intersect - no overlap
01168      if( facet1->bbox_overlap( facet_compare_tol, *facet2 ) )
01169      {
01170         // Check distance between triangles, must be within criteria
01171         double dist = facet1->distance( *facet2 );
01172         if( dist >= gapMin && dist <= facet_compare_tol )
01173         {
01174            return CUBIT_TRUE;
01175         }
01176       }   
01177     }
01178   }
01179 
01180   return CUBIT_FALSE;
01181 }
01182 
01183 
01184 CubitBoolean 
01185 SurfaceOverlapTool::check_overlap( DLIList<SurfaceOverlapFacet*> *facet_list1,
01186                                    DLIList<SurfaceOverlapFacet*> *facet_list2,
01187                                    AbstractTree<SurfaceOverlapFacet*> *a_tree, 
01188                                    CubitBoolean abort, 
01189                                    CubitBoolean draw_overlap,
01190                                    double *overlap_area ) 
01191 {
01192   double area = 0;
01193   double opp_low = 180.0 - angleMax;
01194   double opp_high = 180.0 - angleMin;
01195 
01196   facet_list1->reset();
01197   int num_tri1 = facet_list1->size();
01198   int i,j;
01199   for( i=num_tri1; i--; )
01200   {
01201     if(i%20 == 0)
01202     {
01203       // Cancel button pushed or cntrl-C
01204       if (AppUtil::instance()->interrupt()) 
01205       {
01206         PRINT_INFO("Find overlap operation aborted.\n");
01207         abort = CUBIT_TRUE;
01208         return CUBIT_FALSE;
01209       }
01210     }
01211 
01212     SurfaceOverlapFacet *facet1 = facet_list1->get_and_step();
01213 
01214     DLIList<SurfaceOverlapFacet*> close_facets;
01215     if( a_tree )
01216     {
01217       a_tree->find( facet1->bounding_box(), close_facets );
01218       facet_list2 = &close_facets;
01219     }
01220     
01221     facet_list2->reset();
01222     for( j=facet_list2->size(); j--; )
01223     {
01224       if(j%20 == 0)
01225       {
01226         // Cancel button pushed or cntrl-C
01227         if (AppUtil::instance()->interrupt()) 
01228         {
01229           PRINT_INFO("Find overlap operation aborted.\n");
01230           abort = CUBIT_TRUE;
01231           return CUBIT_FALSE;
01232         }
01233       }
01234 
01235       SurfaceOverlapFacet *facet2 = facet_list2->get_and_step();
01236       
01237       // Check angle between triangles, must be within criteria
01238       double ang = facet1->angle( *facet2 ); 
01239 
01240       // Allow overlap for angles close to 180 and 0 degrees
01241       
01242       // normalType - 1=any, 2=opposite, 3=same
01243       //ang>=180.0-angt || ang<angt
01244       if( ((normalType==1 && ang>=opp_low && ang<=opp_high) ||
01245         (normalType==1 && ang>=angleMin && ang<=angleMax) ||
01246         (normalType==2 && ang>=opp_low && ang<=opp_high) ||
01247         (normalType==3 && ang>=angleMin && ang<=angleMax) ) &&
01248         (normalType != 2 || !skipFacingSurfaces || !facet1->facing( *facet2 )))// check to make sure the surfaces are not facing )
01249       {
01250         // If triangle bounding boxes don't intersect - no overlap
01251         if( facet1->bbox_overlap( gapMax, *facet2 ) )
01252         {
01253           // Check distance between triangles, must be within criteria
01254           double dist = facet1->distance( *facet2 );
01255 
01256           if( dist >= gapMin && dist <= gapMax )
01257           {
01258             // Check for projected overlap
01259             // We want sum of area of ALL overlapping facets
01260             area += facet1->projected_overlap( *facet2, draw_overlap );
01261             if( area > overlapTolerance &&
01262                (draw_overlap == CUBIT_FALSE && overlap_area == NULL ) )
01263             {
01264               return CUBIT_TRUE;
01265             }                
01266           }
01267         }
01268       }
01269     }
01270   }  
01271   if( draw_overlap == CUBIT_TRUE ) 
01272   {
01273     PRINT_INFO("Total overlapping area = %f\n", area );
01274 
01275     if( area > 0.0 )
01276       return CUBIT_TRUE;
01277   }
01278 
01279   if( overlap_area )
01280   {
01281     if( area > 0.0 )
01282     {
01283       *overlap_area = area;
01284       return CUBIT_TRUE;
01285     }
01286   }
01287 
01288   return CUBIT_FALSE;
01289 }
01290 
01291 CubitBoolean
01292 SurfaceOverlapTool::check_overlap( RefFace *ref_face_ptr1, RefFace *ref_face_ptr2, 
01293                                    CubitBoolean abort, 
01294                                    CubitBoolean draw_overlap,
01295                                    double *overlap_area ) 
01296 {
01297   if( ref_face_ptr1 == ref_face_ptr2 )
01298     return CUBIT_FALSE;
01299 
01300   //if surfaces are not splines and are not of the same type, 
01301   //they won't overlap
01302   /*
01303   I am commenting this out because it filters out some cases we need to find with 
01304   this overlap check.
01305   if( (ref_face_ptr1->get_surface_ptr()->geometry_type() != SPLINE_SURFACE_TYPE  &&
01306        ref_face_ptr2->get_surface_ptr()->geometry_type() != SPLINE_SURFACE_TYPE) &&
01307       (ref_face_ptr1->get_surface_ptr()->geometry_type() != 
01308        ref_face_ptr2->get_surface_ptr()->geometry_type() )) 
01309     return CUBIT_FALSE;
01310     */
01311  
01312   AnalyticGeometryTool::instance();
01313   abort = CUBIT_FALSE;
01314 
01315   // Check for overlap between the found surfaces using the facets
01316   TDSurfaceOverlap *tdso_1;
01317   tdso_1 = (TDSurfaceOverlap *)ref_face_ptr1->get_TD(&TDSurfaceOverlap::is_surface_overlap);
01318   if( !tdso_1 )
01319   {
01320     ref_face_ptr1->add_TD( new TDSurfaceOverlap( ref_face_ptr1, facetAngTol, facetAbsTol,
01321                                                  gapMax ) );
01322     tdso_1 = (TDSurfaceOverlap *)ref_face_ptr1->get_TD(&TDSurfaceOverlap::is_surface_overlap);
01323   }
01324 
01325   TDSurfaceOverlap *tdso_2;
01326   tdso_2 = (TDSurfaceOverlap *)ref_face_ptr2->get_TD(&TDSurfaceOverlap::is_surface_overlap);
01327   if( !tdso_2 )
01328   {
01329     ref_face_ptr2->add_TD( new TDSurfaceOverlap( ref_face_ptr2, facetAngTol, facetAbsTol,
01330                                                  gapMax ) );
01331     tdso_2 = (TDSurfaceOverlap *)ref_face_ptr2->get_TD(&TDSurfaceOverlap::is_surface_overlap);
01332   }
01333   
01334   // Check if within the same body - maybe we don't need to consider this
01335   if( checkWithinBodies == CUBIT_FALSE )
01336   {
01337     DLIList<Body*> *body_list_ptr1, *body_list_ptr2;
01338     body_list_ptr1 = tdso_1->get_body_list();
01339     body_list_ptr2 = tdso_2->get_body_list();
01340     DLIList<Body*> shared_body_list = *body_list_ptr1;
01341     shared_body_list.intersect( *body_list_ptr2 );
01342     if( shared_body_list.size() )
01343       return CUBIT_FALSE;
01344   }
01345 
01346   // Check if in different bodies - maybe we don't need to consider this
01347   if( checkAcrossBodies == CUBIT_FALSE )
01348   {
01349     DLIList<Body*> *body_list_ptr1, *body_list_ptr2;
01350     body_list_ptr1 = tdso_1->get_body_list();
01351     body_list_ptr2 = tdso_2->get_body_list();
01352     DLIList<Body*> shared_body_list = *body_list_ptr1;
01353     shared_body_list.intersect( *body_list_ptr2 );
01354     if( shared_body_list.size() == 0 )
01355       return CUBIT_FALSE;
01356   }
01357   
01358   // Compare facets
01359   DLIList<SurfaceOverlapFacet*> *facet_list1 = tdso_1->get_facet_list();
01360   int num_tri1 = 0;
01361   if(facet_list1)
01362     num_tri1 = facet_list1->size();
01363   if( !num_tri1 )
01364   {
01365     PRINT_WARNING( "Unable to facet surface %d\n", ref_face_ptr1->id() );
01366     return CUBIT_FALSE;
01367   }
01368   
01369   DLIList<SurfaceOverlapFacet*> *facet_list2 = tdso_2->get_facet_list();
01370   int num_tri2 = 0;
01371   if(facet_list2)
01372     num_tri2 = facet_list2->size();
01373   if( !num_tri2 )
01374   {
01375     PRINT_WARNING( "Unable to facet surface %d\n", ref_face_ptr2->id() );
01376     return CUBIT_FALSE;
01377   }
01378   
01379   PRINT_DEBUG_102( " Comparing %d facets in Surface %d with %d facets in Surface %d...\n",
01380     num_tri1, ref_face_ptr1->id(), num_tri2, ref_face_ptr2->id() );
01381 
01382   // Compare least to most - possibly switch the lists
01383   if( facet_list1->size() > facet_list2->size() )
01384   {
01385     DLIList<SurfaceOverlapFacet*> *temp_list = facet_list1;
01386     facet_list1 = facet_list2;
01387     facet_list2 = temp_list;
01388     TDSurfaceOverlap *temp_tdso = tdso_1;
01389     tdso_2 = tdso_1;
01390     tdso_1 = temp_tdso;
01391   }
01392 
01393   // Possibly use an AbstractTree for facet_list2
01394   AbstractTree<SurfaceOverlapFacet*> *a_tree = NULL;
01395   if( facet_list2->size() > NO_FACETS_FOR_ABSTRACTTREE )
01396   { 
01397     // If the same size, use the existing AbstractTree if one has
01398     // one and the other doesn't.  This probably won't 
01399     // save time, but there is a miniscule chance it might.
01400     if( facet_list1->size() == facet_list2->size() )
01401     {
01402       if( !tdso_2->has_rtree() && tdso_1->has_rtree() )
01403       {
01404         // Switch them, just to use the existing AbstractTree
01405         DLIList<SurfaceOverlapFacet*> *temp_list = facet_list1;
01406         facet_list1 = facet_list2;
01407         facet_list2 = temp_list;
01408         TDSurfaceOverlap *temp_tdso = tdso_1;
01409         tdso_2 = tdso_1;
01410         tdso_1 = temp_tdso;
01411       }
01412     }
01413     a_tree = tdso_2->get_facet_rtree();
01414   }
01415 
01416   bool surfs_overlap = check_overlap( facet_list1, facet_list2, a_tree,
01417                                       abort, draw_overlap, overlap_area );
01418 
01419   return surfs_overlap;
01420 }
01421 
01422 void SurfaceOverlapTool::list_settings()
01423 {
01424   char on_off[2][4];
01425   strcpy( on_off[0], "Off" );
01426   strcpy( on_off[1], "On" );
01427 
01428   PRINT_INFO( "Surface Overlap Algorithm Settings:\n" );
01429   if( facetAbsTol == 0.0 )
01430     PRINT_INFO( " Facetting Absolute Tolerance: 0.0 (using default solid modeler setting)\n" );
01431   else
01432     PRINT_INFO( " Facetting Absolute Tolerance: %f\n", facetAbsTol );
01433 
01434   if( facetAngTol == 0 )
01435     PRINT_INFO( " Facetting Angle Tolerance: 0 (using default solid modeler setting)\n" );
01436   else
01437     PRINT_INFO( " Facetting Angle Tolerance: %d\n", facetAngTol );
01438 
01439   PRINT_INFO( " Gap Range: %f to %f\n", gapMin, gapMax );
01440   PRINT_INFO( " Angle Range: %.1f to %.1f degrees\n", angleMin, angleMax );
01441   PRINT_INFO( " Overlap Area Tolerance: %f\n", overlapTolerance );
01442 
01443   switch( normalType )
01444   {
01445   case 1:
01446     PRINT_INFO( " Pair Normals Allowed: Any\n" );
01447     break;
01448   case 2:
01449     PRINT_INFO( " Pair Normals Allowed: Opposite\n" );
01450     break;
01451   case 3:
01452     PRINT_INFO( " Pair Normals Allowed: Same\n" );
01453     break;
01454   }
01455 
01456   PRINT_INFO( " Display Pairs: %s\n", on_off[displayPairs] );
01457   PRINT_INFO( " List Pairs: %s\n", on_off[listPairs] );
01458   PRINT_INFO( " Group Results: %s\n", on_off[groupResults] );
01459   PRINT_INFO( " Across Body|Volume: %s\n", on_off[checkAcrossBodies] );
01460   PRINT_INFO( " Within Body|Volume: %s\n", on_off[checkWithinBodies] );
01461   PRINT_INFO( " Imprint: %s\n", on_off[imprintResults] );
01462 }
01463 
01464 CubitString SurfaceOverlapTool::get_normal_type_setting()
01465 {
01466   if (normalType == 2) {
01467     return CubitString("opposite");
01468   }
01469   else if (normalType == 3) {
01470     return CubitString("same");
01471   }
01472   else {
01473     return CubitString("any");
01474   }
01475 }
01476 
01477 void SurfaceOverlapTool::set_normal_type_setting(CubitString type )
01478 {
01479   if (CubitUtil::compare(type.c_str(), "opposite")) {
01480     normalType = 2;
01481   }
01482   else if (CubitUtil::compare(type.c_str(), "same")) {
01483     normalType = 3;
01484   }
01485   else {
01486     normalType = 1;
01487   }
01488 }
01489 
01490 int SurfaceOverlapTool::get_group_results_setting()
01491 {return groupResults;}
01492 
01493 void SurfaceOverlapTool::set_group_results_setting( int setting )
01494 {groupResults = (setting) ? CUBIT_TRUE : CUBIT_FALSE;}
01495 
01496 int SurfaceOverlapTool::get_list_pairs_setting()
01497 {return listPairs;}
01498 
01499 void SurfaceOverlapTool::set_list_pairs_setting( int setting )
01500 {listPairs = (setting) ? CUBIT_TRUE : CUBIT_FALSE;}
01501 
01502 int SurfaceOverlapTool::get_display_pairs_setting()
01503 {return displayPairs;}
01504 
01505 void SurfaceOverlapTool::set_display_pairs_setting( int setting )
01506 {displayPairs = (setting) ? CUBIT_TRUE : CUBIT_FALSE;}
01507 
01508 int SurfaceOverlapTool::get_facet_ang_tol_setting()
01509 {return facetAngTol;}
01510 
01511 void SurfaceOverlapTool::set_facet_ang_tol_setting( int val )
01512 {facetAngTol=(unsigned short)val;}
01513 
01514 //Imprints the bodies containing the lists of surfaces.  Also
01515 //uses the edges imprinting rather than the normal imprint.
01516 CubitStatus SurfaceOverlapTool::imprint(DLIList<RefFace*> &ref_face_list1,
01517                                         DLIList<RefFace*> &ref_face_list2)
01518 {
01519   //This is a very tricky goal.  The goal is to imprint each pair for the
01520   //two lists.  The problem is that we need to imprint the bodies of the
01521   //surfaces not just the surfaces since this isn't as robust.  The problem
01522   //is that more than one of these surfaces may reference the same body.  So
01523   //in fact as we imprint one of the surfaces, the other ones could get deleted and
01524   //create a memory leak.
01525   
01526   //The only thing I can think of is to use the id's of the bodies as the constant.
01527   //On the imprint, the body id should not change.  So lets create an array of bodies,
01528   //and update the array as they get changed.  The array will allow constant access time.
01529   DLIList <Body*> body_list, temp_bodies;
01530   DLIList <int> body_ids1, body_ids2, modified_list;
01531   DLIList <DLIList<RefEdge*>*> edges_list1, edges_list2;
01532   DLIList <RefEdge*> *ref_edges1, *ref_edges2, tmp_edges;
01533   
01534   CubitBoolean print = CUBIT_TRUE;
01535   Body *tmp_body;
01536   int i, max_id = -1;
01537   
01538     //first get the max id of the bodies here to help us
01539     //get the size of the array.
01540   for ( i = ref_face_list1.size(); i > 0; i-- )
01541   {
01542     temp_bodies.clean_out();
01543     RefFace *ref_face1 = ref_face_list1.get_and_step();
01544     if ( ref_face1 == NULL )
01545     {
01546       PRINT_ERROR("Bad data sent to imprint overlaps.\n");
01547       return CUBIT_FAILURE;
01548     }
01549     ref_face1->bodies(temp_bodies);
01550     if ( temp_bodies.size() != 1 )
01551     {
01552       PRINT_WARNING("Entities must be in one body\n");
01553       PRINT_WARNING("Skipping that entity\n");
01554       ref_face_list2.step();
01555       continue;
01556     }
01557     tmp_body = temp_bodies.get();
01558     temp_bodies.clean_out();
01559     RefFace *ref_face2 = ref_face_list2.get_and_step();
01560     if ( ref_face2 == NULL )
01561     {
01562       PRINT_ERROR("Bad data sent to imprint overlaps.\n");
01563       return CUBIT_FAILURE;
01564     }
01565     ref_face2->bodies(temp_bodies);
01566     if ( temp_bodies.size() != 1 )
01567     {
01568       PRINT_WARNING("Entities must be in one body\n");
01569       PRINT_WARNING("Skipping that entity\n");
01570       continue;
01571     }
01572     if ( tmp_body->id() > max_id )
01573       max_id = tmp_body->id();
01574     body_list.append(tmp_body);
01575     body_ids1.append(tmp_body->id());
01576     body_list.append(temp_bodies.get());
01577     body_ids2.append(temp_bodies.get()->id());
01578     if ( temp_bodies.get()->id() > max_id )
01579       max_id = temp_bodies.get()->id();
01580       //Now set up the edge lists.
01581     ref_edges1 = new DLIList<RefEdge*>;
01582     ref_face1->ref_edges(tmp_edges);
01583     CubitStatus stat = copy_edges_in_list(tmp_edges, *ref_edges1);
01584     if ( stat != CUBIT_SUCCESS )
01585       return CUBIT_FAILURE;
01586     ref_edges2 = new DLIList<RefEdge*>;
01587     tmp_edges.clean_out();
01588     ref_face2->ref_edges(tmp_edges);
01589     stat = copy_edges_in_list(tmp_edges, *ref_edges2);
01590     if ( stat != CUBIT_SUCCESS )
01591       return CUBIT_FAILURE;
01592     edges_list1.append(ref_edges1);
01593     edges_list2.append(ref_edges2);
01594   }
01595     //Now create an array and store all of the bodies.
01596   Body **body_array = new Body* [2*max_id+1];
01597     //initialize the array to null.
01598   for ( i = 0; i < 2*max_id+1; i++ )
01599   {
01600     body_array[i] = (Body*)NULL;
01601   }
01602     //Now put the bodies into the array.
01603   for ( i = body_list.size(); i > 0; i-- )
01604   {
01605     tmp_body = body_list.get_and_step();
01606     body_array[tmp_body->id()] = tmp_body;
01607   }
01608     //Now go through and pairwise imprint the bodies.
01609   DLIList <Body*> bodies, tmp_modified_bodies;
01610   for( i = body_ids1.size(); i > 0; i-- )
01611   {
01612     tmp_modified_bodies.clean_out();
01613     int id1 = body_ids1.get_and_step();
01614     int id2 = body_ids2.get_and_step();
01615     ref_edges1 = edges_list1.get_and_step();
01616     ref_edges2 = edges_list2.get_and_step();
01617     
01618     Body *body1 = body_array[id1];
01619     Body *body2 = body_array[id2];
01620     int body1_num = num_descendants(body1);
01621     int body2_num = num_descendants(body2);
01622     bodies.clean_out();
01623     bodies.append(body2);
01624     CubitStatus stat = GeometryModifyTool::instance()->
01625       imprint(bodies, *ref_edges1, tmp_modified_bodies, CUBIT_FALSE, CUBIT_FALSE);
01626     if ( stat == CUBIT_SUCCESS && tmp_modified_bodies.size() == 1 )
01627     {
01628       body2 = tmp_modified_bodies.get();
01629     }
01630     tmp_modified_bodies.clean_out();
01631     bodies.clean_out();
01632     bodies.append(body1);
01633     stat = GeometryModifyTool::instance()->
01634       imprint(bodies, *ref_edges2, tmp_modified_bodies, CUBIT_FALSE, CUBIT_FALSE);
01635     if ( stat == CUBIT_SUCCESS && tmp_modified_bodies.size() == 1 )
01636     {
01637       body1 = tmp_modified_bodies.get();
01638     }
01639     body_array[id1] = body1;
01640     int temp_num = num_descendants(body1);
01641     if ( temp_num != body1_num )
01642     {
01643       modified_list.append_unique(id1);
01644     }
01645     body_array[id2] = body2;
01646     temp_num = num_descendants(body2);
01647     if ( temp_num != body2_num )
01648     {
01649       modified_list.append_unique(id2);
01650     }
01651   }
01652   if ( modified_list.size() && print )
01653   {
01654     if ( modified_list.size() != 1 )
01655       PRINT_INFO("Imprinting Modified Bodies: ");
01656     else
01657       PRINT_INFO("Imprinting Modified Body: ");
01658     for ( i = 0; i < modified_list.size(); i++ )
01659     {
01660       if ( i != modified_list.size()-1 )
01661       {
01662         if (i%10 == 0 && i != 0 )
01663           PRINT_INFO("%d,\n", modified_list.get_and_step());
01664         else
01665           PRINT_INFO("%d, ", modified_list.get_and_step());
01666       }
01667       else
01668         PRINT_INFO("%d.\n", modified_list.get_and_step());
01669     }
01670   }
01671   else if ( modified_list.size() == 0 && print )
01672     PRINT_INFO("Imprinting overlaps resulted in no modifications.\n");
01673 
01674     //clean up our memory.
01675   for ( i = edges_list1.size(); i > 0; i-- )
01676   {
01677     ref_edges1 =  edges_list1.remove();
01678     ref_edges2 = edges_list2.remove();
01679     delete_edges_in_list(*ref_edges1);
01680     delete_edges_in_list(*ref_edges2);
01681     delete ref_edges1;
01682     delete ref_edges2;
01683   }
01684   delete [] body_array;
01685   return CUBIT_SUCCESS;
01686 }
01687 
01688 int SurfaceOverlapTool::num_descendants(Body *body)
01689 {
01690   int counter = 0;
01691   counter += body->num_ref_volumes();
01692   counter += body->num_ref_faces();
01693   counter += body->num_ref_edges();
01694   counter += body->num_ref_vertices();
01695   return counter;
01696 }
01697 
01698 //---------------------------------------------------------
01699 // copy_edges_in_list:
01700 // copy's each of the edges in the old list, and puts the
01701 // stand alone edges in the new list.
01702 // NOTE: THESE ARE NEWLY CREATED EDGES AND SHOULD BE DELETED
01703 //       BY THE CALLING FUNCTION.
01704 // Author: David R. White
01705 // Date: 1/11/02
01706 //---------------------------------------------------------
01707 CubitStatus SurfaceOverlapTool::copy_edges_in_list(DLIList<RefEdge*> &old_list,
01708                                                    DLIList<RefEdge*> &new_list )
01709 {
01710   int i;
01711   RefEdge *curr_edge, *new_edge;
01712   RefEntity *curr_entity, *new_entity;
01713   
01714   for ( i = old_list.size(); i > 0; i-- )
01715   {
01716     curr_edge = old_list.get_and_step();
01717     curr_entity = CAST_TO(curr_edge, RefEntity);
01718     assert(curr_entity != NULL );
01719     new_entity = GeometryModifyTool::instance()->copy_refentity(curr_entity);
01720     new_edge = CAST_TO(new_entity, RefEdge);
01721     if ( new_edge == NULL )
01722     {
01723       PRINT_ERROR("Problems copying edges for imprinting overlap.\n");
01724       assert(new_edge != NULL );
01725       return CUBIT_FAILURE;
01726     }
01727     new_list.append(new_edge);
01728   }
01729   return CUBIT_SUCCESS;
01730 }
01731 
01732 //Initialize all settings in this class
01733 void SurfaceOverlapTool::initialize_settings()
01734 {
01735   SettingHandler::instance()->add_setting("Overlap Facet BBox Absolute", 
01736     SurfaceOverlapTool::set_facet_abs_tol, 
01737     SurfaceOverlapTool::get_facet_abs_tol); 
01738   
01739   SettingHandler::instance()->add_setting("Overlap Facet BBox Angle", 
01740     SurfaceOverlapTool::set_facet_ang_tol_setting, 
01741     SurfaceOverlapTool::get_facet_ang_tol_setting);
01742   
01743   SettingHandler::instance()->add_setting("Overlap Minimum Gap", 
01744     SurfaceOverlapTool::set_gap_min, 
01745     SurfaceOverlapTool::get_gap_min);  
01746   
01747   SettingHandler::instance()->add_setting("Overlap Maximum Gap",
01748     SurfaceOverlapTool::set_gap_max,
01749     SurfaceOverlapTool::get_gap_max);
01750   
01751   SettingHandler::instance()->add_setting("Overlap Minimum Angle", 
01752     SurfaceOverlapTool::set_angle_min, 
01753     SurfaceOverlapTool::get_angle_min); 
01754   
01755   SettingHandler::instance()->add_setting("Overlap Maximum Angle", 
01756     SurfaceOverlapTool::set_angle_max, 
01757     SurfaceOverlapTool::get_angle_max);
01758   
01759   SettingHandler::instance()->add_setting("Overlap Normal", 
01760     SurfaceOverlapTool::set_normal_type_setting, 
01761     SurfaceOverlapTool::get_normal_type_setting);  
01762   
01763   SettingHandler::instance()->add_setting("Overlap Tolerance",
01764     SurfaceOverlapTool::set_overlap_tolerance,
01765     SurfaceOverlapTool::get_overlap_tolerance);
01766   
01767   SettingHandler::instance()->add_setting("Overlap Group", 
01768     SurfaceOverlapTool::set_group_results_setting, 
01769     SurfaceOverlapTool::get_group_results_setting); 
01770   
01771   SettingHandler::instance()->add_setting("Overlap List", 
01772     SurfaceOverlapTool::set_list_pairs_setting, 
01773     SurfaceOverlapTool::get_list_pairs_setting);
01774   
01775   SettingHandler::instance()->add_setting("Overlap Display", 
01776     SurfaceOverlapTool::set_display_pairs_setting, 
01777     SurfaceOverlapTool::get_display_pairs_setting);
01778   
01779   SettingHandler::instance()->add_setting("Overlap Within Bodies", 
01780     SurfaceOverlapTool::set_check_within_bodies, 
01781     SurfaceOverlapTool::get_check_within_bodies);
01782 
01783   SettingHandler::instance()->add_setting("Overlap Across Bodies", 
01784     SurfaceOverlapTool::set_check_across_bodies, 
01785     SurfaceOverlapTool::get_check_across_bodies);
01786 }
01787 
01788 CubitStatus SurfaceOverlapTool::delete_edges_in_list(DLIList<RefEdge*> &edge_list )
01789 {
01790   int i;
01791   RefEdge *curr_edge;
01792   RefEntity *curr_entity;
01793   
01794   for ( i = edge_list.size(); i > 0; i-- )
01795   {
01796     curr_edge = edge_list.remove();
01797     curr_entity = CAST_TO(curr_edge, RefEntity);
01798     assert(curr_entity != NULL );
01799     CubitStatus stat = GeometryQueryTool::instance()->delete_RefEntity(curr_entity);
01800     if ( stat != CUBIT_SUCCESS )
01801     {
01802       PRINT_ERROR("Problems deleting edges after imprinting overlaps\n");
01803       assert(0);
01804       return CUBIT_FAILURE;
01805     }
01806   }
01807   return CUBIT_SUCCESS;
01808 }
01809 
01810 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<Curve*> &curve_list,
01811                                 DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
01812                                 std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
01813                                 std::multimap<BodySM*, CubitVector> &body_point_imprint_map,
01814                                 double overlap_tol)
01815 {
01816   int i;
01817 
01818   //put all the curves into a tree 
01819   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
01820   if(overlap_tol > 0.0)
01821     tolerance = overlap_tol;
01822 
01823   // Populate the Surface AbstractTree
01824   AbstractTree<Curve*> *a_tree = new RTree<Curve*>( tolerance );
01825   curve_list.reset();
01826   for( i=curve_list.size(); i--; )
01827   {
01828     Curve *curve = curve_list.get_and_step();
01829     a_tree->add( curve );
01830   }
01831 
01832   std::map<Curve*, DLIList<CurveOverlapFacet*>* > facet_map;
01833   std::map<Curve*, DLIList<Curve*>* >::iterator list_iter; 
01834 
01835   curve_list.reset();
01836   for( i=curve_list.size(); i--; )
01837   {
01838     Curve *curve1= curve_list.get_and_step();
01839 
01840     BodySM *curve1_body = curve1->bodysm();
01841 
01842     // Remove this surface from AbstractTree so it is not found and never
01843     // found again
01844     a_tree->remove( curve1 );
01845 
01846     // Find RefFaces from AbstractTree that are within range of this surface
01847     CubitBox curve1_box = curve1->bounding_box();
01848     DLIList<Curve*> close_curves;
01849     a_tree->find( curve1_box, close_curves );
01850 
01851     int j;
01852     for( j=close_curves.size(); j--; )
01853     {
01854       Curve *curve2 = close_curves.get_and_step();
01855       BodySM *curve2_body = curve2->bodysm();
01856       
01857       if( curve2_body == curve1_body )
01858         continue;
01859 
01860       std::multimap<BodySM*, CubitVector> tmp_body_point_imprint_map;
01861 
01862       if( check_overlap( curve1, curve2, &facet_map, &tmp_body_point_imprint_map, overlap_tol  ) ) 
01863       {
01864         //check to see if the curve1 is already overlapping with another curve 
01865         list_iter = curve_to_list_map.find( curve1 );
01866         if( list_iter != curve_to_list_map.end() )
01867         {
01868           DLIList<Curve*> *tmp_curve_list = list_iter->second;
01869           tmp_curve_list->append( curve2 );
01870         }
01871         else
01872         {
01873           //list for curve 1 does not exist....make a new one
01874           DLIList<Curve*> *tmp_curve_list = new DLIList<Curve*>;
01875           overlapping_curve_lists.append( tmp_curve_list );
01876           tmp_curve_list->append( curve1 );
01877           tmp_curve_list->append( curve2 );
01878           curve_to_list_map.insert( std::map<Curve*,
01879                DLIList<Curve*>*>::value_type( curve1, tmp_curve_list ));
01880         }
01881       }
01882       else
01883       {
01884         //append what's in body_point_imprint_map to one passed in
01885         body_point_imprint_map.insert( tmp_body_point_imprint_map.begin(), 
01886                                        tmp_body_point_imprint_map.end() ); 
01887       }
01888     }
01889   }
01890 
01891   //clean up facet map
01892   std::map<Curve*, DLIList<CurveOverlapFacet*>* >::iterator facet_iter;
01893   facet_iter=facet_map.begin(); 
01894   for(; facet_iter != facet_map.end(); facet_iter++ )
01895   {
01896     DLIList<CurveOverlapFacet*> *co_facet_list = facet_iter->second;
01897 
01898     //delete all the facets in the list
01899     for( i=co_facet_list->size(); i--; )
01900       delete co_facet_list->get_and_step();
01901     delete co_facet_list;
01902   }
01903 
01904   delete a_tree;
01905 
01906   return CUBIT_SUCCESS;
01907 }
01908 
01909 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<Surface*> &surf_list,
01910                                 DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
01911                                 std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
01912                                 std::multimap<BodySM*, CubitVector> &body_point_imprint_map)
01913 {
01914   //collect all the surfaces
01915   DLIList<Curve*> curve_list;
01916   int i;
01917   for( i=surf_list.size(); i--; )
01918   {
01919     Surface *surf = surf_list.get_and_step();
01920     DLIList<Curve*> curves;
01921     surf->curves_ignore_virtual(curves, false);
01922 //    body_sm->curves( curves);
01923     curve_list.merge_unique( curves );
01924   }
01925 
01926   return find_overlapping_curves(curve_list, overlapping_curve_lists, curve_to_list_map,
01927     body_point_imprint_map);
01928 }
01929 
01930 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<BodySM*> &body_list,
01931                                 DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
01932                                 std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
01933                                 std::multimap<BodySM*, CubitVector> &body_point_imprint_map,
01934                                 double overlap_tol)
01935 {
01936   //collect all the surfaces
01937   DLIList<Curve*> curve_list;
01938   int i;
01939   for( i=body_list.size(); i--; )
01940   {
01941     BodySM *body_sm = body_list.get_and_step();
01942     DLIList<Curve*> curves;
01943     body_sm->curves_ignore_virtual(curves, false);
01944 //    body_sm->curves( curves);
01945     curve_list.merge_unique( curves );
01946   }
01947 
01948   return find_overlapping_curves(curve_list, overlapping_curve_lists, curve_to_list_map,
01949     body_point_imprint_map, overlap_tol);
01950 
01951 }
01952 
01953 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<Body*> &bodies,
01954                                 std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
01955                                 double maxgap /* =-1*/)
01956 {
01957   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator list_iter; 
01958 
01959   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
01960   if (maxgap != -1 && maxgap != 0.0)
01961       tolerance = maxgap;
01962 
01963   int i,j;
01964   DLIList<Body*> tmp_body_list = bodies;
01965   for(i=tmp_body_list.size(); i--; )
01966   {
01967     Body *tmp_body1 = tmp_body_list.pop();
01968 
01969     tmp_body_list.reset();
01970     for(j=tmp_body_list.size(); j--; )
01971     {
01972       Body *tmp_body2 = tmp_body_list.get_and_step();
01973 
01974       //determine if bodies are close enough to have overlapping curves
01975       CubitBox body_box1 = tmp_body1->bounding_box();
01976       CubitBox body_box2 = tmp_body2->bounding_box();
01977 
01978       if( body_box1.overlap( tolerance, body_box2 ) )
01979       {
01980         // create list of edges on each body.
01981         // put the edges in body2 in edges1 so edges1 contains
01982         // the list of curves contained in the body listed first in the list
01983         DLIList<RefEdge*> edges1, edges2;
01984         tmp_body1->ref_edges( edges2 );
01985         tmp_body2->ref_edges( edges1 );
01986         
01987         //check individual curves for bounding box interference
01988         if (!find_overlapping_curves(edges1, edges2, overlapping_edge_map, tolerance))
01989             return CUBIT_FAILURE;
01990       }
01991     }
01992   }
01993 
01994   return CUBIT_SUCCESS;
01995 }
01996 
01997 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<RefFace*> &faces,
01998                         std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
01999                         double maxgap /*=-1*/)
02000 {
02001   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
02002 
02003   if (maxgap != -1 && maxgap != 0.0)
02004       tolerance = maxgap;
02005 
02006   // Populate the Surface AbstractTree
02007   AbstractTree<RefFace*> *a_tree = new RTree<RefFace*>( tolerance );
02008   faces.reset();
02009   int i;
02010   for( i=faces.size(); i--; )
02011   {
02012     RefFace* face = faces.get_and_step();
02013     a_tree->add( face );
02014   }
02015 
02016   faces.reset();
02017   for( i=faces.size(); i--; )
02018   {
02019     RefFace* face1 = faces.get_and_step();
02020 
02021     Body *face1_body = face1->body();
02022 
02023     // Remove this face from AbstractTree so it is not found and never
02024     // found again
02025     a_tree->remove( face1 );
02026 
02027     // Find RefFaces from AbstractTree that are within range of this surface
02028     CubitBox face1_box = face1->bounding_box();
02029     DLIList<RefFace*> close_faces;
02030     a_tree->find( face1_box, close_faces );
02031 
02032     int j;
02033     for( j=close_faces.size(); j--; )
02034     {
02035       RefFace *face2 = close_faces.get_and_step();
02036       Body *face2_body = face2->body();
02037 
02038       //don't check for overlapping faces within bodies
02039       if( face1_body == face2_body )
02040               continue;
02041 
02042       DLIList<RefEdge*> edges1, edges2;
02043       face1->ref_edges( edges1 );
02044       face2->ref_edges( edges2 );
02045 
02046       if (!find_overlapping_curves(edges1, edges2, overlapping_edge_map, tolerance))
02047               return CUBIT_FAILURE;
02048             
02049     }
02050   }
02051   return CUBIT_SUCCESS;
02052 }
02053 
02054 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<RefEdge*> &edgelist,
02055                 std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map, double maxgap /*=-1*/ )
02056 {
02057   // for now, check every edge against every other edge
02058   // (the helper function will skip edges if they are in the same body)
02059 
02060   DLIList<RefEdge*> edgelist2 = edgelist;
02061   return find_overlapping_curves(edgelist, edgelist2, overlapping_edge_map, maxgap);
02062 }
02063 
02064 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<RefEdge*> &edges1, DLIList<RefEdge*> &edges2,
02065                                               std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
02066                                               double maxgap /*=-1*/)
02067 {
02068   int i;
02069   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > facet_map; 
02070   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator list_iter; 
02071 
02072   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
02073 
02074   if (maxgap != -1 && maxgap != 0.0)
02075       tolerance = maxgap;
02076 
02077   for( i=edges1.size(); i--; )
02078   {
02079     RefEdge *edge1 = edges1.get_and_step(); 
02080 
02081     int j;
02082     for( j=edges2.size(); j--; )
02083     {
02084       RefEdge *edge2 = edges2.get_and_step();
02085       
02086       if( edge1 == edge2 )
02087         continue;
02088 
02089       std::multimap<RefEdge*, RefEdge*>::iterator it;
02090       it = overlapping_edge_map.find( edge2 );
02091       if( it != overlapping_edge_map.end() )
02092         continue;
02093 
02094       // check to see if this pair is already in the overlap map.
02095       //  If it is, don't need to bother checking it for overlap
02096      /* 
02097       std::multimap<RefEdge*, RefEdge*>::iterator it;
02098       std::pair< std::multimap<RefEdge*,RefEdge*>::iterator, std::multimap<RefEdge*,RefEdge*>::iterator > range;
02099 
02100       range = overlapping_edge_map.equal_range(edge1);
02101 
02102       for (it=range.first; it!=range.second; it++)
02103       {
02104         if ( (it->second == edge2) && (it->first == edge1) )
02105                 pair_already_in_map = true;
02106       }
02107       if (pair_already_in_map)
02108         continue; 
02109 
02110       */
02111 
02112       if( check_overlap( edge1, edge2, &facet_map, &tolerance ) ) 
02113       {
02114         overlapping_edge_map.insert( std::multimap<RefEdge*, RefEdge*>
02115                       ::value_type( edge1, edge2));
02116         //PRINT_INFO("Curve %d and %d overlap.\n", edge1->id(), edge2->id());
02117         //PRINT_INFO("Insert Curve %d, Curve %d.\n", edge1->id(), edge2->id());
02118       }
02119     }
02120   }
02121   //clean up facet map
02122   list_iter=facet_map.begin(); 
02123   for(; list_iter != facet_map.end(); list_iter++ )
02124   {
02125     DLIList<CurveOverlapFacet*> *co_facet_list = list_iter->second;
02126     //delete all the facets in the list
02127     for( i=co_facet_list->size(); i--; )
02128             delete co_facet_list->get_and_step();
02129     delete co_facet_list;
02130   }
02131 
02132   return CUBIT_SUCCESS;
02133 }
02134 
02135 CubitBoolean SurfaceOverlapTool::check_overlap( Curve *curve1, Curve *curve2, 
02136   std::map<Curve*, DLIList<CurveOverlapFacet*>* > *facet_map,
02137   std::multimap<BodySM*,CubitVector> *body_point_imprint_map,
02138   double overlap_tol) 
02139 {
02140   //if surfaces are not splines and are not of the same type, 
02141   //they won't overlap
02142   GeometryType curve1_type = curve1->geometry_type();
02143   GeometryType curve2_type = curve2->geometry_type();
02144 
02145   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
02146   if(overlap_tol > 0.0)
02147     tolerance = overlap_tol;
02148 
02149   double facet_tol = tolerance*10;
02150 
02151   std::map<Curve*, DLIList<CurveOverlapFacet*>* >::iterator facet_iterator;
02152 
02153   CubitBox curve_box1 = curve1->bounding_box(); 
02154   CubitBox curve_box2 = curve2->bounding_box();
02155 
02156   DLIList<CurveOverlapFacet*> *facet_list1 = NULL;
02157   DLIList<CurveOverlapFacet*> *facet_list2 = NULL;
02158 
02159   //see if curve is in map...if not we have to create faceting for it.
02160   if( facet_map )
02161     facet_iterator = facet_map->find( curve1 );
02162 
02163   if( facet_map == NULL || facet_iterator == facet_map->end() )
02164   {
02165     facet_list1 = new DLIList<CurveOverlapFacet*>;
02166 
02167     GMem curve_graphics;
02168     curve1->get_geometry_query_engine()->get_graphics( curve1, 
02169       &curve_graphics, 0, facet_tol );
02170 
02171     GPoint *points = curve_graphics.point_list();
02172     int num_points = curve_graphics.pointListCount;
02173 
02174     int kk;
02175     for( kk=0; kk<num_points-1; kk++ )
02176     {
02177       //create a new CurveOverlapFacets
02178       GPoint gpoints[2];
02179       gpoints[0] = points[kk];
02180       gpoints[1] = points[kk + 1];
02181 
02182       CurveOverlapFacet *tmp_facet = new CurveOverlapFacet( gpoints ); 
02183       facet_list1->append( tmp_facet );
02184     }
02185 
02186     if( facet_map )
02187       facet_map->insert( std::map<Curve*, 
02188       DLIList<CurveOverlapFacet*>*>::value_type( curve1, facet_list1 )); 
02189 
02190   }
02191   else
02192     facet_list1 = (*facet_iterator).second;
02193 
02194   //see if edge is in map...if not we have to create facet for it.
02195   if( facet_map )
02196     facet_iterator = facet_map->find( curve2 );
02197 
02198   if( facet_map == NULL || facet_iterator == facet_map->end() )
02199   {
02200     facet_list2 = new DLIList<CurveOverlapFacet*>;
02201 
02202     GMem curve_graphics;
02203     curve2->get_geometry_query_engine()->get_graphics( curve2, 
02204       &curve_graphics, 0, facet_tol );    
02205 
02206     GPoint *points = curve_graphics.point_list();
02207     int num_points = curve_graphics.pointListCount;
02208 
02209     int kk;
02210     for( kk=0; kk<num_points-1; kk++ )
02211     {
02212       //create a new CurveOverlapFacets
02213       GPoint gpoints[2];
02214       gpoints[0] = points[kk];
02215       gpoints[1] = points[kk + 1];
02216 
02217       CurveOverlapFacet *tmp_facet = new CurveOverlapFacet( gpoints ); 
02218       facet_list2->append( tmp_facet );
02219     }
02220 
02221     if( facet_map )
02222       facet_map->insert( std::map<Curve*, 
02223       DLIList<CurveOverlapFacet*>*>::value_type( curve2, facet_list2 )); 
02224   }
02225   else
02226     facet_list2 = (*facet_iterator).second;
02227 
02228   bool overlap = false;
02229   int kk;
02230   if(facet_list1->size() > 0 && facet_list2->size() > 0)
02231   {
02232     //compare smaller list to larger list...want list1 to be smaller
02233     if( facet_list1->size() > facet_list2->size() )
02234     {
02235       DLIList<CurveOverlapFacet*> *tmp_list = facet_list1;
02236       facet_list1 = facet_list2;
02237       facet_list2 = tmp_list;
02238       Curve *tmp_curve = curve1;
02239       curve1 = curve2;
02240       curve2 = tmp_curve;
02241     }
02242 
02243     CubitVector curv1_start_pt;
02244     CubitVector curv2_start_pt;
02245     CubitVector curv1_end_pt;
02246     CubitVector curv2_end_pt;
02247 
02248     facet_list1->reset();
02249     facet_list2->reset();
02250     //get start/end facet points on curves
02251     if( body_point_imprint_map )
02252     {
02253       curv1_start_pt = facet_list1->get()->start_point();
02254       curv2_start_pt = facet_list2->get()->start_point();
02255       facet_list1->last();
02256       facet_list2->last();
02257       curv1_end_pt = facet_list1->get()->end_point();
02258       curv2_end_pt = facet_list2->get()->end_point();
02259     }
02260 
02261     facet_list1->reset();
02262     facet_list2->reset();
02263     double total_overlap = 0.0;
02264     //now determine if enough curve facets overlap
02265 
02266     int list_size1 = facet_list1->size();
02267     for( kk=list_size1; kk--; )
02268     {
02269       CurveOverlapFacet *curr_facet = facet_list1->get_and_step();
02270       if( curr_facet->length() < GEOMETRY_RESABS )
02271         continue;
02272 
02273       //if 'curr_facet' is the first or last facet in curve1,
02274       //check to see if the start/end point is on curve2, and not coincident
02275       //with the start/end point of curve2.  If so, it's a case where you need
02276       //to imprint this start/end point onto the body of curve2.
02277       if( body_point_imprint_map )
02278       {
02279         if( kk == list_size1-1 ) //first facet in curve1
02280         {
02281           CubitVector closest_point;
02282           curve2->closest_point_trimmed( curr_facet->start_point(), closest_point );
02283           if( curv2_start_pt.distance_between( curr_facet->start_point() ) > tolerance &&  
02284               curv2_end_pt.distance_between( curr_facet->start_point() ) > tolerance &&  
02285               closest_point.distance_between( curr_facet->start_point() ) < tolerance )
02286           {
02287             BodySM *tmp_body_sm = curve2->bodysm();
02288             body_point_imprint_map->insert( std::multimap<BodySM*, 
02289               CubitVector>::value_type(
02290               tmp_body_sm, closest_point)); 
02291           }
02292         }
02293         if( kk == 0 ) //last facet in curve1 
02294         {
02295           CubitVector closest_point;
02296           curve2->closest_point_trimmed( curr_facet->end_point(), closest_point );
02297           if( curv2_start_pt.distance_between( curr_facet->end_point() ) > tolerance &&  
02298               curv2_end_pt.distance_between( curr_facet->end_point() ) > tolerance &&  
02299               closest_point.distance_between( curr_facet->end_point() ) < tolerance ) 
02300           {
02301             //insert into vertex-volume imprint map
02302             BodySM *tmp_body_sm = curve2->bodysm();
02303             body_point_imprint_map->insert( std::multimap<BodySM*, 
02304               CubitVector>::value_type(
02305               tmp_body_sm, closest_point)); 
02306           }
02307         }
02308       } 
02309 
02310       //do bounding boxes of facets overlap?
02311       int jj;
02312       int list_size2 = facet_list2->size();
02313       for( jj=list_size2; jj--; )
02314       {
02315         CurveOverlapFacet *other_facet = facet_list2->get_and_step();
02316 
02317         if( curr_facet->bbox_overlap( tolerance, other_facet ) )
02318         {
02319           double distance_between_facets = curr_facet->facet_to_facet_distance( other_facet );
02320           if( distance_between_facets < tolerance+facet_tol )
02321           {
02322             if( other_facet->length() < GEOMETRY_RESABS ) 
02323               continue;
02324 
02325             //if 'other_facet' is the first or last facet in curve1,
02326             //check to see if the start/end point is on curve1, and not coincident
02327             //with the start/end point of curve1.  If so, it's a case where you need
02328             //to imprint this start/end point onto the body of curve1.
02329             if( body_point_imprint_map  )
02330             {
02331               if( jj == list_size2-1 ) //first facet in curve1
02332               {
02333                 CubitVector closest_point;
02334                 curve1->closest_point_trimmed( other_facet->start_point(), closest_point );
02335 
02336                 if( curv1_start_pt.distance_between( other_facet->start_point() ) > tolerance &&  
02337                     curv1_end_pt.distance_between( other_facet->start_point() ) > tolerance &&  
02338                     closest_point.distance_between( other_facet->start_point() ) < tolerance )
02339                 {
02340                   //insert into vertex-volume imprint map
02341                   BodySM *tmp_body_sm = curve1->bodysm();
02342                   body_point_imprint_map->insert( std::multimap<BodySM*, 
02343                     CubitVector>::value_type(
02344                     tmp_body_sm, closest_point )); 
02345                 }
02346               }
02347               if( jj == 0 ) //last facet in curve1 
02348               {
02349                 CubitVector closest_point;
02350                 curve1->closest_point_trimmed( other_facet->end_point(), closest_point );
02351                 if( curv1_start_pt.distance_between( other_facet->end_point() ) > tolerance &&  
02352                     curv1_end_pt.distance_between( other_facet->end_point() ) > tolerance &&  
02353                     closest_point.distance_between( other_facet->end_point() ) < tolerance )
02354                 {
02355                   //insert into vertex-volume imprint map
02356                   BodySM *tmp_body_sm = curve1->bodysm();
02357                   body_point_imprint_map->insert( std::multimap<BodySM*, 
02358                     CubitVector>::value_type(
02359                     tmp_body_sm, closest_point )); 
02360                 }
02361               }
02362             }
02363 
02364             //get the long and short facet edge
02365             double curr_facet_length = curr_facet->length();
02366             double other_facet_length = other_facet->length();
02367             CurveOverlapFacet *long_facet = ( curr_facet_length > other_facet_length ?
02368                                                curr_facet : other_facet );
02369             CurveOverlapFacet *short_facet = curr_facet;
02370             if( long_facet == curr_facet )
02371                 short_facet = other_facet;
02372                 
02373             //make sure both endpoints or one endpoint and the midpoint 
02374             // of the smaller facet edge lie within a radius
02375             //of merge tolerance + facet tolerance to an infinite line defined 
02376             // by longer facet edge
02377             CubitVector direction = long_facet->end_point() - long_facet->start_point();
02378             double dist1 = short_facet->start_point().distance_from_infinite_line(
02379               long_facet->start_point(), direction );
02380             double dist2 = short_facet->end_point().distance_from_infinite_line(
02381               long_facet->start_point(), direction );
02382 
02383             if( dist2 > tolerance+facet_tol && dist1 > tolerance+facet_tol )
02384               continue;
02385 
02386             CubitVector facet_mid_point = (short_facet->end_point() + short_facet->start_point()) * 0.5;
02387 
02388             double dist_to_midpoint = facet_mid_point.distance_from_infinite_line(
02389               long_facet->start_point(), direction );               
02390       
02391             if( dist_to_midpoint <= tolerance+facet_tol && (dist2 <= tolerance+facet_tol || dist1 <= tolerance+facet_tol ))
02392             {              
02393               double overlap_tolerance = 
02394                 curr_facet->length() < other_facet->length() ? curr_facet->length():
02395                 other_facet->length();
02396               overlap_tolerance *= 0.01;
02397 
02398               //how much of the facet overlaps?
02399               double tmp_overlap = curr_facet->distance_overlapping( other_facet ) ;
02400               if( tmp_overlap > overlap_tolerance )
02401                 total_overlap += tmp_overlap;
02402 
02403               if( total_overlap > tolerance )
02404               {
02405                 overlap = true;
02406                 break;
02407               }
02408             }
02409           }
02410         }
02411       }
02412       if( overlap == true )
02413         break;
02414     } 
02415   }
02416 
02417   if( facet_map == NULL )
02418   {
02419     //clean up facets and list
02420     for( kk=facet_list1->size(); kk--; )
02421       delete facet_list1->get_and_step();
02422     for( kk=facet_list2->size(); kk--; )
02423       delete facet_list2->get_and_step();
02424 
02425     delete facet_list1; 
02426     delete facet_list2; 
02427   }
02428 
02429   if( overlap == false )
02430     return CUBIT_FALSE;
02431 
02432   if( curve1_type == SPLINE_CURVE_TYPE  || 
02433       curve2_type == SPLINE_CURVE_TYPE ) 
02434   {
02435     //measure between the 2 curves
02436     double dist_between_curves = 0;
02437     CubitVector point_on_curve1, point_on_curve2;
02438     GeometryQueryTool::instance()->entity_entity_distance(curve1, curve2,
02439       point_on_curve1, point_on_curve2, dist_between_curves);
02440 
02441     if( dist_between_curves > tolerance )
02442         return CUBIT_FALSE;
02443 
02444     //the curvature at the same spot on the curve could be almost the same
02445     //if curvatures at midpoint are not the same, they don't overlap
02446     CubitVector curvature1, curvature2;
02447     CubitVector tangent, closest_location;
02448     curve1->closest_point( point_on_curve1, closest_location, &tangent, &curvature1 ); 
02449     curve2->closest_point( point_on_curve2, closest_location, &tangent, &curvature2 ); 
02450 
02451     double rad1 = curvature1.length();
02452     double rad2 = curvature2.length();
02453       
02454     //if curvatures are more than 10% off 
02455     double curvature_diff = fabs( rad1 - rad2 );
02456 
02457     if( rad1 > GEOMETRY_RESABS || rad2 > GEOMETRY_RESABS ) 
02458     {
02459       if( curvature_diff/( (fabs(rad1) + fabs(rad2))/2 ) > 0.1 )
02460         return CUBIT_FALSE;
02461     }
02462   }
02463   else if( curve1_type == ARC_CURVE_TYPE && 
02464            curve2_type == ARC_CURVE_TYPE ) 
02465   {
02466     //if both curves are arcs, make sure radii are almost the same
02467     CubitVector mid_point1, mid_point2;
02468     curve1->mid_point( mid_point1 );
02469     curve2->mid_point( mid_point2 );
02470     
02471     CubitVector dummy_vec;
02472     CubitVector curvature1;
02473     CubitVector curvature2;
02474     curve1->closest_point( mid_point1, dummy_vec, NULL, &curvature1 );
02475     curve2->closest_point( mid_point2, dummy_vec, NULL, &curvature2 );
02476     
02477     double rad1 = 1/curvature1.length();
02478     double rad2 = 1/curvature2.length();
02479 
02480     if( fabs( rad1 - rad2 ) > tolerance )
02481       return CUBIT_FALSE; 
02482   }
02483   else
02484     return CUBIT_TRUE;
02485   
02486   return CUBIT_TRUE;
02487 }
02488 
02489 CubitBoolean SurfaceOverlapTool::check_overlap( RefEdge *edge1, RefEdge *edge2, 
02490   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > *facet_map,
02491   double *overlap_tol ) 
02492 {
02493   //if edges are not splines and are not of the same type, 
02494   //they won't overlap
02495   if( (edge1->get_curve_ptr()->geometry_type() != SPLINE_CURVE_TYPE  &&
02496        edge2->get_curve_ptr()->geometry_type() != SPLINE_CURVE_TYPE) &&
02497       (edge1->get_curve_ptr()->geometry_type() != 
02498        edge2->get_curve_ptr()->geometry_type() )) 
02499     return CUBIT_FALSE;
02500 
02501   // we don't want to consider edges from the same body
02502   if (edge1->body() == edge2->body())
02503       return CUBIT_FALSE;
02504 
02505 
02506   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
02507   if( overlap_tol )
02508     tolerance = *overlap_tol;
02509     
02510 
02511   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator facet_iterator;
02512   CubitBox edge_box1 = edge1->bounding_box(); 
02513   CubitBox edge_box2 = edge2->bounding_box();
02514 
02515   //do bounding boxes overlap
02516   if( edge_box1.overlap( tolerance, edge_box2 ) )
02517   {
02518     //curves must overlap at least by 100th of the smaller curve's length
02519     double min_overlap = 0.0;
02520     double edge1_length = edge1->measure();
02521     double edge2_length = edge2->measure();
02522     if( edge1_length < edge2_length )
02523       min_overlap = edge1->measure() * 0.01;
02524     else 
02525       min_overlap = edge2->measure() * 0.01;
02526 
02527     DLIList<CurveOverlapFacet*> *facet_list1 = NULL;
02528     DLIList<CurveOverlapFacet*> *facet_list2 = NULL;
02529 
02530     //see if edge is in map...if not we have to create faceting for it.
02531     if( facet_map )
02532       facet_iterator = facet_map->find( edge1 );
02533 
02534     if( facet_map == NULL || facet_iterator == facet_map->end() )
02535     {
02536       facet_list1 = new DLIList<CurveOverlapFacet*>;
02537 
02538       GMem curve_graphics;
02539       edge1->get_graphics( curve_graphics );
02540 
02541       GPoint *points = curve_graphics.point_list();
02542       int num_points = curve_graphics.pointListCount;
02543 
02544       int kk;
02545       for( kk=0; kk<num_points-1; kk++ )
02546       {
02547         //create a new CurveOverlapFacets
02548         GPoint gpoints[2];
02549         gpoints[0] = points[kk];
02550         gpoints[1] = points[kk + 1];
02551 
02552         CurveOverlapFacet *tmp_facet = new CurveOverlapFacet( gpoints ); 
02553         facet_list1->append( tmp_facet );
02554       }
02555       
02556       if( facet_map )
02557         facet_map->insert( std::map<RefEdge*, 
02558           DLIList<CurveOverlapFacet*>*>::value_type( edge1, facet_list1 )); 
02559     }
02560     else
02561       facet_list1 = (*facet_iterator).second;
02562 
02563     //see if edge is in map...if not we have to create facet for it.
02564     if( facet_map )
02565       facet_iterator = facet_map->find( edge2 );
02566 
02567     if( facet_map == NULL || facet_iterator == facet_map->end() )
02568     {
02569       facet_list2 = new DLIList<CurveOverlapFacet*>;
02570 
02571       GMem curve_graphics;
02572       edge2->get_graphics( curve_graphics );
02573 
02574       GPoint *points = curve_graphics.point_list();
02575       int num_points = curve_graphics.pointListCount;
02576 
02577       int kk;
02578       for( kk=0; kk<num_points-1; kk++ )
02579       {
02580         //create a new CurveOverlapFacets
02581         GPoint gpoints[2];
02582         gpoints[0] = points[kk];
02583         gpoints[1] = points[kk + 1];
02584 
02585         CurveOverlapFacet *tmp_facet = new CurveOverlapFacet( gpoints ); 
02586         facet_list2->append( tmp_facet );
02587       }
02588       
02589       if( facet_map )
02590         facet_map->insert( std::map<RefEdge*, 
02591           DLIList<CurveOverlapFacet*>*>::value_type( edge2, facet_list2 )); 
02592     }
02593     else
02594       facet_list2 = (*facet_iterator).second;
02595     
02596     //compare smaller list to larger list...want list1 to be smaller
02597     if( facet_list1->size() > facet_list2->size() )
02598     {
02599       DLIList<CurveOverlapFacet*> *tmp_list = facet_list1;
02600       facet_list1 = facet_list2;
02601       facet_list2 = tmp_list;
02602     }
02603 
02604     facet_list1->reset();
02605     facet_list2->reset();
02606     int kk;
02607     double total_overlap = 0.0;
02608     bool overlap = false;
02609     //now determine if enough curve facets overlap
02610     for( kk=facet_list1->size(); kk--; )
02611     {
02612       CurveOverlapFacet *curr_facet = facet_list1->get_and_step();
02613 
02614       //do bounding boxes of facets overlap?
02615       int jj;
02616       for( jj=facet_list2->size(); jj--; )
02617       {
02618         CurveOverlapFacet *other_facet = facet_list2->get_and_step();
02619 
02620         if( curr_facet->bbox_overlap( tolerance, other_facet ) )
02621         {
02622           if( curr_facet->facet_to_facet_distance( other_facet ) < tolerance )
02623           {
02624 
02625             //are facets parallel within some tolerance angle?
02626             double angle = curr_facet->angle( other_facet ); 
02627             if( angle < 1 || fabs(180-angle ) < 1 )
02628             {
02629               double overlap_tolerance = 
02630                 curr_facet->length() < other_facet->length() ? curr_facet->length():
02631                 other_facet->length();
02632               overlap_tolerance *= 0.01;
02633               
02634               //how much of the facet overlaps?
02635               double tmp_overlap = curr_facet->distance_overlapping( other_facet ) ;
02636               if( tmp_overlap > overlap_tolerance )
02637                 total_overlap += tmp_overlap;
02638 
02639               if( total_overlap > min_overlap )
02640               {
02641                 if( facet_map == NULL )
02642                 {
02643                   //clean up facets and list
02644                   int i;
02645                   for( i=facet_list1->size(); i--; )
02646                     delete facet_list1->get_and_step();
02647                   for( i=facet_list2->size(); i--; )
02648                     delete facet_list2->get_and_step();
02649 
02650                   delete facet_list1; 
02651                   delete facet_list2; 
02652                 }
02653                 overlap = true;
02654                 break;
02655               }
02656             }
02657           }
02658         }
02659       }
02660       if( overlap == true )
02661         break;
02662     }
02663     if( overlap == false )
02664       return CUBIT_FALSE;
02665 
02666     if( edge1->get_curve_ptr()->geometry_type() == SPLINE_CURVE_TYPE  || 
02667         edge2->get_curve_ptr()->geometry_type() == SPLINE_CURVE_TYPE ) 
02668     {
02669       //measure between the 2 curves
02670       double dist_between_edges = 0;
02671       CubitVector point_on_edge1, point_on_edge2;
02672       GeometryQueryTool::instance()->entity_entity_distance( edge1, edge2, 
02673                                                 point_on_edge1, point_on_edge2, dist_between_edges );
02674     
02675       if( dist_between_edges > tolerance )
02676         return CUBIT_FALSE;
02677 
02678       //the curvature at the same spot on the curve could be almost the same
02679       //if curvature's at midpoint are not the same, they don't overlap
02680       CubitVector curvature1, curvature2;
02681       CubitVector tangent, closest_location;
02682       edge1->closest_point( point_on_edge1, closest_location, &tangent, &curvature1 ); 
02683       edge2->closest_point( point_on_edge2, closest_location, &tangent, &curvature2 ); 
02684 
02685       double rad1 = curvature1.length();
02686       double rad2 = curvature2.length();
02687         
02688       //if curvatures are more than 10% off 
02689       double curvature_diff = fabs( rad1 - rad2 );
02690 
02691       if( (rad1 || rad2 ) && 
02692          (rad1 > GEOMETRY_RESABS ||   //radii must be of significance even look at  
02693           rad2 > GEOMETRY_RESABS ))
02694       {
02695         if( curvature_diff/( (fabs(rad1) + fabs(rad2))/2 ) > 0.1 )
02696           return CUBIT_FALSE;
02697       }
02698     }
02699     else
02700       return CUBIT_TRUE;
02701   }
02702   else
02703     return CUBIT_FALSE;
02704   
02705   return CUBIT_TRUE;
02706 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines