cgma
ChollaEngine.cpp
Go to the documentation of this file.
00001 //- Class:       ChollaEngine
00002 //- Description: Creates the topology for a given geometry described by facets.
00003 //- Owner:       Steven J. Owen
00004 //- Checked by:
00005 //- Version:
00006 //#include <list>
00007 #include <set>
00008 #include <map>
00009 #include <vector>
00010 #include "CubitDefines.h"
00011 #include "ChollaEngine.hpp"
00012 #include "DLIList.hpp"
00013 #include "TDGeomFacet.hpp"
00014 #include "CastTo.hpp"
00015 #include "ChollaSkinTool.hpp"
00016 #include "ChollaVolume.hpp"
00017 #include "ChollaSurface.hpp"
00018 #include "ChollaCurve.hpp"
00019 #include "ChollaPoint.hpp"
00020 #include "CubitFacet.hpp"
00021 #include "CubitFacetData.hpp"
00022 #include "CubitFacetEdge.hpp"
00023 #include "CubitFacetEdgeData.hpp"
00024 #include "CubitPoint.hpp"
00025 #include "CubitPointData.hpp"
00026 #include "FacetEntity.hpp"
00027 #include "FacetEvalTool.hpp"
00028 #include "FacetDataUtil.hpp"
00029 #include "ChollaDebug.hpp"
00030 #include "TDFacetBoundaryEdge.hpp"
00031 #include "TDFacetBoundaryPoint.hpp"
00032 #include "CurveFacetEvalTool.hpp"
00033 #include "Cholla.h"
00034 #include "GfxDebug.hpp"
00035 #include "TDFacetboolData.hpp"
00036 #include "GMem.hpp"
00037 
00038 //============================================================================
00039 //Function:  ChollaEngine (PUBLIC) (constructor)
00040 //============================================================================
00041 ChollaEngine::ChollaEngine()
00042 {
00043   hashCurveArray = NULL;
00044   hashCurveSize = 0;
00045   hashPointArray = NULL;
00046   hashPointSize = 0;
00047 }
00048 
00049 //============================================================================
00050 //Function:  ChollaEngine (PUBLIC) (constructor)
00051 //============================================================================
00052 ChollaEngine::ChollaEngine(DLIList<FacetEntity*> &face_list,
00053                            DLIList<FacetEntity*> &edge_list,
00054                            DLIList<FacetEntity*> &point_list )
00055 {
00056   faceList = face_list;
00057   edgeList = edge_list;
00058   pointList = point_list;
00059   set_up_tool_datas();
00060   hashCurveArray = NULL;
00061   hashCurveSize = 0;
00062   hashPointArray = NULL;
00063   hashPointSize = 0;
00064   doFlip = CUBIT_FALSE;
00065 }
00066 
00067 //============================================================================
00068 //Function:  ChollaEngine (PUBLIC) (constructor)
00069 //============================================================================
00070 ChollaEngine::ChollaEngine(DLIList<CubitFacet*>     &facet_list,
00071                            DLIList<CubitFacetEdge*> &edge_list,
00072                            DLIList<CubitPoint*>     &point_list )
00073 {
00074   CAST_LIST(facet_list, faceList, FacetEntity);
00075   CAST_LIST(edge_list, edgeList, FacetEntity);
00076   CAST_LIST(point_list, pointList, FacetEntity);
00077   set_up_tool_datas();
00078   hashCurveArray = NULL;
00079   hashCurveSize = 0;
00080   hashPointArray = NULL;
00081   hashPointSize = 0;
00082   doFlip = CUBIT_FALSE;
00083 }
00084 
00085 //============================================================================
00086 //Function:  ChollaEngine (PUBLIC) (constructor)
00087 //Notes: This case is used only when the cholla entities have been generated 
00088 //       directly rather than using create_geometry
00089 //       Does not use the TDGeomFacet Tooldatas
00090 //============================================================================
00091 ChollaEngine::ChollaEngine(DLIList<CubitFacet*>     &facet_list,
00092                            DLIList<CubitFacetEdge*> &edge_list,
00093                            DLIList<CubitPoint*>     &point_list,
00094                            DLIList<ChollaVolume *>  &cholla_volumes,
00095                            DLIList<ChollaSurface *> &cholla_surfaces,
00096                            DLIList<ChollaCurve *>   &cholla_curves,
00097                            DLIList<ChollaPoint *>   &cholla_points )
00098 {
00099   CAST_LIST(facet_list, faceList, FacetEntity);
00100   CAST_LIST(edge_list, edgeList, FacetEntity);
00101   CAST_LIST(point_list, pointList, FacetEntity);
00102   //set_up_tool_datas();  TDGeomFacet tooldatas should have already been added
00103 
00104   hashCurveArray = NULL;
00105   hashCurveSize = 0;
00106   hashPointArray = NULL;
00107   hashPointSize = 0;
00108   doFlip = CUBIT_FALSE;
00109   
00110   chollaVolumeList = cholla_volumes;
00111   chollaSurfaceList = cholla_surfaces;
00112   chollaCurveList = cholla_curves;
00113   chollaPointList = cholla_points;
00114 }
00115                           
00116 
00117 //============================================================================
00118 //Function:  set_up_tool_datas
00119 //============================================================================
00120 void ChollaEngine::set_up_tool_datas( )
00121 {
00122   int ii;
00123   FacetEntity *fe_ptr;
00124   for (ii=0; ii<faceList.size(); ii++)
00125   {
00126     fe_ptr = faceList.get_and_step();
00127     TDGeomFacet::add_geom_facet( fe_ptr, -1 );
00128   }
00129   for (ii=0; ii<pointList.size(); ii++)
00130   {
00131     fe_ptr = pointList.get_and_step();
00132     TDGeomFacet::add_geom_facet( fe_ptr, -1 );
00133   }
00134 }
00135 
00136 CubitStatus ChollaEngine::build_eval_tools()
00137 {
00138   CubitBoolean use_feature_angle = CUBIT_FALSE; 
00139   double min_dot = 0.0;                    
00140   int interp_order = 0;                 
00141   CubitBoolean smooth_non_manifold = CUBIT_FALSE;
00142   CubitBoolean split_surfaces = CUBIT_FALSE;
00143 
00144   return build_eval_tools( chollaSurfaceList,
00145                            chollaCurveList,
00146                            interp_order, use_feature_angle, 
00147                            min_dot, smooth_non_manifold,
00148                            split_surfaces );
00149 }
00150 
00151 //============================================================================
00152 //Function:  delete_tool_datas
00153 //============================================================================
00154 void ChollaEngine::delete_tool_datas( )
00155 {
00156   int ii;
00157   FacetEntity *fe_ptr;
00158   for (ii=0; ii<faceList.size(); ii++)
00159   {
00160     fe_ptr = faceList.get_and_step();
00161     fe_ptr->delete_TD( &TDGeomFacet::is_geom_facet );
00162   }
00163   for (ii=0; ii<edgeList.size(); ii++)
00164   {
00165     fe_ptr = edgeList.get_and_step();
00166     fe_ptr->delete_TD( &TDGeomFacet::is_geom_facet );
00167   }
00168   for (ii=0; ii<pointList.size(); ii++)
00169   {
00170     fe_ptr = pointList.get_and_step();
00171     fe_ptr->delete_TD( &TDGeomFacet::is_geom_facet );
00172   }
00173 }
00174 
00175 //============================================================================
00176 //Function:  delete_eval_tools
00177 //============================================================================
00178 void ChollaEngine::delete_eval_tools()
00179 {
00180 
00181   delete_tool_datas();
00182   int ii;
00183   ChollaSurface *cs_ptr = NULL;
00184   FacetEvalTool *fe_tool_ptr;
00185   for (ii = chollaSurfaceList.size(); ii > 0; ii-- )
00186   {
00187     cs_ptr = chollaSurfaceList.get_and_step();
00188     fe_tool_ptr = cs_ptr->get_eval_tool();
00189     if (fe_tool_ptr)
00190       delete fe_tool_ptr;
00191   }
00192   ChollaCurve *cc_ptr = NULL;
00193   CurveFacetEvalTool *ce_tool_ptr;
00194   for (ii = chollaCurveList.size(); ii > 0; ii-- )
00195   {
00196     cc_ptr = chollaCurveList.get_and_step();
00197     ce_tool_ptr = cc_ptr->get_eval_tool();
00198     if (ce_tool_ptr)
00199       delete ce_tool_ptr;
00200   }
00201   faceList.clean_out();
00202   edgeList.clean_out();
00203   pointList.clean_out();
00204 }
00205 
00206 //============================================================================
00207 //Function:  delete_eval_tools_but_not_facets
00208 //============================================================================
00209 void ChollaEngine::delete_eval_tools_but_not_facets()
00210 {
00211 
00212   delete_tool_datas();
00213   int ii;
00214   ChollaSurface *cs_ptr = NULL;
00215   FacetEvalTool *fe_tool_ptr;
00216   for (ii = chollaSurfaceList.size(); ii > 0; ii-- )
00217   {
00218     cs_ptr = chollaSurfaceList.get_and_step();
00219     fe_tool_ptr = cs_ptr->get_eval_tool();
00220     if (fe_tool_ptr)
00221     {
00222       DLIList<CubitFacet *>facets;
00223       fe_tool_ptr->remove_facets(facets);
00224       delete fe_tool_ptr;
00225     }
00226   }
00227   ChollaCurve *cc_ptr = NULL;
00228   CurveFacetEvalTool *ce_tool_ptr;
00229   for (ii = chollaCurveList.size(); ii > 0; ii-- )
00230   {
00231     cc_ptr = chollaCurveList.get_and_step();
00232     ce_tool_ptr = cc_ptr->get_eval_tool();
00233     if (ce_tool_ptr)
00234     {
00235       delete ce_tool_ptr;
00236     }
00237   }
00238   faceList.clean_out();
00239   edgeList.clean_out();
00240   pointList.clean_out();
00241 }
00242 
00243 //============================================================================
00244 //Function:  ~ChollaEngine (PUBLIC) (destructor)
00245 //============================================================================
00246 ChollaEngine::~ChollaEngine()
00247 {
00248 }
00249 
00250 //============================================================================
00251 //Function:  delete (PUBLIC)
00252 //Description: removes all cholla entities stored with the cholla engine
00253 //             usually called before destructor
00254 //============================================================================
00255 void ChollaEngine::delete_me()
00256 {
00257   delete_tool_datas();
00258   int ii;
00259     //clean up any data remaining.
00260   for (ii = chollaPointList.size(); ii > 0; ii-- )
00261     delete chollaPointList.remove();
00262   for (ii = chollaCurveList.size(); ii > 0; ii-- )
00263     delete chollaCurveList.remove();
00264   for (ii = chollaSurfaceList.size(); ii > 0; ii-- )
00265     delete chollaSurfaceList.remove();
00266   
00267 }
00268 
00269 //==================================================================================
00270 //Function:  create_geometry (PUBLIC)
00271 //Description:  Interface function to acutally create the topology
00272 //              for the given mesh.
00273 //==================================================================================
00274 CubitStatus ChollaEngine::create_geometry(
00275   CubitBoolean use_feature_angle,   // use an angle to define where to break surfaces
00276   double angle,                     // the feature angle
00277   int interp_order,                 // 0=linear, 4=b-spline patches
00278   CubitBoolean smooth_non_manifold, // check for continuity accross >2 valence edges
00279   CubitBoolean split_surfaces)      // create new FacetEntities to split surfaces at
00280                                     // at features.  Otherwise - don't mess with the
00281                                     // FacetEntities. (creates TDs instead)
00282 
00283 {
00284   if (0)
00285   {
00286     dump("cyl.cholla", angle);
00287   }
00288 
00289   //- convert feature angle to a dot product
00290 
00291   double min_dot = 0.0;
00292   if (use_feature_angle)
00293   {
00294     if (angle > 180.0) angle = 180.0;
00295     if (angle < 0.0) angle = 0.0;
00296     double rad_angle = (180.0 - angle) * CUBIT_PI / 180.0;
00297     min_dot = cos( rad_angle );
00298   }
00299 
00300   //- create one facet surface to start with
00301 
00302   ChollaSkinTool c_skin_tool;
00303   ChollaSurface *cholla_surface_ptr = NULL;
00304   CubitStatus stat = c_skin_tool.skin_2d(faceList, cholla_surface_ptr);
00305   if ( stat != CUBIT_SUCCESS )
00306     return stat;
00307   if ( cholla_surface_ptr )
00308     chollaSurfaceList.append(cholla_surface_ptr);
00309 
00310   // before building the surfaces, orient the facets so they are consistent
00311   
00312   DLIList<CubitFacet *>total_facet_list;
00313   CAST_LIST( faceList, total_facet_list, CubitFacet );
00314   //stat = check_all_facet_orientations( total_facet_list, doFlip );
00315   if (stat!=CUBIT_SUCCESS)
00316     return stat;
00317   
00318   // generate the topology from the facets
00319 
00320   stat = create_volume_boundaries( chollaSurfaceList,
00321                                    use_feature_angle, min_dot, 
00322                                    split_surfaces );
00323   if ( stat == CUBIT_FAILURE )
00324     return stat;
00325 
00326   stat = create_surface_boundaries( chollaSurfaceList, chollaCurveList,
00327                                     use_feature_angle, min_dot );
00328   if ( stat == CUBIT_FAILURE )
00329     return stat;
00330 
00331   stat = create_curve_boundaries( chollaCurveList, chollaPointList );
00332   if ( stat == CUBIT_FAILURE )
00333     return stat;
00334 
00335     // Okay.  Now we are ready to actually build the geometry.
00336   int mydebug = 0;
00337   if (mydebug)
00338     print_me();
00339 
00340   stat = build_eval_tools( chollaSurfaceList,
00341                            chollaCurveList,
00342                            interp_order, use_feature_angle, 
00343                            min_dot, smooth_non_manifold,
00344                            split_surfaces );
00345 
00346   return stat;
00347 }
00348 
00349 //=============================================================================
00350 //Function:  create_volume_boundaries (PRIVATE)
00351 //Description: creates the surfaces based on the sideset and element block
00352 //             information
00353 //Author: sjowen
00354 //Date: 10/17/00
00355 //=============================================================================
00356 CubitStatus ChollaEngine::create_volume_boundaries( 
00357   DLIList<ChollaSurface*> &cholla_surface_sheets,  // output global list of surfaces
00358   CubitBoolean use_feature_angle,   // define surfaces based on feature angle
00359   double min_dot,      // minimum dot product between face normals
00360   CubitBoolean split_surfaces )  // create new FacetEntities to split surfaces at
00361                                  // at features.  Otherwise - don't mess with the
00362                                  // FacetEntities. (creates TDs instead)
00363 {
00364   CubitStatus rv = CUBIT_SUCCESS;
00365 
00366   // Split these surfaces so that there is only one set of continuous
00367   // faces per surface 
00368 
00369   int ii;
00370   int num_surfaces = cholla_surface_sheets.size();
00371   cholla_surface_sheets.reset();
00372   for ( ii = num_surfaces; ii > 0; ii-- )
00373   {
00374 
00375     ChollaSurface *chsurf_ptr = cholla_surface_sheets.get_and_step();
00376 
00377     DLIList<FacetEntity*> surf_facet_list;
00378     FacetEntity *sfacet;    
00379     chsurf_ptr->get_facets(surf_facet_list);
00380     DLIList<CubitFacet*> facet_list;
00381     CubitFacet *facet;
00382     CubitFacetEdge *fedge;
00383     int kk, mm;
00384     int mydebug = 0;
00385     if(mydebug){
00386       GfxDebug::clear();
00387     }
00388     DLIList<CubitFacetEdge *> feature_edge_list;
00389     for ( kk = surf_facet_list.size(); kk > 0; kk-- ) {
00390       sfacet = surf_facet_list.get_and_step();
00391       facet_list.clean_out();
00392       sfacet->facets(facet_list);
00393       facet = facet_list.get();
00394       TDFacetboolData* tdf = TDFacetboolData::get(facet);
00395       if ( tdf ) {
00396         int *cptr;
00397         cptr = tdf->get_edge_indices( (bool) facet->is_backwards());
00398         for ( mm = 0; mm < 3; mm++ ) {
00399           if ( cptr[mm] != 0 ) {
00400             fedge = facet->edge((2+mm)%3);
00401             if(mydebug){
00402               if(facet->is_backwards()){
00403                 facet->edge((1+mm)%3)->debug_draw(CUBIT_GREEN_INDEX);
00404                 facet->edge((mm)%3)->debug_draw(CUBIT_RED_INDEX);
00405               
00406                 fedge->debug_draw(CUBIT_BLUE_INDEX);
00407               }
00408               else
00409                 fedge->debug_draw(CUBIT_WHITE_INDEX);
00410             }
00411             
00412             TDGeomFacet::add_geom_facet(fedge, -1);
00413             fedge->set_as_feature();
00414             feature_edge_list.append( fedge );
00415           }            
00416         }
00417       }
00418     }
00419     if(mydebug){
00420       GfxDebug::mouse_xforms();
00421     }
00422     // make a list of feature edges
00423 
00424     rv = chsurf_ptr->add_preexisting_feature_edges( feature_edge_list );
00425         if (rv != CUBIT_SUCCESS)
00426             return rv;
00427         
00428     if (use_feature_angle)
00429     {
00430       rv = chsurf_ptr->feature_angle( min_dot, feature_edge_list );
00431     }
00432     else
00433     {
00434       rv = chsurf_ptr->non_manifold_edges( feature_edge_list );
00435     }
00436     if (rv != CUBIT_SUCCESS)
00437       return rv;
00438 
00439      // crack the surface at the feature edges.  create new edges and
00440      // points so the facet representation is discontinuous.
00441 
00442     rv = make_features( feature_edge_list, split_surfaces );
00443     if (rv != CUBIT_SUCCESS)
00444        return rv;
00445 
00446     // split up the surface
00447 
00448     rv = chsurf_ptr->split_surface( cholla_surface_sheets );
00449     if (rv != CUBIT_SUCCESS)
00450        return rv;
00451   }
00452 
00453   // Clean up any edges that do not form complete loops as a result of 
00454   // feature angle.  For this implementation we will allow features to exist
00455   // within the surface without defining a complete loop. -- so the next
00456   // piece of code is never executed.
00457 
00458   CubitBoolean use_complete_loops_only = CUBIT_FALSE;
00459   if (use_feature_angle && use_complete_loops_only)
00460   {
00461     for ( ii = cholla_surface_sheets.size(); ii > 0; ii-- )
00462     {
00463       ChollaSurface *chsurf_ptr = cholla_surface_sheets.get_and_step();
00464       chsurf_ptr->clean_features();
00465     }
00466   }
00467 
00468   // Now that we've broken everything into surfaces, update the surface IDs
00469   // on the boundary facet tool data
00470 
00471   if (!split_surfaces)
00472   {
00473     for ( ii = cholla_surface_sheets.size(); ii > 0; ii-- )
00474     {
00475       ChollaSurface *chsurf_ptr = cholla_surface_sheets.get_and_step();
00476       chsurf_ptr->update_boundary_tool_data();
00477     }
00478   }
00479   return rv;
00480 }
00481 
00482 
00483 //=============================================================================
00484 //Function:  create_surface_boundaries (PRIVATE)
00485 //Description: creates the curves based on the facet surface information
00486 //Author: sjowen
00487 //Date: 12/3/00
00488 //=============================================================================
00489 CubitStatus ChollaEngine::create_surface_boundaries(
00490   DLIList<ChollaSurface*> &cholla_surface_list, // global list of surfaces
00491   DLIList<ChollaCurve*> &cholla_curve_list,     // output global list of curves
00492   CubitBoolean use_feature_angle,
00493   double min_dot )
00494 {
00495   CubitStatus stat = CUBIT_SUCCESS;
00496 
00497     // determine the boundaries for each surface.  One curve per surface
00498 
00499   int ii;
00500   for ( ii = cholla_surface_list.size(); ii > 0; ii-- )
00501   {
00502     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
00503     DLIList<ChollaCurve*> chcurve_list;
00504     chsurf_ptr->get_curves( chcurve_list );
00505     if (chcurve_list.size() == 0)
00506     {
00507       DLIList<FacetEntity*> facet_list;
00508       chsurf_ptr->get_facets(facet_list);
00509       ChollaSkinTool c_skin_tool;
00510       stat = c_skin_tool.skin_2d(facet_list, chsurf_ptr);
00511       if ( stat != CUBIT_SUCCESS )
00512         return stat;
00513     }
00514   }
00515 
00516   // create a hash list of curves - to speed up classification
00517 
00518   stat = init_hash_curves();
00519   if (stat != CUBIT_SUCCESS)
00520   {
00521     delete_hash_curves();
00522     return stat;
00523   }
00524 
00525   // loop through each of the edges on the surfaces
00526   // Determine which curve it is a part of.
00527   // Create a new ChollaCurve for each curve
00528   // Curves are created wherever there is a unique set of associated
00529   // surfaces 
00530 
00531   int jj, kk;
00532   for ( ii = cholla_surface_list.size(); ii > 0; ii-- )
00533   {
00534 
00535     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
00536     DLIList<ChollaCurve*> chcurve_list;
00537     chsurf_ptr->get_curves( chcurve_list );
00538 
00539     // curently there should only be one curve list per surface
00540 
00541     for (jj=chcurve_list.size(); jj>0; jj--)
00542     {
00543       ChollaCurve *chcurv_ptr = chcurve_list.get_and_step();
00544       DLIList<FacetEntity*> facet_list =  chcurv_ptr->get_facet_list();
00545       FacetEntity *edge_ptr;
00546       for ( kk = 0; kk < facet_list.size(); kk++)
00547       {
00548         edge_ptr = facet_list.get_and_step();
00549         stat = classify_edge( edge_ptr, cholla_curve_list, chsurf_ptr );
00550         if (stat != CUBIT_SUCCESS) 
00551           return stat;
00552       }
00553 
00554       // delete this ChollaCurve - it should have been replaced by one
00555       // or more curves bounding this surface
00556 
00557       chsurf_ptr->remove_curve( chcurv_ptr );
00558       delete chcurv_ptr;
00559     }
00560   }
00561   delete_hash_curves();
00562 
00563   // Split these curves so that there is only one string of continuous
00564   // edges per curve (it will also order the edges and set the start
00565   // and end nodes for each curve) 
00566 
00567   int num_curves = cholla_curve_list.size();
00568 
00569   cholla_curve_list.reset();
00570   for ( ii = num_curves; ii > 0 && stat == CUBIT_SUCCESS; ii-- )
00571   {
00572     ChollaCurve *chcurv_ptr = cholla_curve_list.get();
00573 
00574     // if necessary mark nodes that will serve as feature breaks (vertices 
00575     // will be generatedat them)
00576 
00577     if (use_feature_angle)
00578     {
00579       stat = chcurv_ptr->feature_angle( min_dot );
00580       if (stat != CUBIT_SUCCESS)
00581          return stat;
00582     }
00583 
00584     // split the curve based on various criteria
00585 
00586     stat = chcurv_ptr->split_curve( cholla_curve_list );
00587 
00588     // delete this curve (new curves were created in split_curve)
00589 
00590     delete chcurv_ptr;
00591     cholla_curve_list.change_to(NULL);
00592     cholla_curve_list.step();
00593   }
00594   cholla_curve_list.remove_all_with_value(NULL);
00595 
00596   // update the point->curve associativity
00597 
00598   for (ii=0; ii<cholla_curve_list.size(); ii++)
00599   {
00600     ChollaCurve *chcurv_ptr = cholla_curve_list.get_and_step();
00601     CubitPoint *start_ptr, *end_ptr;
00602     chcurv_ptr->get_ends( start_ptr, end_ptr );
00603     TDGeomFacet *td = TDGeomFacet::get_geom_facet( start_ptr );
00604     td->add_cholla_curve( chcurv_ptr );
00605     td = TDGeomFacet::get_geom_facet( end_ptr );
00606     td->add_cholla_curve( chcurv_ptr );
00607   }
00608 
00609   return stat;
00610 }
00611 
00612 //=============================================================================
00613 //Function:  init_hash_curves (PRIVATE)
00614 //Description: create a hash array of all curves.  They are hashed based on the
00615 //             smallest id of any surface attached to the curve 
00616 //Author: sjowen
00617 //Date: 3/7/01
00618 //=============================================================================
00619 CubitStatus ChollaEngine::init_hash_curves( )
00620 {
00621   /* === find the next highest prime number */
00622 
00623   int num_surfs = chollaSurfaceList.size();
00624   int i;
00625   hashCurveSize = num_surfs;
00626   if (num_surfs < 30) hashCurveSize = 31;
00627   else 
00628   {
00629     i=2;
00630     while (i<hashCurveSize*0.5 + 1) {
00631       if (hashCurveSize % i == 0) {
00632         i=2;
00633         hashCurveSize++;
00634       }
00635       else {
00636         i++;
00637       }
00638     }
00639   }
00640   hashCurveArray = new DLIList<ChollaCurve*>[hashCurveSize];
00641 
00642   int key = 0;
00643   ChollaCurve *chcurv_ptr;
00644   DLIList<ChollaSurface*> *fsm_list_ptr; 
00645   for (i=0; i<chollaCurveList.size(); i++)
00646   {
00647     chcurv_ptr = chollaCurveList.get_and_step();
00648     fsm_list_ptr = chcurv_ptr->get_surface_list_ptr();
00649     key = get_curve_hash_key( fsm_list_ptr );
00650     hashCurveArray[key].append( chcurv_ptr );   
00651   }
00652   return CUBIT_SUCCESS;
00653 }
00654 
00655 //=============================================================================
00656 //Function:  delete_hash_curves (PRIVATE)
00657 //Description: delete the hash curve stuff
00658 //Author: sjowen
00659 //Date: 3/7/01
00660 //=============================================================================
00661 void ChollaEngine::delete_hash_curves( )
00662 {
00663   if (hashCurveArray)
00664    delete [] hashCurveArray;
00665   hashCurveArray = NULL;
00666   hashCurveSize = 0;
00667 }
00668 
00669 //=============================================================================
00670 //Function:  get_curve_hash_key (PRIVATE)
00671 //Description: 
00672 //Author: sjowen
00673 //Date: 3/7/01
00674 //=============================================================================
00675 int ChollaEngine::get_curve_hash_key(
00676   DLIList<ChollaSurface*> *fsm_list_ptr )
00677 {
00678   int key, j;
00679   ChollaSurface *chsurf_ptr;
00680   if (fsm_list_ptr->size() == 0)
00681   {
00682     key = 0;
00683   }
00684   else
00685   {
00686     key = INT_MAX;
00687     for (j=0; j<fsm_list_ptr->size(); j++)
00688     {
00689       chsurf_ptr = fsm_list_ptr->get_and_step();
00690       if (chsurf_ptr->get_id() < key)
00691         key = chsurf_ptr->get_id();
00692     }
00693   }
00694   key = key % hashCurveSize;
00695   return key;
00696 }
00697 
00698 
00699 //=============================================================================
00700 //Function:  classify_edge (PRIVATE)
00701 //Description: sorts a edge into its correct curve based on its associated
00702 //             surfaces and sidesets/nodesets.  Creates a new block curve if 
00703 //             necessary.
00704 //Author: sjowen
00705 //Date: 12/3/00
00706 //=============================================================================
00707 CubitStatus ChollaEngine::classify_edge(
00708   FacetEntity *edge_ptr,       // the edge we are classifying
00709   DLIList<ChollaCurve*> &cholla_curve_list,  // add to one of these
00710   ChollaSurface *cholla_surf_mesh_ptr )   // the current surface
00711 {
00712   CubitStatus rv = CUBIT_SUCCESS;
00713 
00714   // see if we have already classified this edge (from another surface)
00715 
00716   TDGeomFacet *td_gm_edge = TDGeomFacet::get_geom_facet(edge_ptr);
00717   if (td_gm_edge->get_hit_flag() != 0)
00718     return rv;
00719   td_gm_edge->set_hit_flag(1);
00720 
00721   // get the surfaces adjacent to this edge
00722 
00723   DLIList<ChollaSurface*> this_chsurf_list;
00724   td_gm_edge->get_cholla_surfs( this_chsurf_list );
00725   int this_num_adj = this_chsurf_list.size();
00726    
00727   // see if the surfaces defined on this face match any 
00728   // of the existing block curves
00729 
00730   DLIList<ChollaSurface*> *chsurf_list_ptr;
00731   ChollaCurve *chcurv_ptr = NULL;
00732   int found = 0;
00733   int key = get_curve_hash_key( &this_chsurf_list );
00734   int ii;
00735   for (ii=0; ii<hashCurveArray[key].size() && !found; ii++)
00736   {
00737     chcurv_ptr = hashCurveArray[key].get();
00738     // the first one checked should be the same as the last one checked (don't
00739     // use get_and_step here)  This should speed things up
00740 
00741     // check if surfaces are the same
00742 
00743     chsurf_list_ptr = chcurv_ptr->get_surface_list_ptr( );
00744     int num_adj = chsurf_list_ptr->size();
00745     if (num_adj == this_num_adj)
00746     {
00747       found = 1;
00748       int jj, kk;
00749       for (jj=chsurf_list_ptr->size(); jj>0 && found; jj--)
00750       {
00751         int same_surf = 0;
00752         ChollaSurface *chsurf_ptr = chsurf_list_ptr->get_and_step();
00753         for(kk=this_chsurf_list.size(); kk>0 && !same_surf; kk--)
00754         {
00755           ChollaSurface *this_chsurf_ptr = this_chsurf_list.get_and_step();
00756           if (this_chsurf_ptr == chsurf_ptr)
00757           {
00758             same_surf = 1;
00759           }
00760         }
00761         if (!same_surf)
00762           found = 0;
00763       }
00764     }
00765     if (!found)
00766       hashCurveArray[key].step();
00767   }
00768 
00769   // if the unique set of surfaces that this edge is associated 
00770   // with was found to already exist for a facet curve -- add the
00771   // edge to the block curve
00772 
00773   if (found)
00774   {
00775 
00776     // add the edge to the block curve mesh (make sure it is only added once)
00777 
00778     //int was_added = 
00779     chcurv_ptr->add_facet_unique( edge_ptr );
00780 
00781     // add the curve to the surface (if needed)
00782 
00783     cholla_surf_mesh_ptr->add_curve_unique( chcurv_ptr );
00784 
00785     // add the curve to the edge
00786   
00787     td_gm_edge->add_cholla_curve( chcurv_ptr );
00788   }
00789 
00790   // if the unique set of surfaces that this edge is associated
00791   // with is not found, then create a new facet curve and add the edge to it
00792 
00793   else
00794   {
00795 
00796     // create it and update surface and nodeset info
00797 
00798     int block_id = td_gm_edge->get_block_id();
00799     ChollaCurve *new_chcurv_ptr = new ChollaCurve( block_id ); 
00800     for (int mm=0; mm<this_num_adj; mm++)
00801     {
00802       new_chcurv_ptr->add_surface( this_chsurf_list.get_and_step() );
00803     }
00804 
00805     // add the edge
00806 
00807     new_chcurv_ptr->add_facet( edge_ptr );
00808 
00809     // update the surface with this new curve
00810 
00811     cholla_surf_mesh_ptr->add_curve( new_chcurv_ptr );
00812 
00813     // add the new curve to the global list
00814 
00815     cholla_curve_list.append( new_chcurv_ptr ); 
00816 
00817     // add the curve to the edge
00818   
00819     td_gm_edge->add_cholla_curve( new_chcurv_ptr );
00820 
00821     // add the new curve to the hash table
00822 
00823     hashCurveArray[key].append( new_chcurv_ptr );
00824   }
00825   return rv;
00826 }
00827 
00828 //=============================================================================
00829 //Function:  create_curve_boundaries (PRIVATE)
00830 //Description: creates the points based on the nodeset and curve information
00831 //Author: sjowen
00832 //Date: 12/6/00
00833 //=============================================================================
00834 CubitStatus ChollaEngine::create_curve_boundaries(
00835   DLIList<ChollaCurve*> &cholla_curve_list,   // global list of curves
00836   DLIList<ChollaPoint*> &cholla_point_list )  // output global list of points
00837 {
00838 
00839   CubitStatus stat = CUBIT_SUCCESS;
00840 
00841   // hash the points for speed
00842 
00843   stat = init_hash_points();
00844   if (stat != CUBIT_SUCCESS)
00845   {
00846     delete_hash_points();
00847     return stat;
00848   }
00849 
00850   // loop through each of the end nodes on the curves
00851   // Determine which point it is a part of.
00852   // Create a new ChollaPoint for each point
00853 
00854   //int mydebug = 0;
00855   int ii, kk;
00856   for ( ii = cholla_curve_list.size(); ii > 0; ii-- )
00857   {
00858     ChollaCurve *chcurv_ptr = cholla_curve_list.get_and_step();
00859     CubitPoint *point_ptr[2];
00860     chcurv_ptr->get_ends( point_ptr[0], point_ptr[1] );
00861     for ( kk = 0; kk < 2; kk++)
00862     {
00863       stat = classify_point( point_ptr[kk], cholla_point_list, chcurv_ptr );
00864       if (stat != CUBIT_SUCCESS)
00865       {
00866         delete_hash_points();
00867         return stat;
00868       }
00869     }
00870   }
00871   delete_hash_points();
00872   return stat;
00873 }
00874 
00875 //=============================================================================
00876 //Function:  classify_point (PRIVATE)
00877 //Description: sorts a point into its correct point based on its associated
00878 //             curve.  Creates a new block point if necessary
00879 //Author: sjowen
00880 //Date: 12/6/00
00881 //=============================================================================
00882 CubitStatus ChollaEngine::classify_point(
00883   CubitPoint *point_ptr,                     // the node to classify
00884   DLIList<ChollaPoint*> &cholla_point_list,   // global list of points
00885   ChollaCurve *chcurv_ptr )                 // curve that the end point is on
00886 {
00887   int ii;
00888   int found = 0;
00889   TDGeomFacet *td_node = TDGeomFacet::get_geom_facet( point_ptr );
00890   ChollaPoint *chpnt_ptr = NULL;
00891   DLIList<ChollaCurve*> fcm_list;
00892   td_node->get_cholla_curves(fcm_list);
00893   int key = get_point_hash_key( &fcm_list );
00894   for (ii = 0; ii < hashPointArray[key].size() && !found; ii++)
00895   {
00896     chpnt_ptr = hashPointArray[key].get();
00897     FacetEntity *this_point_ptr = chpnt_ptr->get_facets();
00898     if (this_point_ptr == point_ptr)
00899     {
00900       found = 1;
00901     }
00902     else
00903     {
00904       hashPointArray[key].step();
00905     }
00906   } 
00907 
00908   if (found)
00909   {
00910     chpnt_ptr->add_curve( chcurv_ptr );
00911     chcurv_ptr->add_point( chpnt_ptr );
00912   }
00913   else
00914   {
00915     ChollaPoint *new_chpnt_ptr = new ChollaPoint(); 
00916     new_chpnt_ptr->add_facet( point_ptr );
00917     new_chpnt_ptr->add_curve( chcurv_ptr );
00918     chcurv_ptr->add_point( new_chpnt_ptr );
00919     cholla_point_list.append( new_chpnt_ptr );
00920     hashPointArray[key].append( new_chpnt_ptr );
00921   }
00922   return CUBIT_SUCCESS;
00923 }
00924 
00925 //=============================================================================
00926 //Function:  init_hash_points (PRIVATE)
00927 //Description: create a hash array of all points.  They are hashed based on the
00928 //             smallest id of any curve attached to the curve 
00929 //Author: sjowen
00930 //Date: 3/7/01
00931 //=============================================================================
00932 CubitStatus ChollaEngine::init_hash_points( )
00933 {
00934   /* === find the next highest prime number */
00935 
00936   int num_curves = chollaCurveList.size();
00937   int i;
00938   hashPointSize = num_curves;
00939   if (num_curves < 30) hashPointSize = 31;
00940   else 
00941   {
00942     i=2;
00943     while (i<hashPointSize*0.5 + 1) {
00944       if (hashPointSize % i == 0) {
00945         i=2;
00946         hashPointSize++;
00947       }
00948       else {
00949         i++;
00950       }
00951     }
00952   }
00953   hashPointArray = new DLIList<ChollaPoint*>[hashPointSize];
00954 
00955   int key = 0;
00956   ChollaPoint *chpnt_ptr;
00957   DLIList<ChollaCurve*> *fcm_list_ptr; 
00958   for (i=0; i<chollaPointList.size(); i++)
00959   {
00960     chpnt_ptr = chollaPointList.get_and_step();
00961     fcm_list_ptr = chpnt_ptr->get_curve_list_ptr();
00962     key = get_point_hash_key( fcm_list_ptr );
00963     hashPointArray[key].append( chpnt_ptr );   
00964   }
00965   return CUBIT_SUCCESS;
00966 }
00967 
00968 //=============================================================================
00969 //Function:  delete_hash_points (PRIVATE)
00970 //Description: delete the hash point stuff
00971 //Author: sjowen
00972 //Date: 3/7/01
00973 //=============================================================================
00974 void ChollaEngine::delete_hash_points( )
00975 {
00976   if (hashPointArray)
00977    delete [] hashPointArray;
00978   hashPointArray = NULL;
00979   hashPointSize = 0;
00980 }
00981 
00982 //=============================================================================
00983 //Function:  get_point_hash_key (PRIVATE)
00984 //Description: 
00985 //Author: sjowen
00986 //Date: 3/7/01
00987 //=============================================================================
00988 int ChollaEngine::get_point_hash_key(
00989   DLIList<ChollaCurve*> *fcm_list_ptr )
00990 {
00991   int key, j;
00992   ChollaCurve *chcurv_ptr;
00993   if (fcm_list_ptr->size() == 0)
00994   {
00995     key = 0;
00996   }
00997   else
00998   {
00999     key = INT_MAX;
01000     for (j=0; j<fcm_list_ptr->size(); j++)
01001     {
01002       chcurv_ptr = fcm_list_ptr->get_and_step();
01003       if (chcurv_ptr->get_id() < key)
01004         key = chcurv_ptr->get_id();
01005     }
01006   }
01007   key = key % hashPointSize;
01008   return key;
01009 }
01010 
01011 //=============================================================================
01012 //Function:  facet_dimension (PRIVATE)
01013 //Description: returns the dimension of a mesh entity.
01014 //=============================================================================
01015 int ChollaEngine::facet_dimension(FacetEntity *facet_ptr)
01016 {
01017   if (CAST_TO(facet_ptr, CubitFacet) != NULL)
01018     return 2;
01019   if (CAST_TO(facet_ptr, CubitFacetEdge) != NULL)
01020     return 1;
01021   if (CAST_TO(facet_ptr, CubitPoint) != NULL)
01022     return 0;
01023   return -1;
01024 }
01025 
01026 
01027 //===============================================================================
01028 //Function:  build_eval_tools (PRIVATE)
01029 //Description:  build the CUBIT geometry based on the Facet entity class lists
01030 //===============================================================================
01031 CubitStatus ChollaEngine::build_eval_tools(
01032   DLIList<ChollaSurface*> &cholla_surface_list,
01033   DLIList<ChollaCurve*> &cholla_curve_list,
01034   int interp_order,
01035   CubitBoolean use_feature_angle,
01036   double min_dot,
01037   CubitBoolean smooth_non_manifold,
01038   CubitBoolean split_surfaces )
01039 {
01040   CubitStatus stat = CUBIT_SUCCESS;  
01041 
01042   if (stat == CUBIT_SUCCESS)
01043     stat = build_surface_and_curve_eval_tools( cholla_surface_list,
01044                                    interp_order, min_dot );  
01045   if (stat == CUBIT_SUCCESS)
01046     stat = build_curve_eval_tools( cholla_curve_list, interp_order );
01047 
01048   if (stat == CUBIT_SUCCESS)
01049     if (interp_order == 4)
01050       stat = clean_geometry( smooth_non_manifold, split_surfaces,
01051                            use_feature_angle, min_dot, cholla_curve_list );
01052   return stat;
01053 }
01054 
01055 
01056 //===============================================================================
01057 //Function:  build_curve_eval_tools (PRIVATE)
01058 //Description:  From the cholla curve list, create CurveFacetEvalTools
01059 //===============================================================================
01060 CubitStatus ChollaEngine::build_curve_eval_tools(
01061   DLIList<ChollaCurve*> &cholla_curve_list,
01062   int /* interp_order */)
01063 {
01064   CubitStatus stat = CUBIT_SUCCESS;
01065   int kk;
01066   for ( kk = cholla_curve_list.size(); kk > 0; kk-- )
01067   {
01068     ChollaCurve *chcurv_ptr = cholla_curve_list.get_and_step();
01069     CurveFacetEvalTool *curv_eval_tool_ptr = chcurv_ptr->get_eval_tool();
01070     if (curv_eval_tool_ptr == NULL)
01071     {
01072       CubitPoint *start_point, *end_point;
01073       chcurv_ptr->get_ends( start_point, end_point );
01074       
01075       // if this is a curve without a parent surface then handle it 
01076       // differently.  (Curves with parents use the surface to evaluate to
01077       // With only a curve, it must evaluate to the curve)
01078       // Note the CurveFacetEvalTool for curves that have parent surfaces
01079       // are computed in build_surface_eval_tools
01080       
01081       DLIList<ChollaSurface*> chsurf_list = chcurv_ptr->get_surfaces();
01082       if (chsurf_list.size() == 0)
01083       {
01084         DLIList<FacetEntity*> facet_list;
01085         DLIList<CubitPoint*> point_list;  // needs to be filled in
01086         facet_list = chcurv_ptr->get_facet_list();
01087         DLIList<CubitFacetEdge*> edge_list;
01088         CAST_LIST( facet_list, edge_list, CubitFacetEdge );
01089         if (stat != CUBIT_SUCCESS)
01090           return stat;     
01091 
01092         curv_eval_tool_ptr = new CurveFacetEvalTool;
01093         stat = curv_eval_tool_ptr->initialize( edge_list, point_list );
01094 
01095         if ( stat != CUBIT_SUCCESS )
01096         {
01097             return stat;
01098         }
01099         chcurv_ptr->assign_eval_tool(curv_eval_tool_ptr);
01100       }
01101       else
01102       {       
01103         //fix up the orientation of the Cholla curve
01104         stat = chcurv_ptr->order_edges();
01105         if ( stat != CUBIT_SUCCESS )
01106         {         
01107           return stat;
01108         }
01109         
01110         DLIList<FacetEntity*> facet_ents;
01111         facet_ents = chcurv_ptr->get_facet_list();
01112         DLIList<CubitFacetEdge*> edge_facets;
01113         CAST_LIST(facet_ents, edge_facets, CubitFacetEdge );
01114         DLIList<CubitPoint*> ordered_points;
01115         
01116         for( int k=0; k<edge_facets.size(); k++ )
01117         {
01118           CubitFacetEdge *tmp_edge = edge_facets.get_and_step();          
01119           if( k==0 )
01120           {
01121             ordered_points.append( tmp_edge->point(0) );            
01122             ordered_points.append( tmp_edge->point(1) );            
01123           }
01124           else        
01125             ordered_points.append( tmp_edge->point(1) );                      
01126         }     
01127 
01128         FacetEvalTool *surf_eval_tool = chsurf_list.get()->get_eval_tool();
01129         CurveFacetEvalTool *curv_eval_tool_ptr = new CurveFacetEvalTool;       
01130         edge_facets.reset();        
01131         stat = curv_eval_tool_ptr->initialize( edge_facets, ordered_points, surf_eval_tool );          
01132 
01133         if ( stat != CUBIT_SUCCESS )
01134         {
01135           return stat;
01136         }
01137         chcurv_ptr->assign_eval_tool( curv_eval_tool_ptr );           
01138       }
01139     }   
01140   }
01141   return stat;
01142 }
01143 
01144 //===============================================================================
01145 //Function:  build_surface_eval_tools (PRIVATE)
01146 //Description:  From the facet surface list, create the FacetEvalTools
01147 //===============================================================================
01148 CubitStatus ChollaEngine::build_surface_and_curve_eval_tools(
01149   DLIList<ChollaSurface*> &cholla_surface_list,
01150   int interp_order,
01151   double min_dot)
01152 {
01153   CubitStatus stat = CUBIT_SUCCESS;
01154   int ii, kk;
01155 
01156   // make sure the facet flags have been reset
01157 
01158   for ( kk = cholla_surface_list.size(); kk > 0; kk-- )
01159   {
01160     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
01161     chsurf_ptr->reset_facet_flags();
01162   }
01163 
01164   // now loop through surfaces and create them
01165 
01166   for ( kk = cholla_surface_list.size(); kk > 0; kk-- )
01167   {
01168     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
01169     DLIList<FacetEntity*> facet_entity_list;    
01170     DLIList<CubitPoint*> point_list;
01171     chsurf_ptr->get_points(point_list);
01172     chsurf_ptr->get_facets(facet_entity_list);
01173     DLIList<CubitFacet*> facet_list;
01174     CAST_LIST( facet_entity_list, facet_list, CubitFacet );
01175 
01176     FacetEvalTool *eval_tool_ptr = new FacetEvalTool();
01177     eval_tool_ptr->initialize(facet_list, point_list, interp_order, min_dot);
01178 
01179     chsurf_ptr->assign_eval_tool(eval_tool_ptr);
01180 
01181     // go through each of this surface's curves and create CurveFacetEvalTools
01182 
01183     DLIList<ChollaCurve *> chcurv_list;
01184     chsurf_ptr->get_curves( chcurv_list );
01185     for (ii=0; ii<chcurv_list.size(); ii++)
01186     {
01187       ChollaCurve *chcurv_ptr = chcurv_list.get_and_step();   
01188 
01189       if (chcurv_ptr->get_eval_tool() == NULL)
01190       {
01191         //fix up the orientation of the Cholla curve
01192         stat = chcurv_ptr->order_edges();
01193         if ( stat != CUBIT_SUCCESS )
01194         {         
01195           PRINT_ERROR("Problems ordering edges!!!!!\n");          
01196           return stat;
01197         }        
01198         
01199         DLIList<FacetEntity*> facet_ents;
01200         facet_ents = chcurv_ptr->get_facet_list();
01201         DLIList<CubitFacetEdge*> edge_facets;
01202         CAST_LIST(facet_ents, edge_facets, CubitFacetEdge );
01203         DLIList<CubitPoint*> ordered_points;
01204         
01205         for( int k=0; k<edge_facets.size(); k++ )
01206         {
01207           CubitFacetEdge *tmp_edge = edge_facets.get_and_step();          
01208           if( k==0 )
01209           {
01210             ordered_points.append( tmp_edge->point(0) );            
01211             ordered_points.append( tmp_edge->point(1) );            
01212           }
01213           else        
01214             ordered_points.append( tmp_edge->point(1) );                      
01215         }     
01216 
01217         CurveFacetEvalTool *curv_eval_tool_ptr = new CurveFacetEvalTool;       
01218         edge_facets.reset();        
01219         stat = curv_eval_tool_ptr->initialize( edge_facets, ordered_points, eval_tool_ptr );          
01220 
01221         if ( stat != CUBIT_SUCCESS )
01222         {
01223           return stat;
01224         }
01225         chcurv_ptr->assign_eval_tool( curv_eval_tool_ptr );     
01226       }
01227     }
01228   }
01229   return stat;
01230 }
01231 
01232 CubitStatus ChollaEngine::rebuild_surface_and_curve_eval_tools(
01233   DLIList<ChollaSurface*> &cholla_surface_list,
01234   int interp_order,
01235   double min_dot )
01236 {
01237   CubitStatus stat = CUBIT_SUCCESS;
01238   int ii, kk;
01239 
01240   // make sure the facet flags have been reset
01241   for ( kk = cholla_surface_list.size(); kk > 0; kk-- )
01242   {
01243     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
01244     chsurf_ptr->reset_facet_flags();    
01245   }
01246 
01247   // get unique list of curves
01248   DLIList<ChollaCurve *> all_chcurves;
01249   for ( kk = cholla_surface_list.size(); kk > 0; kk-- )
01250   {
01251     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
01252     DLIList<ChollaCurve *> chcurv_list;
01253     chsurf_ptr->get_curves( chcurv_list );
01254     all_chcurves += chcurv_list;    
01255   }
01256   all_chcurves.uniquify_ordered();
01257 
01258   // now loop through surfaces and create them
01259 
01260   for ( kk = cholla_surface_list.size(); kk > 0; kk-- )
01261   {
01262     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
01263     DLIList<FacetEntity*> facet_entity_list;
01264     DLIList<CubitPoint*> point_list;
01265     chsurf_ptr->get_points(point_list);
01266     chsurf_ptr->get_facets(facet_entity_list);
01267     DLIList<CubitFacet*> facet_list;
01268     CAST_LIST( facet_entity_list, facet_list, CubitFacet );
01269 
01270     FacetEvalTool *eval_tool_ptr = chsurf_ptr->get_eval_tool();
01271     if (NULL != eval_tool_ptr)
01272     {
01273       DLIList<CubitFacet*> facets;
01274       eval_tool_ptr->remove_facets(facets);
01275       delete eval_tool_ptr;
01276     }
01277 
01278     eval_tool_ptr = new FacetEvalTool();
01279     if ( CUBIT_SUCCESS != eval_tool_ptr->initialize(facet_list, point_list, interp_order, min_dot) )
01280     {
01281       return CUBIT_FAILURE;
01282     }
01283 
01284     //eval_tool_ptr = new FacetEvalTool();
01285     //eval_tool_ptr->replace_facets(facet_list);
01286 
01287     chsurf_ptr->assign_eval_tool(eval_tool_ptr);
01288   }
01289 
01290   // go through each of the curves and create CurveFacetEvalTools
01291   for (ii=0; ii<all_chcurves.size(); ii++)
01292   {
01293     ChollaCurve *chcurv_ptr = all_chcurves.get_and_step();    
01294 
01295     CubitStatus rv = chcurv_ptr->order_edges();
01296     if (CUBIT_SUCCESS != rv) {
01297       PRINT_ERROR("Failed to order edges.\n");
01298       return rv;
01299     }
01300 
01301     CurveFacetEvalTool* curve_eval = chcurv_ptr->get_eval_tool();
01302     if (NULL != curve_eval)
01303     {
01304       DLIList<CubitFacetEdge*> eval_facets;
01305       curve_eval->remove_facets(eval_facets);
01306       delete curve_eval;
01307     }
01308 
01309     DLIList<FacetEntity*> facet_ents;
01310     facet_ents = chcurv_ptr->get_facet_list();
01311     DLIList<CubitFacetEdge*> edge_facets;
01312     CAST_LIST(facet_ents, edge_facets, CubitFacetEdge );
01313     DLIList<CubitPoint*> ordered_points;
01314 
01315     for( int k=0; k<edge_facets.size(); k++ )
01316     {
01317       CubitFacetEdge *tmp_edge = edge_facets.get_and_step();          
01318       if( k==0 )
01319       {
01320         ordered_points.append( tmp_edge->point(0) );            
01321         ordered_points.append( tmp_edge->point(1) );            
01322       }
01323       else        
01324         ordered_points.append( tmp_edge->point(1) );                      
01325     }     
01326 
01327     CurveFacetEvalTool *curv_eval_tool_ptr = new CurveFacetEvalTool;       
01328     edge_facets.reset();
01329     ordered_points.reset();
01330     stat = curv_eval_tool_ptr->initialize( edge_facets, ordered_points);          
01331 
01332     if ( stat != CUBIT_SUCCESS )
01333     {
01334       return stat;
01335     }
01336     chcurv_ptr->assign_eval_tool( curv_eval_tool_ptr );       
01337   }
01338 
01339   return stat; 
01340 }
01341 
01342 //===============================================================================
01343 //Function:  determine_curve_orientation (static PUBLIC)
01344 //Description:  Determine orientation of the curve with respect to the surface
01345 //===============================================================================
01346 CubitStatus ChollaEngine::determine_curve_orientation( 
01347   ChollaSurface *chsurf_ptr,
01348   ChollaCurve *chcurv_ptr,
01349   CubitSense & orientation )
01350 {
01351   // get the first mesh edge on the curve. use it to determine the 
01352   // orientation of the curve with respect to the surface
01353 
01354   DLIList<FacetEntity*> facet_list = chcurv_ptr->get_facet_list();
01355   facet_list.reset();
01356   FacetEntity *facet_ptr = facet_list.get();
01357   CubitFacetEdge *edge_ptr = CAST_TO( facet_ptr, CubitFacetEdge );
01358   if (!edge_ptr)
01359     return CUBIT_FAILURE; // facet edges are not on the list - we shouldn't be here
01360 
01361   // get the adjacent face on this surface
01362 
01363   DLIList<FacetEntity*> adj_face_list;
01364   edge_ptr->get_parents( adj_face_list );
01365 
01366   DLIList<FacetEntity*> face_ptrs;
01367   int jj;
01368   for ( jj = 0; jj < adj_face_list.size(); jj++ )
01369   {
01370     FacetEntity* face_ptr = adj_face_list.get_and_step();    
01371     TDGeomFacet *td_gm_face = TDGeomFacet::get_geom_facet(face_ptr); 
01372     DLIList<ChollaSurface*> chsurf_list;
01373     if(td_gm_face)
01374     {
01375       td_gm_face->get_cholla_surfs( chsurf_list );
01376       if (chsurf_list.size())
01377       {
01378         ChollaSurface *face_chsurf_ptr = chsurf_list.get();
01379         if(face_chsurf_ptr == chsurf_ptr)
01380         {
01381           face_ptrs.append(face_ptr);
01382         }
01383       }
01384     }
01385   }
01386   if(!face_ptrs.size())
01387     return CUBIT_FAILURE;  // didn't find an adj face on the surface ???
01388     
01389 
01390   // if there are two, we'll just say the orientation is unknown
01391   // this happens when there is a non-manifold, callers are responsible for dealing with those
01392   if(face_ptrs.size() >= 2)
01393   {
01394     orientation = CUBIT_UNKNOWN;
01395     return CUBIT_SUCCESS;
01396   }
01397 
01398   FacetEntity* face_ptr = face_ptrs[0];
01399 
01400   // determine orientation of nodes on this mesh face
01401 
01402   CubitPoint *start_ptr, *end_ptr;
01403   chcurv_ptr->get_ends( start_ptr, end_ptr );
01404   end_ptr = edge_ptr->other_point( start_ptr );
01405   if (end_ptr == NULL)    
01406   {  
01407     return CUBIT_FAILURE;  // the edge list may not be ordered correctly??
01408   }
01409   CubitPoint *points[3];
01410   CubitFacet *tri_ptr = CAST_TO( face_ptr, CubitFacet );
01411   tri_ptr->points( points[0], points[1], points[2] );
01412   
01413   int found = 0;
01414   for ( jj = 0; jj < 3 && !found; jj++ )
01415   {
01416     if (points[jj] == start_ptr)
01417     {
01418       int next_jj = (jj + 1)%3;
01419       int prev_jj = (jj + 2)%3;
01420       if(points[next_jj] == end_ptr)
01421       {
01422         found = 1;
01423         orientation = CUBIT_FORWARD;
01424       }
01425       else if(points[prev_jj] == end_ptr)
01426       {
01427         found = 1;
01428         orientation = CUBIT_REVERSED;
01429       }
01430     } 
01431   } 
01432   if (!found)
01433     return CUBIT_FAILURE;  // couldn't determine the orientation
01434 
01435   return CUBIT_SUCCESS;
01436 }
01437 
01438 //===============================================================================
01439 //Function:  clean_geometry (PRIVATE)
01440 //Description:  fix the edge control points and the normals so they are conforming
01441 //              (or non-conforming) accross curves
01442 //===============================================================================
01443 CubitStatus ChollaEngine::clean_geometry( 
01444   CubitBoolean smooth_non_manifold,
01445   CubitBoolean split_surfaces,
01446   CubitBoolean use_feature_angle,
01447   double mindot,
01448   DLIList <ChollaCurve *> &cholla_curve_list )
01449 {
01450   int iedge;
01451   ChollaCurve *chcurv_ptr;
01452   FacetEntity *fedge_ptr;
01453   CubitFacetEdge *edge_ptr;
01454   DLIList <FacetEntity *> facet_list; 
01455   DLIList<CubitFacetEdge *> feature_edge_list;
01456   int icurve;
01457   for (icurve=0; icurve<cholla_curve_list.size(); icurve++)
01458   {
01459     chcurv_ptr = cholla_curve_list.get_and_step();
01460     facet_list.clean_out();
01461     facet_list = chcurv_ptr->get_facet_list( );
01462     for (iedge=0; iedge<facet_list.size(); iedge++)
01463     {
01464       fedge_ptr = facet_list.get_and_step();
01465       edge_ptr = CAST_TO( fedge_ptr, CubitFacetEdge );
01466       feature_edge_list.append( edge_ptr );
01467     }
01468   }
01469 
01470   return fix_geometry( smooth_non_manifold,split_surfaces, 
01471                        use_feature_angle,mindot, feature_edge_list );
01472 }
01473 
01474 //=============================================================================
01475 //Function:  check_all_facet_orientations (PUBLIC)
01476 //Description: check for consistent orientation of the facets and set the 
01477 //             isBackwards flag on the facets if necessary  
01478 //Author: sjowen
01479 //Date: 8/14/01
01480 //=============================================================================
01481 CubitStatus ChollaEngine::check_all_facet_orientations(
01482   DLIList<CubitFacet*> &facet_list,
01483   CubitBoolean do_flip)
01484 {
01485   CubitStatus stat = CUBIT_SUCCESS;
01486   //return CUBIT_SUCCESS;
01487   // mark facets
01488 
01489   int ii;
01490   for (ii=0; ii<facet_list.size(); ii++)
01491     facet_list.get_and_step()->marked(1);
01492 
01493   int mydebug = 0;
01494   if (mydebug)
01495   {
01496     dcolor(CUBIT_YELLOW_INDEX);
01497     dfldraw(facet_list);
01498     dview();
01499   }
01500 
01501   // recursively loop through all facets making sure we are oriented the same
01502   int nfacets = 0;
01503   CubitFacet *facet_ptr;
01504   while ( nfacets < facet_list.size() )
01505   {
01506     facet_ptr = facet_list.get_and_step();
01507     if (facet_ptr->marked() == 1)
01508     {
01509       stat = check_facet_orientation( facet_ptr, do_flip, nfacets, mydebug );
01510       if (stat!= CUBIT_SUCCESS)
01511         return stat;
01512     }
01513   }
01514   return stat;
01515 }
01516 
01517 
01518 //=============================================================================
01519 //Function:  check_facet_orientation (PUBLIC)
01520 //Description: check for consistent orientation of the facets and change
01521 //             orientation if necessary  (is NOT recursive function)
01522 //Notes:  If do_flip is CUBIT_TRUE, then the facet topology is actually
01523 //        changed.  Otherwise the is_backwards flag is set
01524 //Author: sjowen
01525 //Date: 6/3/01
01526 //=============================================================================
01527 CubitStatus ChollaEngine::check_facet_orientation(
01528   CubitFacet *start_facet, 
01529   CubitBoolean do_flip,
01530   int &nfacets, int mydebug )
01531 {
01532 
01533   int jj;
01534   CubitFacet *adjfacet, *facet;
01535   CubitPoint *cpt0, *cpt1, *adjpt;
01536   DLIList<CubitFacet *>temp_flist;
01537   DLIList<CubitFacet *>adj_facet_list;
01538   temp_flist.append(start_facet);
01539   if (mydebug)
01540   {
01541     dcolor(CUBIT_RED_INDEX);
01542     dfdraw(start_facet);
01543   }
01544   nfacets++;
01545   start_facet->marked( 0 );
01546   int adjidx; 
01547   while(temp_flist.size())
01548   {
01549     facet = temp_flist.pop();
01550     if (facet->marked() == 0)
01551     {
01552       for (jj=0; jj<3; jj++)
01553       {
01554         cpt0 = facet->point(jj);
01555         cpt1 = facet->point((jj+1)%3);
01556         adj_facet_list.clean_out();
01557         facet->shared_facets(cpt0, cpt1, adj_facet_list);
01558         if(adj_facet_list.size()==1)
01559         {
01560           adjfacet = adj_facet_list.get();
01561           if (adjfacet->marked() == 1)
01562           {
01563             adjidx = adjfacet->point_index( cpt1 ); 
01564             if (adjidx == -1)
01565             {
01566               return CUBIT_FAILURE;
01567             }
01568             adjpt = adjfacet->point((adjidx+1)%3);
01569             if (adjpt != cpt0)
01570             {        
01571               // the orientation is not consistent -- flip the orientation of the 
01572               // adjacent facet
01573 
01574               // an assertion here means that the facets really don't share an
01575               // edge.  Should not happen!
01576               
01577               if (adjfacet->point((adjidx+2)%3) != cpt0)
01578               {
01579                 return CUBIT_FAILURE;
01580               }
01581        
01582               if (do_flip)
01583               {
01584                 adjfacet->flip();
01585               }
01586               else
01587               {
01588                 if(adjfacet->is_backwards())
01589                   adjfacet->is_backwards( 0 );
01590                 else
01591                   adjfacet->is_backwards( 1 );
01592               }
01593               if(mydebug){
01594                 adjfacet->debug_draw(CUBIT_WHITE_INDEX);
01595               }
01596             }
01597 
01598             // put its neighbor on the list to be processed later
01599 
01600             if (adjfacet->marked() == 1)
01601             {
01602               temp_flist.append( adjfacet );
01603               adjfacet->marked( 0 );
01604               if(mydebug)
01605               {
01606                 dfdraw(adjfacet);
01607               }
01608               nfacets++;
01609             }
01610           }
01611         }
01612       }
01613     }
01614   }
01615   if(mydebug)
01616     GfxDebug::mouse_xforms();
01617   return CUBIT_SUCCESS;
01618 }
01619 
01620 
01621 #ifdef ALPHA_CABLE
01622 //=============================================================================
01623 //Function:  split_surface_at_edges (PUBLIC)
01624 //Description: Given a list of edges that divides a surface into two, this
01625 // function splits the surface and modifies the engine to represent the
01626 // new geometry.
01627 //Author: mbrewer
01628 //Date: 4/22/2004
01629 //=============================================================================
01630 CubitStatus ChollaEngine::split_surface_at_edges(
01631   ChollaSurface* owning_surface,
01632   DLIList<CubitFacetEdge *> &feature_edge_list,
01633   DLIList<ChollaCurve*> &cholla_curves,
01634   DLIList<ChollaSurface*> &cholla_surfaces)
01635 {
01636   int i=0;
01637   DLIList<ChollaSurface*> original_surfaces = chollaSurfaceList;
01638   DLIList<ChollaCurve*> original_curves = chollaCurveList;
01639   //mark edges as feature
01640   CubitFacetEdge* edge_ptr=NULL;
01641   for(i=0;i<feature_edge_list.size();++i){
01642     edge_ptr=feature_edge_list.get_and_step();
01643     TDGeomFacet::add_geom_facet(edge_ptr, -1); 
01644     TDGeomFacet* td_gm_edge = TDGeomFacet::get_geom_facet(edge_ptr);
01645     edge_ptr->set_as_feature();
01646   }
01647    //Michael temp
01648   DLIList<FacetEntity*> *surf_facet_list=owning_surface->get_facet_list_ptr();
01649   int surface_id = owning_surface->get_id();
01650   for(i=0;i<surf_facet_list->size();++i){
01651     FacetEntity* face_ptr = surf_facet_list->get_and_step();
01652     TDGeomFacet *td_gm_face = TDGeomFacet::get_geom_facet(face_ptr);
01653     td_gm_face->set_hit_flag(surface_id);
01654   }
01655   
01656   CubitStatus rv = make_features( feature_edge_list, CUBIT_FALSE );
01657   if (rv != CUBIT_SUCCESS)
01658     return rv;
01659   
01660     // split up the surface
01661   rv = owning_surface->split_surface( cholla_surfaces );
01662   if (rv != CUBIT_SUCCESS)
01663     return rv;
01664 
01665   for ( i = cholla_surfaces.size(); i > 0; i-- )
01666   {
01667     ChollaSurface *chsurf_ptr = cholla_surfaces.get_and_step();
01668     chsurf_ptr->update_boundary_tool_data();
01669     if(chsurf_ptr != owning_surface){
01670       chollaSurfaceList.append(chsurf_ptr);
01671      
01672     }
01673   }
01674   rv = create_surface_boundaries( chollaSurfaceList, chollaCurveList,
01675                                   CUBIT_FALSE, 0.0);
01676   if ( !rv )
01677     return rv;
01678 
01679   rv = create_curve_boundaries( chollaCurveList, chollaPointList );
01680   if ( !rv )
01681     return rv;
01682 
01683   rv = build_eval_tools( chollaSurfaceList,
01684                          chollaCurveList,
01685                          0, CUBIT_FALSE, 
01686                          0, CUBIT_FALSE, CUBIT_FALSE);
01687   
01688   
01689   cholla_surfaces = chollaSurfaceList;
01690   cholla_curves = chollaCurveList;
01691 
01692   cholla_surfaces -= original_surfaces;
01693   cholla_curves -= original_curves;
01694   
01695   return rv;
01696 }
01697 #endif//cable
01698 
01699 //=============================================================================
01700 //Function:  make_features (PRIVATE)
01701 //Description: add additional edges and points where feature angle requires
01702 //             a break in the surface
01703 //Author: sjowen
01704 //Date:  4/31/01
01705 //=============================================================================
01706 CubitStatus ChollaEngine::make_features(
01707   DLIList<CubitFacetEdge *> &feature_edge_list,
01708   CubitBoolean split_surfaces )
01709 {
01710   CubitStatus rv = CUBIT_SUCCESS;
01711   int ii, jj;
01712   CubitFacetEdge *edge_ptr;
01713   CubitPoint *point_ptr;
01714   int mydebug = 0;
01715   if(mydebug)
01716     GfxDebug::clear();
01717   for (ii=0; ii<feature_edge_list.size(); ii++)
01718   {
01719     edge_ptr = feature_edge_list.get_and_step();
01720     if(mydebug)
01721       edge_ptr->debug_draw(CUBIT_YELLOW_INDEX);
01722     for (jj=0; jj<2; jj++)
01723     {
01724       point_ptr = edge_ptr->point( jj );
01725       point_ptr->marked( 0 );
01726     }
01727     edge_ptr->set_flag( 1 );  // mark edges as being feature edges
01728   }
01729 
01730   if (mydebug)
01731   {
01732     GfxDebug::mouse_xforms();
01733     dcolor(CUBIT_WHITE_INDEX);
01734     deldraw(feature_edge_list);
01735     dview();
01736   }
01737 
01738   for (ii=0; ii<feature_edge_list.size(); ii++)
01739   {
01740     edge_ptr = feature_edge_list.get_and_step();
01741     for (jj=0; jj<2; jj++)
01742     {
01743       point_ptr = edge_ptr->point( jj );
01744       if (0 == point_ptr->marked())
01745       {
01746         point_ptr->marked(1);
01747         if (split_surfaces)
01748           rv = crack_open_point( point_ptr, mydebug );
01749         else
01750           rv = insert_discontinuity_at_point( point_ptr );
01751         if (rv != CUBIT_SUCCESS)
01752           return rv;
01753       }
01754     }
01755   }
01756 
01757   for (ii=0; ii<feature_edge_list.size(); ii++)
01758   {
01759     feature_edge_list.get_and_step()->set_flag( 0 );
01760   }
01761   return rv;
01762 }
01763 
01764 //=============================================================================
01765 //Function:  crack_open_point (PRIVATE)
01766 //Description: split the surface facets at a point if required.  Create
01767 //             new points and edges as needed
01768 //Author: sjowen
01769 //Date:  4/31/01
01770 //=============================================================================
01771 CubitStatus ChollaEngine::crack_open_point(
01772   CubitPoint *point_ptr,  
01773   int mydebug )
01774 {
01775   CubitStatus rv = CUBIT_SUCCESS;
01776 
01777   // get facets at this point and mark them all ready for recursion function
01778   // get_facets_at_point
01779 
01780   int ii, jj;
01781   DLIList<CubitFacet *> facet_list;
01782   point_ptr->facets( facet_list );
01783   CubitFacet *facet_ptr, *adj_facet_ptr;
01784   for (ii=0; ii<facet_list.size(); ii++)
01785   {
01786     facet_ptr = facet_list.get_and_step();
01787     facet_ptr->marked( 0 );
01788   }
01789 
01790   // go through and find groups of adjacent facets that will form part of
01791   // new surfaces
01792 
01793   int totfacets = facet_list.size();
01794   int numfacets = 0;
01795   while(numfacets < totfacets)
01796   {
01797     facet_list.clean_out();
01798     point_ptr->facets( facet_list );
01799     facet_ptr = facet_list.get();
01800     DLIList<CubitFacet *> adj_facet_list;
01801     DLIList<CubitFacetEdge *>feature_edge_list;
01802 
01803     // make a list of all facets adjacet this point that are bounded
01804     // by feature edges.  Start with facet_ptr and recurse until
01805     // we bump into feature edges at the point.
01806 
01807     rv = get_facets_at_point( point_ptr, facet_ptr, adj_facet_list, 
01808                               feature_edge_list );
01809     numfacets += adj_facet_list.size();
01810 
01811     // if the number of facets for this feature are the same as the number of
01812     // facets at this point, then we are done with this point.  Otherwise
01813     // create new point and edges 
01814 
01815     if (numfacets < totfacets)
01816     {
01817       // create a new point and update the facets
01818 
01819       CubitPoint *new_point_ptr = 
01820          new CubitPointData( point_ptr->coordinates() );
01821       TDGeomFacet::add_geom_facet( new_point_ptr , -1);
01822       for (ii=0; ii<adj_facet_list.size(); ii++)
01823       {
01824         adj_facet_ptr = adj_facet_list.get_and_step();
01825 
01826         // facet modifications can only occur with native CUBIT facet data
01827         // if we are using someone else's data (ie. Sierra) then fail.
01828         // (Should not be using split_surfaces = TRUE)
01829 
01830         CubitFacetData *cfd_ptr = CAST_TO( adj_facet_ptr, CubitFacetData );
01831         if (!cfd_ptr)
01832           return CUBIT_FAILURE;
01833         new_point_ptr->add_facet( adj_facet_ptr );
01834         point_ptr->remove_facet( adj_facet_ptr );
01835         int pidx = adj_facet_ptr->point_index( point_ptr );
01836         cfd_ptr->set_point( new_point_ptr, pidx );
01837       }
01838 
01839       // The existing and the new points in some cases have to maintain 
01840       // the same normal...  so they need to keep track of
01841       // each other.  They will likely wind up on different surfaces
01842       // and we don't want to go search for them later
01843 
01844       TDGeomFacet *td_existing_point = TDGeomFacet::get_geom_facet( point_ptr );
01845       TDGeomFacet *td_new_point = TDGeomFacet::get_geom_facet( new_point_ptr );
01846       DLIList<CubitPoint *> partner_point_list;
01847 
01848       // add the existing point's partner list to the new point
01849 
01850       CubitPoint *partner_point_ptr;
01851       TDGeomFacet *td_partner;
01852       td_existing_point->get_partner_points( partner_point_list );
01853       for (ii=0; ii<partner_point_list.size(); ii++)
01854       {
01855         partner_point_ptr = partner_point_list.get_and_step();
01856         td_partner = TDGeomFacet::get_geom_facet( partner_point_ptr );
01857           //added mbrewer:  the check for a pointer here shouldn't
01858           // be necessary, but I have a case where it fails.  I don't
01859           // see where the logic is wrong.
01860         if(!td_partner){
01861           TDGeomFacet::add_geom_facet( partner_point_ptr , -1);
01862           td_partner = TDGeomFacet::get_geom_facet( partner_point_ptr );
01863         }
01864         td_partner->add_partner_point( new_point_ptr );
01865         td_new_point->add_partner_point( partner_point_ptr );
01866       }
01867 
01868       // Add each other as a partner
01869 
01870       td_existing_point->add_partner_point( new_point_ptr );
01871       td_new_point->add_partner_point( point_ptr );
01872 
01873       // create new edges at the point
01874 
01875       CubitFacetEdgeData *cfed_ptr;
01876       for (ii=0; ii<feature_edge_list.size(); ii++)
01877       {
01878         CubitFacetEdge *edge_ptr = feature_edge_list.get_and_step();
01879         cfed_ptr = CAST_TO( edge_ptr, CubitFacetEdgeData );
01880         if (!cfed_ptr)
01881           return CUBIT_FAILURE;
01882         rv = CUBIT_FAILURE;
01883         for (jj=0; jj<adj_facet_list.size() && rv == CUBIT_FAILURE; jj++)
01884         {
01885           rv = cfed_ptr->remove_facet( adj_facet_list.get_and_step() );
01886         }
01887         if (rv != CUBIT_SUCCESS)
01888           return rv;
01889         CubitPoint *p1 = edge_ptr->other_point( point_ptr );
01890 
01891         // create a new edge - the edge constructor will update
01892         // the facet and its edge use.
01893 
01894         CubitFacetEdge *new_edge_ptr =
01895           new CubitFacetEdgeData( new_point_ptr, p1 );
01896         TDGeomFacet::add_geom_facet( new_edge_ptr, -1 );
01897         new_edge_ptr->set_as_feature();
01898         if (mydebug)
01899         {
01900           dcolor(CUBIT_RED_INDEX);
01901           dedraw(new_edge_ptr);
01902         }
01903 
01904         // The existing and the new edges have to maintain the same 
01905         // control point locations, so they need to keep track of
01906         // each other.  They will likely wind up on different surfaces
01907         // and we don't want to go search for them later
01908 
01909         TDGeomFacet *td_existing_edge = TDGeomFacet::get_geom_facet( edge_ptr );
01910         TDGeomFacet *td_new_edge = TDGeomFacet::get_geom_facet( new_edge_ptr );
01911         DLIList<CubitFacetEdge *> partner_edge_list;
01912 
01913         // add the existing edge's partner list to the new edge
01914 
01915         CubitFacetEdge *partner_edge_ptr;
01916         td_existing_edge->get_partner_edges( partner_edge_list );
01917         for (jj=0; jj<partner_edge_list.size(); jj++)
01918         {
01919           partner_edge_ptr = partner_edge_list.get_and_step();
01920           td_partner = TDGeomFacet::get_geom_facet( partner_edge_ptr );
01921           td_partner->add_partner_edge( new_edge_ptr );
01922           td_new_edge->add_partner_edge( partner_edge_ptr );
01923         }
01924 
01925         // Add each other as a partner
01926 
01927         td_existing_edge->add_partner_edge( new_edge_ptr );
01928         td_new_edge->add_partner_edge( edge_ptr );
01929       }
01930 
01931       // update the other edges with the new point
01932 
01933       for (ii=0; ii<adj_facet_list.size(); ii++)
01934       {
01935         adj_facet_ptr = adj_facet_list.get_and_step();
01936         for (jj=0; jj<3; jj++)
01937         {
01938           CubitFacetEdge *edge_ptr = adj_facet_ptr->edge( jj );
01939           cfed_ptr = CAST_TO( edge_ptr, CubitFacetEdgeData );
01940           if (!cfed_ptr)
01941             return CUBIT_FAILURE;
01942           if (cfed_ptr->point( 0 ) == point_ptr)
01943             cfed_ptr->set_point( new_point_ptr, 0 );
01944           if (cfed_ptr->point( 1 ) == point_ptr)
01945             cfed_ptr->set_point( new_point_ptr, 1 );
01946         }
01947       }
01948     }
01949   }
01950 
01951   return rv;
01952 }
01953 
01954 //=============================================================================
01955 //Function:  insert_discontinuity_at_point (PRIVATE)
01956 //Description: does the same as crack_open_point, but does not create new 
01957 //             facet entities at surface boundaries.  Instead, it creates 
01958 //             facet boundary tooldatas to hold the additional control point 
01959 //             and normal data
01960 //Author: sjowen
01961 //Date:  4/31/01
01962 //=============================================================================
01963 CubitStatus ChollaEngine::insert_discontinuity_at_point(
01964   CubitPoint *point_ptr )
01965 {
01966   CubitStatus rv = CUBIT_SUCCESS;
01967 
01968   // get facets at this point and mark them all ready for recursion function
01969   // get_facets_at_point
01970 
01971   int ii;
01972   DLIList<CubitFacet *> facet_list;
01973   point_ptr->facets( facet_list );
01974   CubitFacet *facet_ptr = NULL;
01975   for (ii=0; ii<facet_list.size(); ii++)
01976   {
01977     facet_ptr = facet_list.get_and_step();
01978     facet_ptr->marked( 0 );
01979   }
01980 
01981   int mydebug = 0;
01982   if (mydebug) {
01983     dfldraw(facet_list);
01984     dview();
01985   }
01986 
01987   // go through and find groups of adjacent facets that will form part of
01988   // new surfaces
01989 
01990   TDFacetBoundaryPoint *td_fbp = 
01991     TDFacetBoundaryPoint::get_facet_boundary_point( point_ptr );
01992   int totfacets = facet_list.size();
01993   int numfacets = 0;
01994   while(numfacets < totfacets)
01995   {
01996     ii = 0;
01997     int found = 0;
01998     while(!found && ii < totfacets )
01999     {
02000       ii++;
02001       facet_ptr = facet_list.get_and_step();
02002       if (facet_ptr != NULL)
02003         found = 1;
02004     }
02005     assert(found);
02006     DLIList<CubitFacet *> adj_facet_list;
02007     DLIList<CubitFacetEdge *>feature_edge_list;
02008 
02009     // make a list of all facets adjacet this point that are bounded
02010     // by feature edges.  Start with facet_ptr and recurse until
02011     // we bump into feature edges at the point.
02012 
02013     rv = get_facets_at_point( point_ptr, facet_ptr, adj_facet_list, 
02014                               feature_edge_list );
02015 
02016     if (rv != CUBIT_SUCCESS)
02017       return rv;
02018     numfacets += adj_facet_list.size();
02019     for (ii=0; ii<adj_facet_list.size(); ii++)
02020     {
02021       facet_list.move_to( adj_facet_list.get_and_step() );
02022       facet_list.change_to( NULL );
02023     }
02024 
02025     // create a new boundary point tooldata if needed and add the facets
02026     // associated with this surface
02027 
02028     if (td_fbp == NULL)
02029     {
02030       TDFacetBoundaryPoint::add_facet_boundary_point( point_ptr );
02031       td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( point_ptr );
02032     }
02033     td_fbp->add_surf_facets( adj_facet_list );
02034 
02035     // create new boundary edge tooldatas at the point
02036     for (ii=0; ii<feature_edge_list.size(); ii++)
02037     {
02038       CubitFacetEdge *edge_ptr = feature_edge_list.get_and_step();
02039 
02040       TDFacetBoundaryEdge *td_fbe = 
02041         TDFacetBoundaryEdge::get_facet_boundary_edge( edge_ptr );
02042       if (td_fbe == NULL)
02043       {
02044         TDFacetBoundaryEdge::add_facet_boundary_edge( edge_ptr );
02045         td_fbe = TDFacetBoundaryEdge::get_facet_boundary_edge( edge_ptr );
02046       }
02047       td_fbe->add_surf_facet( adj_facet_list );
02048     }
02049   }
02050 
02051   return rv;
02052 }
02053 
02054 //=============================================================================
02055 //Function:  get_facets_at_point (PRIVATE)
02056 //Description: make a list of all faces adjacent to a single point that are 
02057 //             bounded by feature edges - recursive function
02058 //Author: sjowen
02059 //Date:  5/2/01
02060 //=============================================================================
02061 CubitStatus ChollaEngine::get_facets_at_point(
02062   CubitPoint *point_ptr,
02063   CubitFacet *facet_ptr,
02064   DLIList<CubitFacet *> &facet_list,
02065   DLIList<CubitFacetEdge *> &feature_edge_list)
02066 {
02067   CubitStatus rv = CUBIT_SUCCESS;
02068   CubitFacetEdge *edge_ptr;
02069   CubitFacet *adj_facet;
02070   facet_list.append(facet_ptr);
02071   facet_ptr->marked( 1 );
02072 
02073   for (int ii=0; ii<3; ii++)
02074   {
02075     edge_ptr = facet_ptr->edge( ii );
02076     if (edge_ptr->contains( point_ptr ))
02077     {
02078       if (!edge_ptr->is_feature())
02079       {
02080         if (edge_ptr->num_adj_facets() >2)
02081           return CUBIT_FAILURE;
02082         adj_facet = edge_ptr->other_facet( facet_ptr );
02083         if (adj_facet == NULL)
02084           return CUBIT_FAILURE;
02085         if (adj_facet->marked() == 0)
02086         {
02087           rv = get_facets_at_point( point_ptr, adj_facet, 
02088                                     facet_list, feature_edge_list );
02089           if (rv != CUBIT_SUCCESS)
02090             return rv;
02091         }
02092       }
02093       else
02094       {
02095         if (edge_ptr->num_adj_facets() > 1)
02096         {
02097           feature_edge_list.append_unique( edge_ptr );
02098         }
02099       }
02100     }
02101   }
02102   return rv;
02103 }
02104 
02105 //===============================================================================
02106 //Function:  fix_geometry (PUBLIC)
02107 //Description:  fix the edge control points and the normals so they are conforming
02108 //              (or non-conforming) accross curves
02109 //===============================================================================
02110 CubitStatus ChollaEngine::fix_geometry(
02111   CubitBoolean smooth_non_manifold,
02112   CubitBoolean split_surfaces,
02113   CubitBoolean /* use_feature_angle */,
02114   double mindot,
02115   DLIList <CubitFacetEdge *> &feature_edge_list )
02116 {
02117   CubitStatus stat = CUBIT_SUCCESS;
02118 
02119   // unmark all the edges and points
02120 
02121   CubitFacetEdge *edge_ptr; 
02122   int iedge;
02123   int flag = (smooth_non_manifold) ? 0 : 1;
02124   for (iedge = 0; iedge < feature_edge_list.size(); iedge++)
02125   {
02126     edge_ptr = feature_edge_list.get_and_step();
02127     edge_ptr->set_flag( flag );
02128     edge_ptr->point( 0 )->marked( flag );
02129     edge_ptr->point( 1 )->marked( flag );
02130   }
02131 
02132   // for non-manifold edges, find sets of adjacent facets that 
02133   // we can smooth across.  If adjacent facets do not satisfy the
02134   // feature angle criteria, then they should have C1 continuity
02135   // across the edge.  To do this, the normals at the edge's
02136   // points on partner edges will need to be the same.  This next
02137   // piece of code potentially alters the point normals.  As a result
02138   // edge and facet control points will need to be updated.
02139 
02140   DLIList<CubitFacet *>update_facet_list;
02141   if (smooth_non_manifold)
02142   {
02143     DLIList <CubitPoint *> changed_points;
02144     for (iedge = 0; iedge < feature_edge_list.size(); iedge++)
02145     {
02146       edge_ptr = feature_edge_list.get_and_step();
02147       if (edge_ptr->get_flag() == 1)
02148         continue;
02149       edge_ptr->set_flag( 1 );
02150       if (split_surfaces)
02151         stat = fix_split_non_manifold_edge( edge_ptr, mindot, 
02152                                             changed_points );
02153       else
02154         stat = fix_non_manifold_edge( edge_ptr, mindot, 
02155                                       changed_points );
02156       if (stat != CUBIT_SUCCESS)
02157         return stat;
02158     }
02159     if (changed_points.size() > 0)
02160       stat = update_edges_at_points( split_surfaces,
02161                                      changed_points, 
02162                                      update_facet_list,
02163                                      mindot );
02164     if (stat != CUBIT_SUCCESS)
02165       return stat;
02166   }
02167 
02168   // For all cases we need to ensure that partner edges share the same
02169   // control, point locations.  This piece of code goes through and
02170   // computes an average location for control points on partner edges
02171   // and sets them back on the edge
02172 
02173   for (iedge = 0; iedge < feature_edge_list.size(); iedge++)
02174   {
02175     edge_ptr = feature_edge_list.get_and_step();
02176     if (edge_ptr->get_flag() == 2)
02177       continue;
02178     edge_ptr->set_flag( 2 );
02179     if (split_surfaces)
02180       stat = fix_split_edge( edge_ptr, update_facet_list );
02181     else
02182       stat = fix_edge( edge_ptr, update_facet_list );
02183     if (stat != CUBIT_SUCCESS)
02184       return stat;
02185   }
02186 
02187   // since we have potentially modified the point normals and edge 
02188   // control points, we need to fix the facet control points (interior
02189   // to the facet) The update_facet_list contains a non-unique list of
02190   // facets that will need to be recomputed.
02191 
02192   int ii;
02193   CubitFacet *facet_ptr;
02194   for (ii=0; ii<update_facet_list.size(); ii++)
02195     update_facet_list.get_and_step()->marked( 0 );
02196 
02197   for (ii=0; ii<update_facet_list.size(); ii++)
02198   {
02199     facet_ptr = update_facet_list.get_and_step();
02200     if (facet_ptr->marked() == 0)
02201     {
02202       facet_ptr->marked( 1 );
02203       stat = FacetEvalTool::init_bezier_facet( facet_ptr );
02204       if (stat != CUBIT_SUCCESS)
02205         return stat;
02206     }
02207   }
02208 
02209   for (ii=0; ii<update_facet_list.size(); ii++)
02210     update_facet_list.get_and_step()->marked( 0 );
02211 
02212   return stat;
02213 }
02214 
02215 //===============================================================================
02216 //Function:  update_edges_at_points (PRIVATE)
02217 //Description: recompute the edge control points at all facets sharing
02218 //             points in the list
02219 //Date: 05/01
02220 //===============================================================================
02221 CubitStatus ChollaEngine::update_edges_at_points(
02222   CubitBoolean /* split_surfaces */,        // we are splitting facets to create geometry
02223   DLIList<CubitPoint *> &point_list,  // points whose edges will be updated
02224   DLIList<CubitFacet *> &facet_update_list,  // append facets adjacent edges that
02225                                              // will be updated later
02226   double mindot )
02227 {
02228   CubitStatus stat = CUBIT_SUCCESS;
02229   CubitPoint *point_ptr;
02230   CubitFacetEdge *edge_ptr;
02231   DLIList <CubitFacetEdge *> edge_list;
02232   int ii;
02233   for (ii=0; ii<point_list.size(); ii++)
02234   {
02235     point_ptr = point_list.get_and_step();
02236     point_ptr->edges( edge_list );
02237     point_ptr->facets( facet_update_list );
02238   }
02239   for (ii=0; ii<edge_list.size(); ii++)
02240   {
02241     edge_ptr = edge_list.get_and_step();
02242     edge_ptr->set_flag( 0 );
02243   }
02244   for (ii=0; ii<edge_list.size(); ii++)
02245   {
02246     edge_ptr = edge_list.get_and_step();
02247     if (edge_ptr->get_flag() == 0)
02248     {
02249       edge_ptr->set_flag( 1 );
02250       stat = FacetEvalTool::init_bezier_edge( edge_ptr, mindot );
02251     }
02252   }
02253   return stat;
02254 }
02255 
02256 //===============================================================================
02257 //Function:  fix_edge (PRIVATE)
02258 //Description: Enforce the condition where all partner edges to this edge
02259 //             share the same control points.  Compute the average of the
02260 //             partner control points and set on the edge
02261 //Date: 05/01
02262 //===============================================================================
02263 CubitStatus ChollaEngine::fix_edge( CubitFacetEdge *edge_ptr,
02264                                    DLIList<CubitFacet *> &update_facet_list)
02265 {
02266   if (edge_ptr->num_adj_facets() == 1)
02267     return CUBIT_SUCCESS;
02268   TDFacetBoundaryEdge *td_fbe =
02269     TDFacetBoundaryEdge::get_facet_boundary_edge( edge_ptr );
02270   if (!td_fbe)
02271     return CUBIT_FAILURE;
02272 
02273   edge_ptr->facets( update_facet_list );
02274   CubitStatus stat = td_fbe->merge_control_points();
02275   return stat;
02276 }
02277 
02278 //===============================================================================
02279 //Function:  fix_split_edge (PRIVATE)
02280 //Description: Enforce the condition where all partner edges to this edge
02281 //             share the same control points.  Compute the average of the
02282 //             partner control points and set on the edge
02283 //Date: 05/01
02284 //===============================================================================
02285 CubitStatus ChollaEngine::fix_split_edge( CubitFacetEdge *edge_ptr,
02286                                    DLIList<CubitFacet *> &update_facet_list)
02287 {
02288 
02289   // we only need to do this if the edge has any partners.  Otherwise return
02290 
02291   TDGeomFacet *td = TDGeomFacet::get_geom_facet( edge_ptr );
02292   if (td->num_partner_edges() == 0)
02293     return CUBIT_SUCCESS;
02294  
02295   // get the control points for this edge (oriented with
02296   // respect to point(0) on the edge)--- This means that
02297   // the rest of the partners to this edge must also
02298   // provide control points with respect to the same orientation
02299 
02300   CubitVector control_points[3];
02301   CubitPoint *start_ptr = edge_ptr->point(0);
02302   edge_ptr->get_control_points( start_ptr, control_points );
02303 
02304   // get all this edge's partners
02305 
02306   int ii;
02307   CubitVector partner_control_points[3];
02308   CubitFacetEdge *partner_edge_ptr;
02309   CubitPoint *partner_start_ptr;
02310   DLIList <CubitFacetEdge *> partner_edge_list;
02311   td->get_partner_edges( partner_edge_list );
02312   for (ii=0; ii<partner_edge_list.size(); ii++)
02313   {
02314     partner_edge_ptr = partner_edge_list.get_and_step();
02315     partner_edge_ptr->set_flag( 2 );
02316 
02317     // determine the same orientation as the first edge
02318 
02319     partner_start_ptr = partner_edge_ptr->point(0);
02320     TDGeomFacet *td_point = TDGeomFacet::get_geom_facet( partner_start_ptr );
02321     if (!td_point->is_partner( start_ptr ))
02322     {
02323       partner_start_ptr = partner_edge_ptr->point(1);
02324       td_point = TDGeomFacet::get_geom_facet( partner_start_ptr );
02325       if (!td_point->is_partner( start_ptr ))
02326       {
02327         PRINT_ERROR("Topology error generating facet geometry\n");
02328         return CUBIT_FAILURE;
02329       }
02330     }
02331 
02332     // get the partner's control points and add to the current
02333     // totals
02334 
02335     partner_edge_ptr->get_control_points( partner_start_ptr, 
02336                                       partner_control_points );
02337     control_points[0] += partner_control_points[0];
02338     control_points[1] += partner_control_points[1];
02339     control_points[2] += partner_control_points[2];
02340 
02341     // add this edge's adjacent facets to the update facet list
02342 
02343     partner_edge_ptr->facets( update_facet_list );
02344   }
02345   edge_ptr->facets( update_facet_list );
02346 
02347   // average the control point locations
02348 
02349   int nedges = partner_edge_list.size() + 1;
02350   control_points[0] /= (double)nedges;
02351   control_points[1] /= (double)nedges;
02352   control_points[2] /= (double)nedges;
02353 
02354   // set the new control points back on the edges
02355 
02356   edge_ptr->set_control_points( start_ptr, control_points );
02357 
02358   TDGeomFacet *td_point;
02359   for (ii=0; ii<partner_edge_list.size(); ii++)
02360   {
02361     partner_edge_ptr = partner_edge_list.get_and_step();
02362 
02363     // determine the same orientation as the first edge
02364 
02365     partner_start_ptr = partner_edge_ptr->point(0);
02366     td_point = TDGeomFacet::get_geom_facet( partner_start_ptr );
02367     if (!td_point->is_partner( start_ptr ))
02368     {
02369       partner_start_ptr = partner_edge_ptr->point(1);
02370       td_point = TDGeomFacet::get_geom_facet( partner_start_ptr );
02371       if (!td_point->is_partner( start_ptr ))
02372       {
02373         PRINT_ERROR("Topology error generating facet geometry\n");
02374         return CUBIT_FAILURE;
02375       }
02376     }
02377     partner_edge_ptr->set_control_points( partner_start_ptr,
02378                                            control_points );
02379   }
02380   return CUBIT_SUCCESS;
02381 }
02382 
02383 //===============================================================================
02384 //Function:  fix_non_split_manifold_edge (PRIVATE)
02385 //Description: Enforce the condition where partner edges on non-manifold edges
02386 //             with >2 adjacent facets that do not satisfy feature criteria
02387 //             will have the same normal accross the edge
02388 //Date: 05/01
02389 //===============================================================================
02390 CubitStatus ChollaEngine::fix_split_non_manifold_edge(
02391   CubitFacetEdge *edge_ptr,
02392   double min_dot,
02393   DLIList <CubitPoint *> &changed_points )
02394 {
02395   // first check if this edge has 3 or more adjacent facets.  Return now if not
02396 
02397   CubitStatus stat = CUBIT_SUCCESS;
02398   TDGeomFacet *td = TDGeomFacet::get_geom_facet( edge_ptr );
02399   int nedges = td->num_partner_edges() + 1;
02400   if (nedges < 3)
02401     return stat;
02402 
02403   // make an array of partner edges
02404 
02405   std::vector<int> partner0(nedges);
02406   std::vector<int> partner1(nedges);
02407   std::vector<double> partner_dot(nedges);
02408   int num_partners = 0;
02409   std::vector<CubitFacetEdge*> edges(nedges);
02410 
02411   edges[0] = edge_ptr;
02412   DLIList<CubitFacetEdge *> partner_list;
02413   td->get_partner_edges( partner_list );
02414   int ii;
02415   for (ii=0; ii< partner_list.size(); ii++)
02416   {
02417     edges[ii+1] = partner_list.get_and_step();
02418     edges[ii+1]->set_flag( 1 );
02419   }
02420 
02421   
02422   // check each facet against every other facet at this edge to
02423   // see if we need to enforce continuity.  There may be several
02424   // cases where the feature angle criteria is (not) met.  Find
02425   // the pair that has the greatest dot product between them.
02426   // If more than 1 pair has the same dot product and meets criteria
02427   // then it arbitrarily uses the first one.
02428 
02429   int jj, kk;
02430   for (ii=0; ii<nedges-1; ii++)
02431   {
02432     CubitFacet *facet_ptr = edges[ii]->adj_facet( 0 );
02433     CubitVector normal = facet_ptr->normal();
02434     normal.normalize();
02435     double best_dot = -1.0;
02436     for (jj=ii+1; jj<nedges; jj++)
02437     {
02438       CubitFacet *afacet_ptr = edges[jj]->adj_facet( 0 );
02439       CubitVector anormal = afacet_ptr->normal();
02440       anormal.normalize();
02441       double dot = fabs(normal % anormal);
02442       if (dot > min_dot && dot > best_dot)
02443       {
02444 
02445         // check to see if this partner pair has not already
02446         // been used in another partnership.  If so, then check
02447         // to see if this match is better.  Otherwise, ignore
02448         // this match.
02449 
02450         int found = 0;
02451         for (kk=0; kk<num_partners; kk++)
02452         {
02453           if (partner0[kk] == ii || partner0[kk] == jj ||
02454               partner1[kk] == ii || partner1[kk] == jj)
02455           {
02456             found = 1;
02457             if (dot > partner_dot[kk])
02458             {
02459               partner_dot[kk] = dot;
02460               partner0[kk] = ii;
02461               partner1[kk] = jj;
02462             }
02463           }
02464         }
02465         if (!found)
02466         {
02467           partner_dot[num_partners] = dot;
02468           partner0[num_partners] = ii;
02469           partner1[num_partners] = jj;
02470           num_partners++;
02471         }
02472         best_dot = dot;
02473       }
02474     }
02475   }
02476 
02477   // we found a partner facet(s) that needs to have C1 continuity
02478   // across this facet.  Merge the normals on the edge so they
02479   // are the same
02480 
02481   for (ii=0; ii<num_partners; ii++)
02482   {
02483     CubitFacetEdge *edge0 = edges[partner0[ii]];
02484     CubitFacetEdge *edge1 = edges[partner1[ii]];
02485     for (jj=0; jj<2; jj++)
02486     {
02487       CubitPoint *pt0 = edge0->point(jj);
02488 
02489       // find its point partner on the partner edge
02490 
02491       CubitPoint *pt1 = edge1->point( 0 );
02492       td = TDGeomFacet::get_geom_facet( pt0 );
02493       if (!td->is_partner( pt1 ))
02494       {
02495         pt1 = edge1->point( 1 );
02496         if (!td->is_partner( pt1 ))
02497         {
02498           PRINT_ERROR("Internal error defining continuity across non-manifold edges\n");
02499           return CUBIT_FAILURE;
02500         }
02501       }
02502       if (pt0->marked() == 0 || pt1->marked() == 0)
02503       {
02504         pt0->marked( 1 );
02505         pt1->marked( 1 );
02506         changed_points.append( pt0 );
02507         changed_points.append( pt1 );
02508         stat = merge_normals( pt0, pt1 );
02509         if (stat != CUBIT_SUCCESS)
02510           return stat;
02511       }
02512     }
02513   }
02514   
02515   return stat;
02516 }
02517 
02518 //===============================================================================
02519 //Function:  fix_non_manifold_edge (PRIVATE)
02520 //Description: Enforce the condition where partner edges on non-manifold edges
02521 //             with >2 adjacent facets that do not satisfy feature criteria
02522 //             will have the same normal accross the edge
02523 //Date: 05/01
02524 //===============================================================================
02525 CubitStatus ChollaEngine::fix_non_manifold_edge(
02526   CubitFacetEdge *edge_ptr,
02527   double min_dot,
02528   DLIList <CubitPoint *> &changed_points )
02529 {
02530   // first check if this edge has 3 or more adjacent facets.  Return now if not
02531 
02532   CubitStatus stat = CUBIT_SUCCESS;
02533   int nfacets = edge_ptr->num_adj_facets();
02534   if (nfacets < 3)
02535     return stat;
02536 
02537   TDFacetBoundaryEdge *td_fbe =
02538     TDFacetBoundaryEdge::get_facet_boundary_edge( edge_ptr );
02539   if (td_fbe == NULL)
02540   {
02541     return CUBIT_FAILURE;  // there is supposed to be a tool data here!
02542   }
02543 
02544   // make an array of partner edges
02545 
02546   int *partner0 = new int [nfacets];
02547   int *partner1 = new int [nfacets];
02548   double *partner_dot = new double [nfacets];
02549   int num_partners = 0;
02550   CubitFacet **facets = new CubitFacet * [nfacets];
02551   if (!facets || !partner0 || !partner1 || !partner_dot)
02552     return CUBIT_FAILURE;
02553   DLIList <CubitFacet *>adj_facets;
02554   edge_ptr->facets( adj_facets );
02555   int ii;
02556   for (ii=0; ii< adj_facets.size(); ii++)
02557   {
02558     facets[ii] = adj_facets.get_and_step();
02559     facets[ii]->marked( 1 );
02560   }
02561 
02562   
02563   // check each facet against every other facet at this edge to
02564   // see if we need to enforce continuity.  There may be several
02565   // cases where the feature angle criteria is (not) met.  Find
02566   // the pair that has the greatest dot product between them.
02567   // If more than 1 pair has the same dot product and meets criteria
02568   // then it arbitrarily uses the first one.
02569 
02570   int jj, kk;
02571   for (ii=0; ii<nfacets-1; ii++)
02572   {
02573     CubitFacet *facet_ptr = facets[ii];
02574     CubitVector normal = facet_ptr->normal();
02575     normal.normalize();
02576     double best_dot = -1.0;
02577     for (jj=ii+1; jj<nfacets; jj++)
02578     {
02579       CubitFacet *afacet_ptr = facets[jj];
02580       CubitVector anormal = afacet_ptr->normal();
02581       anormal.normalize();
02582       double dot = fabs(normal % anormal);
02583       if (dot > min_dot && dot > best_dot)
02584       {
02585 
02586         // check to see if this partner pair has not already
02587         // been used in another partnership.  If so, then check
02588         // to see if this match is better.  Otherwise, ignore
02589         // this match.
02590 
02591         int found = 0;
02592         for (kk=0; kk<num_partners; kk++)
02593         {
02594           if (partner0[kk] == ii || partner0[kk] == jj ||
02595               partner1[kk] == ii || partner1[kk] == jj)
02596           {
02597             found = 1;
02598             if (dot > partner_dot[kk])
02599             {
02600               partner_dot[kk] = dot;
02601               partner0[kk] = ii;
02602               partner1[kk] = jj;
02603             }
02604           }
02605         }
02606         if (!found)
02607         {
02608           partner_dot[num_partners] = dot;
02609           partner0[num_partners] = ii;
02610           partner1[num_partners] = jj;
02611           num_partners++;
02612         }
02613         best_dot = dot;
02614       }
02615     }
02616   }
02617 
02618   // we found a partner facet(s) that needs to have C1 continuity
02619   // across this facet.  Merge the normals on the edge so they
02620   // are the same
02621 
02622   if (num_partners > 0)
02623   {
02624     CubitPoint *pt0 = edge_ptr->point(0);
02625     CubitPoint *pt1 = edge_ptr->point(1);
02626     TDFacetBoundaryPoint *td_fbp0 =
02627       TDFacetBoundaryPoint::get_facet_boundary_point( pt0 );
02628     TDFacetBoundaryPoint *td_fbp1 =
02629       TDFacetBoundaryPoint::get_facet_boundary_point( pt1 );
02630     if (!td_fbp0 || !td_fbp1) {
02631       delete [] facets;
02632       delete [] partner0;
02633       delete [] partner1;
02634       delete [] partner_dot;
02635       return CUBIT_FAILURE;
02636     }
02637 
02638     for (ii=0; ii<num_partners; ii++)
02639     {
02640       td_fbp0->merge_normals( facets[partner0[ii]], facets[partner1[ii]] );
02641       td_fbp1->merge_normals( facets[partner0[ii]], facets[partner1[ii]] );
02642     }
02643     pt0->marked( 1 );
02644     pt1->marked( 1 );
02645     changed_points.append( pt0 );
02646     changed_points.append( pt1 );
02647   }
02648   
02649   delete [] facets;
02650   delete [] partner0;
02651   delete [] partner1;
02652   delete [] partner_dot;
02653 
02654   return stat;
02655 }
02656 
02657 //===============================================================================
02658 //Function:  merge_normals (PRIVATE)
02659 //Description: Enforce continuity across facets by merging the normals at two
02660 //             points.  Assumes the points are coincident.
02661 //Date: 05/01
02662 //===============================================================================
02663 CubitStatus ChollaEngine::merge_normals(
02664   CubitPoint *pt0,
02665   CubitPoint *pt1)
02666 {
02667 
02668   DLIList<CubitFacet*> adj_facet_list0;
02669   pt0->facets(adj_facet_list0);
02670   if (adj_facet_list0.size() == 0)
02671     return CUBIT_FAILURE;
02672 
02673   CubitVector avg_normal(0.0e0, 0.0e0, 0.0e0);
02674   double totangle = 0.0e0;
02675   double angle;
02676   CubitFacet *facet;
02677   int j;
02678 
02679   // weight the normal by the spanning angle at the point
02680 
02681   for (j = 0; j < adj_facet_list0.size(); j++)
02682   {
02683     facet = adj_facet_list0.get_and_step();
02684     angle = facet->angle( pt0 );
02685     facet->weight( angle );
02686     totangle += angle;
02687   }
02688   DLIList<CubitFacet*> adj_facet_list1;
02689   pt1->facets(adj_facet_list1);
02690   if (adj_facet_list1.size() == 0)
02691     return CUBIT_FAILURE;
02692   for (j = 0; j < adj_facet_list1.size(); j++)
02693   {
02694     facet = adj_facet_list1.get_and_step();
02695     angle = facet->angle( pt1 );
02696     facet->weight( angle );
02697     totangle += angle;
02698   }
02699 
02700   // computed weighted normal
02701 
02702   CubitVector normal;
02703   for (j = 0; j < adj_facet_list0.size(); j++)
02704   {
02705     facet = adj_facet_list0.get_and_step();
02706     normal = facet->normal();
02707     normal.normalize();
02708     avg_normal += (facet->weight() / totangle) * normal;
02709   }
02710   
02711   // orientation of facets may be opposite on opposing surfaces.
02712   // Check for this case and correct of necessary
02713   
02714   CubitVector norm0, norm1;
02715   norm0 = pt0->normal();
02716   norm0.normalize();
02717   norm1 = pt1->normal();
02718   norm1.normalize();
02719   double dot = norm0 % norm1;
02720   double sign = 1.0;
02721   if (dot < 0.0)
02722     sign = -1.0;
02723 
02724   for (j = 0; j < adj_facet_list1.size(); j++)
02725   {
02726     facet = adj_facet_list1.get_and_step();
02727     normal = sign * facet->normal();
02728     normal.normalize();
02729     avg_normal += (facet->weight() / totangle) * normal;
02730   }
02731 
02732   // set the new normal on both points
02733 
02734   avg_normal.normalize();
02735   pt0->normal(avg_normal);
02736   CubitVector temp_vector = sign * avg_normal;
02737   pt1->normal(temp_vector);
02738   double coefd = -(pt0->coordinates()%avg_normal);
02739   pt0->d_coef( coefd );
02740   pt1->d_coef( sign * coefd );
02741 
02742   return CUBIT_SUCCESS;
02743 }
02744 
02745 //===============================================================================
02746 //Function:  print_me (PRIVATE)
02747 //Description: debug
02748 //===============================================================================
02749 void ChollaEngine::print_me()
02750 {
02751   FILE *fp = fopen( "fbg.out", "w" );
02752   int ii, jj, kk;
02753   for (ii=0; ii<chollaSurfaceList.size(); ii++)
02754   {
02755     ChollaSurface *chsurf_ptr = chollaSurfaceList.get_and_step();
02756     fprintf( fp, "*********** Surface %d ***************\n", chsurf_ptr->get_id());
02757     DLIList<ChollaCurve *> fcm_list;
02758     chsurf_ptr->get_curves( fcm_list );
02759     for (jj=0; jj<fcm_list.size(); jj++)
02760     {
02761       ChollaCurve *chcurv_ptr = fcm_list.get_and_step();
02762       fprintf(fp, "   Curve %d\n", chcurv_ptr->get_id() );
02763       //CubitVector start, end;
02764       DLIList<ChollaPoint *> fpm_list = chcurv_ptr->get_points();
02765       for (kk=0; kk<fpm_list.size(); kk++)
02766       {
02767         ChollaPoint *chpnt_ptr = fpm_list.get_and_step();
02768         FacetEntity *facet_point = chpnt_ptr->get_facets();
02769         if (facet_point)
02770         {
02771           CubitPoint *point_ptr = CAST_TO(facet_point, CubitPoint);
02772           CubitVector pt = point_ptr->coordinates();
02773           fprintf(fp, "      (%d) x = %8.4f y = %8.4f z = %8.4f\n",
02774                   chpnt_ptr->get_id(), pt.x(), pt.y(), pt.z());
02775         }
02776       }
02777     }
02778   }
02779   fclose(fp);
02780 }
02781 
02782 //===============================================================================
02783 //Function:  dump (PUBLIC)
02784 //Description: debug
02785 //===============================================================================
02786 void ChollaEngine::dump( const char *filename, double angle )
02787 {
02788   int include_results = 0;
02789   int num_face = faceList.size();
02790   int num_edge = edgeList.size();
02791   int num_vert = pointList.size();
02792   int *face_edge = new int [3*num_face];
02793   int *edge_vert = new int [2*num_edge];
02794   double *vert = new double [3*num_vert];
02795 
02796   int ii;
02797   CubitVector loc;
02798   CubitPoint *point_ptr;
02799   pointList.reset();
02800   for (ii=0; ii<num_vert; ii++)
02801   {
02802     point_ptr = dynamic_cast<CubitPoint *>(pointList.get_and_step());
02803     point_ptr->set_id( ii );
02804     loc = point_ptr->coordinates();
02805     vert[ii*3] = loc.x();
02806     vert[ii*3+1] = loc.y();
02807     vert[ii*3+2] = loc.z();
02808   }
02809 
02810   CubitFacetEdge *edge_ptr;
02811   edgeList.reset();
02812   for (ii=0; ii<num_edge; ii++)
02813   {
02814     edge_ptr = dynamic_cast<CubitFacetEdge *>(edgeList.get_and_step());
02815     edge_ptr->set_id( ii );
02816     edge_vert[ii*2] = edge_ptr->point( 0 )->id();
02817     edge_vert[ii*2+1] = edge_ptr->point( 1 )->id();
02818   }
02819 
02820   CubitFacet *facet_ptr;
02821   faceList.reset();
02822   for(ii=0; ii<num_face; ii++)
02823   {
02824     facet_ptr = dynamic_cast<CubitFacet *>(faceList.get_and_step());
02825     face_edge[ii*3] = facet_ptr->edge( 0 )->id();
02826     face_edge[ii*3+1] = facet_ptr->edge( 1 )->id();
02827     face_edge[ii*3+2] = facet_ptr->edge( 2 )->id();
02828   }
02829 
02830   double *edge_control_points = new double [3*3*num_edge];
02831   double *tri_control_points = new double [3*6*num_face];
02832   double *quad_control_points = NULL;
02833 
02834   char mesh_filename[256];
02835   sprintf(mesh_filename, "%s.mesh", filename);
02836   dumpMesh(mesh_filename, include_results, angle, num_face, 0, num_edge,
02837            num_vert, face_edge, NULL, edge_vert, vert, edge_control_points, 
02838            tri_control_points, quad_control_points);
02839 
02840   constructBezier( angle, num_face, 0, num_edge, num_vert, face_edge, NULL,
02841                    edge_vert, vert, edge_control_points, tri_control_points,
02842                    quad_control_points );
02843 
02844   char result_filename[256];
02845   sprintf(result_filename, "%s.results", filename);
02846   dumpResults(result_filename, num_edge, num_face, 0, 
02847               edge_control_points, tri_control_points, quad_control_points );
02848 
02849   include_results = 1;
02850   char full_filename[256];
02851   sprintf(full_filename, "%s.full", filename);
02852   dumpMesh(full_filename, include_results, angle, num_face, 0, num_edge,
02853            num_vert, face_edge, NULL, edge_vert, vert, edge_control_points, 
02854            tri_control_points, quad_control_points);
02855 
02856   delete [] face_edge;
02857   delete [] edge_vert;
02858   delete [] vert;
02859   delete [] edge_control_points;
02860   delete [] tri_control_points;
02861 }
02862 
02863 //===============================================================================
02864 //Function:  mark_features (PUBLIC)
02865 //Description: Calling this before ChollaEngine create geometry / topology
02866 // allows you to define features points. This can be used in conjunction
02867 // with the feature angle option or exclusively (original intention).
02868 //===============================================================================
02869 void ChollaEngine::mark_features (DLIList<CubitPoint*> &feature_points)
02870 {
02871   int ii;
02872   TDGeomFacet *td_gm = NULL;
02873   CubitPoint *curr_pt = NULL;
02874 
02875     // loop through supplied CubitPoint*
02876     // set the hit flag on each one
02877   
02878   for (ii=0; ii < feature_points.size(); ++ii)
02879   {
02880     curr_pt = feature_points.get_and_step();
02881     TDGeomFacet::add_geom_facet(curr_pt, -1);
02882     td_gm = TDGeomFacet::get_geom_facet(curr_pt);
02883     td_gm->set_hit_flag(1);
02884     curr_pt->set_as_feature();
02885   }
02886 }
02887 
02888 //===============================================================================
02889 //Function:  mark_features (PUBLIC)
02890 //Description: Calling this before ChollaEngine create geometry / topology
02891 // allows you to define features points. This can be used in conjunction
02892 // with the feature angle option or exclusively (original intention).
02893 //===============================================================================
02894 void ChollaEngine::mark_features (DLIList<CubitFacetEdge*> &feature_edges)
02895 {
02896   int ii;
02897   CubitFacetEdge *curr_edge = NULL;
02898     
02899     // loop through supplied CubitFaceEdge*
02900     // set the hit flag on each one
02901 
02902   for (ii=0; ii < feature_edges.size(); ++ii)
02903   {
02904     curr_edge = feature_edges.get_and_step();
02905     curr_edge->set_as_feature();
02906   }
02907 }
02908 
02909   
02910 static CubitStatus create_tri_facets(int *face_list,int current_position,
02911                                      CubitPoint **point_list,
02912                                      DLIList <CubitFacet*> &facet_list)
02913 {
02914   int step = face_list[current_position];
02915     //This function is hard coded to work for splitting 4, 5, and 6
02916     //faceted points into triangles.
02917   if ( step > 6 || step < 4 )
02918   {
02919     PRINT_ERROR("Trying to split facets with wrong function.\n");
02920     return CUBIT_FAILURE;
02921   }
02922     //Basically get the points in a list first.
02923   int ii = current_position + 1, jj;
02924   DLIList <CubitPoint*> temp_points;
02925   
02926   for( jj = ii; jj < ii+step; jj++ )
02927   {
02928     int index_to_point = face_list[jj];
02929     assert(index_to_point >= 0 );
02930     temp_points.append(point_list[index_to_point]);
02931   }
02932     //Now cycle through the points and creat facets from them.
02933   CubitPoint *point_1, *point_2, *point_3;
02934     //This definatly could be improved to get more optimal triangles...
02935     //Create the first two facets in the normal way.  This is the
02936     //same for 4, 5 and 6 points.
02937   for ( jj = 0; jj < 2; jj++ )
02938   {
02939     point_1 = temp_points.get_and_step();
02940     point_2 = temp_points.get_and_step();
02941     point_3 = temp_points.get();
02942       //If these are colinear we are screwed...
02943     CubitFacet *new_facet = (CubitFacet *)
02944       new CubitFacetData(point_1, point_2, point_3);
02945     facet_list.append(new_facet);
02946   }
02947     //create the third facet for 5 points.
02948   if ( step == 5 )
02949   {
02950       //Now create the last facet with the first point, last point and
02951       //third point.
02952     temp_points.reset();
02953     point_1 = temp_points.prev();
02954     point_2 = temp_points.get();
02955     point_3 = temp_points.next(2);
02956     CubitFacet *new_facet = (CubitFacet *)
02957       new CubitFacetData(point_1, point_2, point_3);
02958     facet_list.append(new_facet);
02959   }
02960     //create the third and fourth for 6 points.
02961   else if ( step == 6 )
02962   {
02963       //get the current point (should be position 5/6)
02964     point_1 = temp_points.get();
02965       //get the next point. (should be position 6/6)
02966     point_2 = temp_points.next();
02967       //get the prev(2) point. ( should be position 3/6)
02968     point_3 = temp_points.prev(2);
02969     CubitFacet *new_facet = (CubitFacet *)
02970       new CubitFacetData(point_1, point_2, point_3);
02971     facet_list.append(new_facet);
02972       // get the next point. (should be 6/6)
02973     point_1 = temp_points.next();
02974       // get the next 2 point ( should be 1/6)
02975     point_2 = temp_points.next(2);
02976       //point3 stays the same (position 3/6).
02977     new_facet = (CubitFacet *)
02978       new CubitFacetData(point_1, point_2, point_3);
02979     facet_list.append(new_facet);
02980   }
02981   return CUBIT_SUCCESS;
02982 }
02983 
02984 //===================================================================================
02985 // Description: given facets in the form of a GMem data structure create new
02986 //              CubitFacet and CubitPoint classes and return in lists
02987 // Notes: 
02988 // Author: 
02989 // Date: 
02990 //===================================================================================
02991 CubitStatus ChollaEngine::get_facets(GMem& gMem, DLIList<CubitFacet*> &facet_list, 
02992                                      DLIList<CubitPoint*> &dl_point_list,
02993                                      bool insert_null_facets )
02994 {
02995   if(gMem.fListCount == 0)
02996     return CUBIT_FAILURE;
02997 
02998   GPoint* plist = gMem.point_list();
02999   CubitPoint **point_list = (CubitPoint **)
03000     new CubitPointData *[gMem.pointListCount];
03001   double x, y, z;
03002   int i,j;
03003   for (i = 0; i<gMem.pointListCount; i++) 
03004   {
03005     x = plist[i].x;
03006     y = plist[i].y;
03007     z = plist[i].z;
03008     CubitPoint *new_point = (CubitPoint *) new CubitPointData(x, y, z);
03009     point_list[i] = new_point;
03010     dl_point_list.append(new_point);
03011   } 
03012   int *face_list = gMem.facet_list();
03013   int step;
03014   DLIList<CubitPoint*> temp_points;
03015   CubitFacet *new_facet;
03016   int ii, index_to_point;
03017   CubitStatus stat1;
03018   for ( i = 0; i < gMem.fListCount; i++ )
03019   {
03020     step = face_list[i];
03021       //Now get the points for this facet.
03022     switch (step)
03023     {
03024       case 3:
03025         ii = i + 1;
03026         temp_points.clean_out();
03027         for( j = ii; j < ii+step; j++ )
03028         {
03029           index_to_point = face_list[j];
03030           assert(index_to_point >= 0 && index_to_point <= gMem.pointListCount );
03031           temp_points.append(point_list[index_to_point]);
03032         }
03033 
03034         if( temp_points.get() != temp_points.next() &&
03035             temp_points.get() != temp_points.next(2) &&
03036             temp_points.next() != temp_points.next(2) )
03037         {
03038           new_facet = (CubitFacet *)
03039           new CubitFacetData(temp_points.get(), 
03040                              temp_points.next(),
03041                              temp_points.next(2) );
03042           facet_list.append(new_facet);
03043         }
03044         i = i+step;
03045         break;
03046       case 4:
03047       case 5:
03048       case 6:
03049         stat1 = create_tri_facets(face_list,i, point_list,
03050                                   facet_list);
03051         if ( stat1 != CUBIT_SUCCESS )
03052         {
03053           PRINT_ERROR("Facets were not triangular and couldn't be split\n");
03054           return stat1;
03055         }
03056         i = i+step;
03057         break;
03058       default:
03059           //We currently can't handle this...
03060           //Eventually we will have to split this polygon into more facets.
03061         PRINT_ERROR("Facets were not triangular, and couldn't be made so.\n");
03062         PRINT_ERROR("Surface has: %d points forming a facet.\n", step);
03063         if( insert_null_facets )
03064           facet_list.append( NULL );
03065         return CUBIT_FAILURE;
03066     }
03067   }
03068   delete [] point_list;
03069   return CUBIT_SUCCESS;
03070 }
03071 
03072 //=============================================================================
03073 //Function: collapses a given curve to a given point_to_keep
03074 //          
03075 //Description:
03076 //Note: the hashing and other data structures are not updated during collapse.
03077 //Author: william roshan quadros
03078 //Date:  12/15/08
03079 //=============================================================================
03080 CubitStatus ChollaEngine::collapse_curve( ChollaCurve *cholla_curve, ChollaPoint *point_to_keep )
03081 {
03082   // Make sure there are no underlying facet edges connected with this curve
03083   if( cholla_curve->get_facet_list().size() )
03084     return CUBIT_FAILURE;
03085   
03086   // Disassociate from cholla_surfaces 
03087   DLIList<ChollaSurface *> &ref_surfaces = cholla_curve->get_surfaces();
03088   int i;
03089   ChollaSurface *cholla_surface;
03090   for( i = 0; i < ref_surfaces.size(); i++ )
03091   {
03092     cholla_surface = ref_surfaces.get_and_step();
03093     cholla_surface->remove_curve( cholla_curve );
03094   }
03095   ref_surfaces.clean_out();
03096 
03097   // Disassociate from cholla point_to_delete 
03098   // Make sure curve has at least one point
03099   DLIList<ChollaPoint *> &cholla_pnts = cholla_curve->get_points();
03100   if( 0 == cholla_pnts.size()  )
03101     return CUBIT_FAILURE;
03102 
03103     // free eval tool
03104   if( cholla_curve->get_eval_tool() )
03105   {
03106     delete cholla_curve->get_eval_tool(); 
03107   }
03108 
03109   // find the point to delete
03110   ChollaPoint *first_pnt = cholla_pnts.get_and_step();
03111   ChollaPoint *last_pnt = cholla_pnts.get();
03112   ChollaPoint *point_to_del = NULL;
03113   switch( cholla_pnts.size() )
03114   {
03115 
03116   case 2:    
03117     if( point_to_keep == last_pnt )
03118     {
03119       point_to_del = first_pnt;
03120     }
03121     else
03122     {
03123       if( point_to_keep == first_pnt )
03124       {
03125         point_to_del = last_pnt;
03126       }
03127     }
03128 
03129     // disassociate end points from cholla_curve
03130     if( point_to_del )
03131     {
03132       point_to_del->remove_curve( cholla_curve );
03133       cholla_pnts.remove( point_to_del );
03134     }
03135     if( point_to_keep )
03136     {
03137       point_to_keep->remove_curve( cholla_curve );
03138       cholla_pnts.remove( point_to_keep );
03139     }
03140 
03141     // Merge two points 
03142     merge_two_points( point_to_keep, point_to_del );
03143 
03144     break;
03145 
03146   case 1:
03147     // disassociate end points from cholla_curve
03148     point_to_del = first_pnt;
03149     point_to_del->remove_curve( cholla_curve );
03150     cholla_pnts.remove( point_to_del );
03151     
03152     if( 0 == point_to_del->get_curve_list_ptr()->size() )
03153     {
03154       // remove point_to_del from ChollaEngine
03155       remove_point( point_to_del );
03156 
03157       // free point_to_del
03158       delete point_to_del;
03159     }    
03160     break;
03161 
03162   default:
03163     return CUBIT_FAILURE;
03164   }
03165 
03166 
03167   // Disassociate curve from chollaEngine
03168   this->remove_curve( cholla_curve );
03169 
03170   // free the cholla_curve
03171   delete cholla_curve;
03172 
03173   return CUBIT_SUCCESS;
03174 }
03175 
03176   // Merge two points 
03177 CubitStatus ChollaEngine::merge_two_points( ChollaPoint *point_to_keep, ChollaPoint *point_to_del )
03178 {
03179   // move cholla curves from point_to_del to point_to_keep
03180   DLIList<ChollaCurve *> &del_pnt_curves = point_to_del->get_curves();
03181   int i;
03182   ChollaCurve *cholla_curve;
03183   for( i = 0; i < del_pnt_curves.size(); i++ )
03184   {
03185     cholla_curve = del_pnt_curves.get_and_step();
03186     
03187     cholla_curve->remove_point( point_to_del );
03188     cholla_curve->add_point( point_to_keep );
03189     point_to_keep->add_curve( cholla_curve );
03190   }
03191   del_pnt_curves.clean_out();
03192 
03193   // if point_to_keep facet is null use point_to_del's facet
03194   if( NULL == point_to_keep->get_facets() && point_to_del->get_facets() )
03195   {
03196     point_to_keep->add_facet( point_to_del->get_facets() );
03197   }
03198   
03199   // what we should do with data member id?  should we move if point_to_keep->get_id() !=  0?
03200 
03201   // remove point_to_del from ChollaEngine
03202   remove_point( point_to_del );
03203 
03204   // free point_to_del
03205   delete point_to_del;
03206 
03207   return CUBIT_SUCCESS;
03208 }
03209 
03210 
03211 
03212 CubitStatus ChollaEngine::disassociate_surface( ChollaSurface *cholla_surf )
03213 {
03214    // remove surface from volume
03215   DLIList<ChollaVolume *> cholla_volumes;
03216   cholla_surf->get_volumes(cholla_volumes);
03217   int i;
03218   ChollaVolume *cholla_volume;
03219   for (i=0; i<cholla_volumes.size(); i++)
03220   {
03221     cholla_volume = cholla_volumes.get_and_step();
03222     cholla_volume->remove_surface( cholla_surf );
03223   }
03224   
03225    // Disassociate curves from suface
03226   DLIList< ChollaCurve *> cholla_curves;
03227   cholla_surf->get_curves( cholla_curves );
03228   
03229   ChollaCurve *cholla_curve;
03230   for( i = 0; i < cholla_curves.size(); i++ )
03231   {
03232     cholla_curve = cholla_curves.get_and_step();
03233     
03234     cholla_curve->remove_surface( cholla_surf );
03235     cholla_surf->remove_curve( cholla_curve );
03236   }
03237   cholla_curves.clean_out();
03238 
03239   // Remove facet tool if available ?
03240   if( cholla_surf->get_eval_tool() )
03241   {
03242 #ifdef _DEBUG
03243     //PRINT_INFO("WARNING: delete ch_surf->facet_eval_tool safely \n");//   
03244 #endif
03245     //delete cholla_surf->get_eval_tool();
03246     // set eval tool to NULL
03247   }
03248   
03249   // remove from ChollaEngine
03250   remove_surface( cholla_surf );
03251 
03252   return CUBIT_SUCCESS;
03253 
03254 }
03255 //=============================================================================
03256 //Function: collapses a given surface 
03257 //Description: currently it disassociates surface with its curves and ChollaEngine 
03258 //Note: make sure there are no underlying facets and model is automatically watertight when input cholla_surf is deleted
03259 //Author: william roshan quadros
03260 //Date:  12/15/08
03261 //=============================================================================
03262 
03263 CubitStatus ChollaEngine::collapse_surface( ChollaSurface *cholla_surf )
03264 {
03265   // Make sure there are no facets 
03266   if( cholla_surf->get_facet_list().size() )
03267      return CUBIT_FAILURE; 
03268 
03269   disassociate_surface( cholla_surf );
03270   
03271   // free cholla surface
03272   delete cholla_surf;
03273 
03274   return CUBIT_SUCCESS;
03275 }
03276 
03277 CubitStatus ChollaEngine::remove_facet_entity( CubitFacet *facet, ChollaSurface *cholla_surf )
03278 {
03279   this->faceList.remove( facet );
03280 
03281   if( cholla_surf )
03282     cholla_surf->remove_facet( facet );
03283 
03284   return CUBIT_SUCCESS;
03285 }
03286   
03287 CubitStatus ChollaEngine::remove_facet_entity( CubitFacetEdge *facet_edge, ChollaCurve *cholla_curve )
03288 {
03289   this->edgeList.remove( facet_edge );
03290 
03291   if( cholla_curve )
03292     cholla_curve->remove_facet( facet_edge );
03293 
03294   return CUBIT_SUCCESS;
03295 }
03296 
03297 CubitStatus ChollaEngine::remove_facet_entity( CubitPoint *facet_pnt, ChollaPoint *cholla_point )
03298 {
03299   this->pointList.remove( facet_pnt );
03300 
03301   if( cholla_point )
03302     cholla_point->remove_facet(/* facet_pnt */);
03303 
03304   return CUBIT_SUCCESS;
03305 }
03306 
03307 CubitStatus ChollaEngine::remove_facet_entity( CubitFacet *facet, std::set<ChollaEntity *> &cholla_surfs )
03308 {
03309   std::set<ChollaEntity *>::iterator set_it;
03310   for( set_it = cholla_surfs.begin(); set_it != cholla_surfs.end(); set_it++ )
03311   {
03312     if( dynamic_cast< ChollaSurface *>(*set_it) )
03313     {
03314       static_cast<ChollaSurface *>(*set_it)->remove_facet( facet );
03315     }
03316   }
03317 
03318   this->faceList.remove( facet );
03319 
03320   return CUBIT_SUCCESS;
03321 }
03322   
03323 CubitStatus ChollaEngine::remove_facet_entity( CubitFacetEdge *facet_edge, std::set<ChollaEntity *> &cholla_curves )
03324 {
03325   
03326   std::set<ChollaEntity *>::iterator set_it;
03327   for( set_it = cholla_curves.begin(); set_it != cholla_curves.end(); set_it++ )
03328   {
03329     if( dynamic_cast<ChollaCurve*>(*set_it) )
03330     { 
03331       dynamic_cast<ChollaCurve*>(*set_it)->remove_facet( facet_edge );
03332     }
03333   }
03334 
03335   this->edgeList.remove( facet_edge );
03336 
03337   return CUBIT_SUCCESS;
03338 }
03339 
03340 CubitStatus ChollaEngine::replace_facet_entity( CubitFacetEdge *remove_edge, CubitFacetEdge *replace_edge, std::set<ChollaEntity *> cholla_curves )
03341 {
03342   std::set<ChollaEntity *>::iterator set_it; 
03343   for( set_it = cholla_curves.begin(); set_it != cholla_curves.end(); set_it++ )
03344   {
03345     if( dynamic_cast<ChollaCurve*>(*set_it) )
03346     { 
03347       static_cast<ChollaCurve*>(*set_it)->replace_facet( remove_edge, replace_edge );
03348     }
03349   }
03350 
03351   return CUBIT_SUCCESS;
03352 }
03353 
03354 
03355 CubitStatus ChollaEngine::remove_facet_entity( CubitPoint *facet_pnt, std::set<ChollaEntity *> &cholla_points )
03356 {
03357   this->pointList.remove( facet_pnt );
03358 
03359   std::set<ChollaEntity *>::iterator set_it;
03360   for( set_it = cholla_points.begin(); set_it != cholla_points.end(); set_it++ )
03361   {
03362     if( dynamic_cast<ChollaPoint*>(*set_it) )
03363     { 
03364       static_cast<ChollaPoint*>(*set_it)->remove_facet( facet_pnt );
03365     }
03366   }
03367 
03368   return CUBIT_SUCCESS;
03369 }
03370 
03371 /*
03372 // disassoicate ch_entity from ch_points, ch_curve, ch_surf, and ch_engine
03373 CubitStatus ChollaEngine::disassociate_curve( ChollaCurve *ch_curve )
03374 {
03375   
03376   // disassociate from cholla points
03377   ch_curve->disassociate_from_points();
03378   
03379   // disassociate from cholla surface
03380   ch_curve->disassociate_from_surfaces();
03381 
03382   // disassociate from cholla engine
03383   remove_curve( ch_curve );
03384 
03385   return CUBIT_SUCCESS;
03386 }
03387 */
03388 
03389 CubitStatus ChollaEngine::create_surface( int block_id,
03390                                           ChollaSurface *&new_ch_surf )
03391 {
03392   new_ch_surf = new ChollaSurface( block_id );
03393   
03394   // add it to cholla engine
03395   chollaSurfaceList.append( new_ch_surf ); 
03396 
03397   return CUBIT_SUCCESS;
03398 }
03399 
03400  // Create new ch_curve and associate with end ch_points.  Add ch_curve to chollaEngine
03401 CubitStatus ChollaEngine::create_curve(int block_id, 
03402                                        ChollaPoint *new_ch_pnt0, 
03403                                        ChollaPoint *new_ch_pnt1, 
03404                                        ChollaCurve *&new_ch_curve
03405                                     )
03406 {
03407 
03408   
03409   new_ch_curve = new ChollaCurve( block_id );
03410 
03411   // associate with cholla points
03412   new_ch_curve->add_point( new_ch_pnt0 );
03413   new_ch_pnt0->add_curve( new_ch_curve );
03414   new_ch_curve->add_point( new_ch_pnt1 );
03415   new_ch_pnt1->add_curve( new_ch_curve );
03416 
03417 
03418   // update start and end facet points
03419   new_ch_curve->set_start( CAST_TO( new_ch_pnt0->get_facets(), CubitPointData) );
03420   new_ch_curve->set_end( CAST_TO( new_ch_pnt1->get_facets(), CubitPointData) );
03421 
03422   // add it to cholla engine
03423   chollaCurveList.append( new_ch_curve ); 
03424 
03425   return CUBIT_SUCCESS;
03426 }
03427 
03428 CubitStatus ChollaEngine::create_point( CubitPoint *pnt, ChollaPoint * &new_ch_pnt )
03429 {
03430   new_ch_pnt = new ChollaPoint();
03431   new_ch_pnt->add_facet( pnt );
03432   double *coordinate = new double[3];
03433   CubitVector coord_vect = pnt->coordinates();
03434   coordinate[0] = coord_vect[0];
03435   coordinate[1] = coord_vect[1];
03436   coordinate[2] = coord_vect[2];
03437   new_ch_pnt->assign_geometric_point( (void*) coordinate );
03438 
03439   return CUBIT_SUCCESS;
03440 }
03441 
03442 
03443 // disassoicate ch_curve from ch_points, ch_surfs, and ch_engine
03444 CubitStatus ChollaEngine::disassociate_curve( ChollaCurve *ch_curve, bool disassociate_with_vert, bool disassociate_with_surf, bool disassociate_with_model )
03445 {
03446   // remove ch_curve from ch_point
03447   int i;
03448   if( disassociate_with_vert )
03449   {
03450     for( i = 0; i < ch_curve->get_points().size(); i++ )
03451     {
03452       ch_curve->get_points().get_and_step()->remove_curve( ch_curve );
03453     }
03454     // remove ch_points
03455     ch_curve->get_points().clean_out();
03456   }
03457 
03458   if( disassociate_with_surf )
03459   {
03460     // remove ch_curve in ch_surface
03461     ChollaSurface *ptr_ch_surf;   
03462     for( i = 0; i < ch_curve->get_surfaces().size(); i++ )
03463     {
03464       ptr_ch_surf = ch_curve->get_surfaces().get_and_step();
03465       ptr_ch_surf->remove_curve( ch_curve );
03466     }
03467     // remove ch_surface
03468     ch_curve->get_surfaces().clean_out();
03469   }
03470 
03471   if( disassociate_with_model )
03472   {
03473     // remove from ch_engie
03474     this->remove_curve( ch_curve );
03475   }
03476 
03477   return CUBIT_SUCCESS;
03478 }
03479 
03480 //=============================================================================
03481 //Function: detach_volumes 
03482 //Description: Create independent manifold volumes from the non-manifold set 
03483 //Note: 
03484 //Author:sjowen
03485 //Date:  09/10/09
03486 //=============================================================================
03487 CubitStatus ChollaEngine::detach_volumes()
03488 {
03489   CubitStatus rv = CUBIT_SUCCESS;
03490  
03491   // define maps between the original entities and their copies so we can 
03492   // use them for detaching the facets
03493   
03494   std::map<ChollaSurface *, ChollaSurface *> surf_map;
03495   std::multimap<ChollaCurve *, ChollaCurve *> curve_map;
03496   std::multimap<ChollaPoint *, ChollaPoint *> point_map; 
03497   
03498   for( int i=chollaVolumeList.size(); i--; )
03499   {
03500     ChollaVolume *chvol = chollaVolumeList.get_and_step();
03501     DLIList<ChollaSurface*> ch_surfaces;
03502     chvol->get_surfaces( ch_surfaces );    
03503 
03504     std::map<ChollaCurve *, ChollaCurve *> tmp_curve_map;
03505     std::map<ChollaPoint *, ChollaPoint *> tmp_point_map; 
03506     
03507     DLIList<ChollaSurface*> surfaces_to_detach;
03508     DLIList<ChollaCurve*> curves_to_detach;
03509     for( int j=ch_surfaces.size(); j--; )
03510     {
03511       ChollaSurface *chsurf_ptr = ch_surfaces.get_and_step();     
03512 
03513       // look for any surfaces that are associated with exactly two volumes
03514       if (chsurf_ptr->num_volumes() == 2)      
03515         surfaces_to_detach.append( chsurf_ptr );   
03516       else
03517       {
03518         //look for any curves that are attached to two volumes
03519         DLIList<ChollaCurve*> ch_curves;
03520         chsurf_ptr->get_curves( ch_curves );
03521         for( int k=ch_curves.size(); k--; )
03522         {
03523           ChollaCurve *tmp_curve = ch_curves.get_and_step();
03524           if( tmp_curve->num_volumes() > 1 )
03525             curves_to_detach.append( tmp_curve );
03526         }
03527       }
03528     }   
03529 
03530     //filter out curves that are in surfs in 'surfaces_to_detach'
03531     //since they will get detached when the parent surface gets detached
03532     for( int j=curves_to_detach.size(); j--; )
03533     {
03534       ChollaCurve *tmp_curve = curves_to_detach.get();
03535       DLIList<ChollaSurface*> tmp_surfs = tmp_curve->get_surfaces();
03536 
03537       for( int k=tmp_surfs.size(); k--; )
03538       {
03539         ChollaSurface *tmp_surf = tmp_surfs.get_and_step();
03540         if( surfaces_to_detach.is_in_list( tmp_surf ) )
03541         {
03542           curves_to_detach.change_to(NULL);
03543           break;
03544         }
03545       }
03546       curves_to_detach.step();    
03547     }  
03548     
03549     curves_to_detach.remove_all_with_value( NULL );
03550     curves_to_detach.uniquify_unordered();
03551 
03552     if( surfaces_to_detach.size() || curves_to_detach.size() )
03553     {
03554       rv = detach_surfaces( surfaces_to_detach, curves_to_detach, chvol, surf_map, tmp_curve_map, tmp_point_map );
03555       if (rv != CUBIT_SUCCESS)
03556         return CUBIT_FAILURE;
03557       
03558       //for all detached surfaces, detach all the facets and create new ones for
03559       //the detached surfaces
03560       rv = detach_facets(surfaces_to_detach, curves_to_detach, chvol, surf_map, tmp_curve_map, tmp_point_map);
03561       if (rv != CUBIT_SUCCESS)
03562         return rv;
03563 
03564       // set the cubitpoints at the correct start/end locations on the cholla curves   
03565       rv = set_curve_endpoints(tmp_point_map, tmp_curve_map );
03566       if (rv != CUBIT_SUCCESS)
03567         return rv;
03568     }
03569 
03570     //append the map to the multi-map
03571     std::map<ChollaCurve*, ChollaCurve*>::iterator iter = tmp_curve_map.begin();
03572     for( ; iter!=tmp_curve_map.end(); iter++)
03573       curve_map.insert( std::pair<ChollaCurve*,ChollaCurve*>(iter->first, iter->second) );
03574 
03575     //append the map to the multi-map
03576     std::map<ChollaPoint*, ChollaPoint*>::iterator pt_iter = tmp_point_map.begin();
03577     for( ; pt_iter!=tmp_point_map.end(); pt_iter++)
03578       point_map.insert( std::pair<ChollaPoint*,ChollaPoint*>(pt_iter->first, pt_iter->second) );   
03579   } 
03580   
03581   // create the evaluation tools on the new entities
03582   
03583   CubitBoolean use_feature_angle = CUBIT_FALSE; 
03584   double min_dot = 0.0;                    
03585   int interp_order = 0;                 
03586   CubitBoolean smooth_non_manifold = CUBIT_FALSE;
03587   CubitBoolean split_surfaces = CUBIT_FALSE;
03588   DLIList<ChollaSurface *> cholla_surfaces;
03589   DLIList<ChollaCurve *> cholla_curves;
03590   
03591   // get lists of new surfaces and curves from the maps
03592   
03593   std::map<ChollaSurface *, ChollaSurface *>::iterator smap_it;
03594   for (smap_it=surf_map.begin(); smap_it != surf_map.end(); smap_it++)
03595   {
03596     cholla_surfaces.append(smap_it->second);
03597   }
03598   
03599   std::multimap<ChollaCurve *, ChollaCurve *>::iterator cmap_it;
03600   for (cmap_it=curve_map.begin(); cmap_it != curve_map.end(); cmap_it++)
03601   {
03602     cholla_curves.append(cmap_it->second);
03603   }
03604   
03605   // rebuild the new curves so the edges are oriented correctly
03606   
03607   for (int ii=0; ii<cholla_curves.size(); ii++)
03608   {
03609     ChollaCurve *cholla_curve = cholla_curves.get_and_step();
03610     DLIList<ChollaPoint *>  cholla_points = cholla_curve->get_points();    
03611     int periodic = 0;
03612     if (cholla_points.size() == 1)
03613       periodic = 1;
03614     else
03615       assert(cholla_points.size() == 2);  // assuming we have exactly two end points so far
03616     CubitPoint *start_point, *end_point;
03617     cholla_curve->get_ends(start_point, end_point);        
03618     int max_edges = cholla_curve->num_edges();
03619     cholla_curve->clean_out_edges();  // edges will be added in build_curve_from_edges 
03620     rv = cholla_curve->build_curve_from_edges( start_point, periodic, max_edges, NULL, cholla_curve );
03621     if (rv != CUBIT_SUCCESS)
03622       return rv;
03623   } 
03624   
03625   // replace the facets on the existing eval tools on the curves and surfaces bounding the interface.
03626   // for simplicity, just replace them on all the existing eval tools on 
03627   
03628   for (int icurv = 0; icurv < chollaCurveList.size(); icurv++)
03629   {
03630     ChollaCurve *chcurv_ptr = chollaCurveList.get_and_step();
03631     CurveFacetEvalTool *ceval = chcurv_ptr->get_eval_tool();
03632     if (ceval != NULL)
03633     {
03634       DLIList<FacetEntity *> fedges = chcurv_ptr->get_facet_list();
03635       DLIList<CubitFacetEdge *> edges;
03636       CAST_LIST( fedges, edges, CubitFacetEdge );
03637       ceval->replace_facets(edges);
03638     }
03639   }
03640   
03641   for (int isurf=0; isurf<chollaSurfaceList.size(); isurf++)
03642   {
03643     ChollaSurface *chsurf_ptr = chollaSurfaceList.get_and_step();
03644     FacetEvalTool *seval = chsurf_ptr->get_eval_tool();
03645     if (seval != NULL)
03646     {
03647       DLIList<FacetEntity *> ffacets = chsurf_ptr->get_facet_list();
03648       DLIList<CubitFacet *> facets;
03649       CAST_LIST( ffacets, facets, CubitFacet );
03650       seval->replace_facets(facets);
03651     }
03652   }
03653  
03654   
03655   // build the eval tools
03656       
03657   rv = build_eval_tools(cholla_surfaces,
03658                         cholla_curves,
03659                         interp_order, use_feature_angle, 
03660                         min_dot, smooth_non_manifold,
03661                         split_surfaces );
03662     
03663   return rv;
03664 }
03665 
03666 //=============================================================================
03667 //Function: detach_surface 
03668 //Description: given a non-manifold surface in a cholla model, create a copy
03669 //             and update child entities
03670 //Notes:  assumes that chsurf_ptr has exactly 2 adjacent volumes
03671 //Author:sjowen
03672 //Date:  09/18/09
03673 //=============================================================================
03674 CubitStatus ChollaEngine::detach_surfaces(DLIList<ChollaSurface*> &chsurfs,
03675                                           DLIList<ChollaCurve*> &chcurves,
03676                                          ChollaVolume *vol_getting_new_surfs,
03677                                          std::map<ChollaSurface *, ChollaSurface *> &surf_map,
03678                                          std::map<ChollaCurve *, ChollaCurve *> &curve_map,
03679                                          std::map<ChollaPoint *, ChollaPoint *> &point_map)
03680 {
03681   CubitStatus rv = CUBIT_SUCCESS;
03682   
03683   // detach the surface from its volumes
03684 
03685   DLIList<ChollaCurve*> all_curves_in_surfs;
03686   DLIList<ChollaPoint*> all_points_in_surfs;
03687 
03688   std::multimap<ChollaCurve*, ChollaSurface*> orig_curve_to_new_surf_map;
03689   
03690   for( int i=chsurfs.size(); i--; )
03691   {
03692     ChollaSurface *chsurf_ptr = chsurfs.get_and_step();
03693     DLIList<ChollaVolume *> chvol_list;
03694     chsurf_ptr->get_volumes(chvol_list);
03695     ChollaVolume *chvol1_ptr = chvol_list.get_and_step();
03696     ChollaVolume *chvol2_ptr = chvol_list.get();
03697 
03698     if( chvol2_ptr != vol_getting_new_surfs )      
03699     {
03700       chvol1_ptr = chvol2_ptr;
03701       chvol2_ptr = vol_getting_new_surfs;      
03702     }
03703 
03704     if (NULL == chvol1_ptr || NULL == chvol2_ptr) {
03705       PRINT_ERROR("Unexpected NULL pointer for cholla volume.\n");
03706       return CUBIT_FAILURE;
03707     }
03708     assert(chvol1_ptr != chvol2_ptr);
03709 
03710     // create a copy of the non-manifold surface and attach it to volume 2
03711 
03712     ChollaSurface *newchsurf_ptr = new ChollaSurface( chsurf_ptr->get_block_id() );
03713     chollaSurfaceList.append(newchsurf_ptr);
03714     surf_map.insert(std::pair<ChollaSurface *, ChollaSurface *>(chsurf_ptr, newchsurf_ptr));
03715 
03716     chvol2_ptr->remove_surface(chsurf_ptr);
03717     chsurf_ptr->remove_volume(chvol2_ptr);
03718     chvol2_ptr->add_surface(newchsurf_ptr);
03719     newchsurf_ptr->add_volume(chvol2_ptr);
03720     
03721     chsurf_ptr->set_merge_partner(newchsurf_ptr);
03722     newchsurf_ptr->set_merge_partner(chsurf_ptr);
03723 
03724     // detach the curves  
03725     DLIList<ChollaCurve *> chcurv_list;
03726     chsurf_ptr->get_curves(chcurv_list);    
03727 
03728     for( int k=chcurv_list.size(); k--; )
03729     {
03730       ChollaCurve *chcurve = chcurv_list.get_and_step();
03731       orig_curve_to_new_surf_map.insert( std::pair<ChollaCurve*, ChollaSurface*>( chcurve, newchsurf_ptr ) );
03732     }
03733 
03734     all_curves_in_surfs += chcurv_list;
03735 
03736     DLIList<ChollaPoint*> chpt_list;
03737     chsurf_ptr->get_vertices( chpt_list );
03738     all_points_in_surfs += chpt_list;
03739   }
03740 
03741   all_curves_in_surfs.uniquify_unordered();  
03742   
03743   for(int icurv = 0; icurv < all_curves_in_surfs.size(); icurv++)
03744   {    
03745     ChollaCurve *chcurv_ptr = all_curves_in_surfs.get_and_step();
03746 
03747     std::multimap<ChollaCurve*, ChollaSurface*>::iterator iter, upper_iter;
03748     DLIList<ChollaSurface*> new_surfs;
03749 
03750     iter = orig_curve_to_new_surf_map.find( chcurv_ptr );
03751 
03752     assert( iter != orig_curve_to_new_surf_map.end() );
03753 
03754     upper_iter = orig_curve_to_new_surf_map.upper_bound( iter->first );
03755 
03756     for(; iter!=upper_iter; ++iter )
03757       new_surfs.append( iter->second );
03758 
03759     rv = detach_curve( chcurv_ptr, new_surfs, vol_getting_new_surfs, curve_map, point_map );
03760     if (rv != CUBIT_SUCCESS)
03761       return rv;  
03762   }
03763 
03764   for( int i=chcurves.size(); i--; )
03765   {
03766     DLIList<ChollaPoint*> tmp_pts = chcurves.get_and_step()->get_points();
03767     all_points_in_surfs += tmp_pts;
03768   }
03769 
03770   rv = detach_curves( chcurves, vol_getting_new_surfs, curve_map, point_map );
03771   if( rv != CUBIT_SUCCESS )
03772     return rv;
03773 
03774   //add the points in the cholla     
03775   all_points_in_surfs.uniquify_unordered();
03776   for (int ipt = 0; ipt < all_points_in_surfs.size(); ipt++)
03777   {
03778     ChollaPoint *chpt_ptr = all_points_in_surfs.get_and_step();
03779     
03780     rv = detach_point( chpt_ptr, vol_getting_new_surfs, point_map, curve_map );
03781     if (rv != CUBIT_SUCCESS)
03782       return rv;
03783   }   
03784   
03785   return rv;
03786 }
03787 
03788 CubitStatus ChollaEngine::detach_curves( DLIList<ChollaCurve*> &curves,
03789                                          ChollaVolume *detaching_volume,                                         
03790                                          std::map<ChollaCurve *, ChollaCurve *> &curve_map,
03791                                          std::map<ChollaPoint *, ChollaPoint *> &point_map )
03792 {
03793   CubitStatus rv = CUBIT_SUCCESS;
03794 
03795   DLIList<ChollaSurface*> tmp_surfs;
03796   DLIList<ChollaPoint*> points_to_detach;
03797   for( int i=curves.size(); i--; )
03798   {    
03799     ChollaCurve *tmp_curve = curves.get_and_step();    
03800 
03801     //get the surfaces in 'detaching_volume'
03802     tmp_surfs.clean_out();
03803     tmp_surfs = tmp_curve->get_surfaces();
03804     for( int k=0; k<tmp_surfs.size(); k++ )
03805     {
03806       if( !tmp_surfs[k]->is_in_volume( detaching_volume) )
03807         tmp_surfs[k] = NULL;      
03808     }
03809     tmp_surfs.remove_all_with_value(NULL);
03810 
03811     rv = detach_curve( tmp_curve, tmp_surfs, detaching_volume, curve_map, point_map );
03812     if (rv != CUBIT_SUCCESS)
03813       return rv;
03814 
03815     DLIList<ChollaPoint*> tmp_pts = tmp_curve->get_points();
03816     points_to_detach += tmp_pts;
03817   }
03818 
03819   //go through the map, setting up merge partners
03820   std::map<ChollaCurve*, ChollaCurve*>::iterator iter = curve_map.begin();
03821   for( ; iter != curve_map.end(); iter++ )
03822   {
03823     ChollaCurve *ch_curv = iter->first;
03824     ChollaCurve *new_ch_curv = iter->second;
03825 
03826     ch_curv->set_merge_partner( new_ch_curv );
03827     new_ch_curv->set_merge_partner( ch_curv );
03828   }
03829   return rv;
03830 }                                          
03831 
03832 //=============================================================================
03833 //Function: detach_curve 
03834 //Description: given a non-manifold curve in a cholla model, create a copy
03835 //             and update child entities. updates the curve_map
03836 //Author:sjowen
03837 //Date:  09/18/09
03838 //=============================================================================
03839 CubitStatus ChollaEngine::detach_curve(ChollaCurve *chcurv_ptr,
03840                                        DLIList<ChollaSurface*> &new_surfs,
03841                                        ChollaVolume *chvol2_ptr,
03842                                        std::map<ChollaCurve*, ChollaCurve*> &curve_map,
03843                                        std::map<ChollaPoint*, ChollaPoint*> &point_map )
03844 {   
03845   // create a copy of the curve on the surface and add it to volume 2  
03846 
03847   ChollaCurve *newchcurv_ptr = new ChollaCurve( chcurv_ptr->get_block_id() );
03848   chollaCurveList.append( newchcurv_ptr );
03849   curve_map.insert(std::pair<ChollaCurve *, ChollaCurve *>(chcurv_ptr, newchcurv_ptr));
03850   
03851   for( int i=new_surfs.size(); i--; )
03852   {
03853     ChollaSurface *newchsurf_ptr = new_surfs.get_and_step();
03854     newchsurf_ptr->add_curve(newchcurv_ptr);
03855     newchcurv_ptr->add_surface(newchsurf_ptr);    
03856   }
03857 
03858   // any surfaces attached to this chcurv that are in vol2 are removed and the newchcurv is added
03859   DLIList<ChollaSurface *> chcsurf_list = chcurv_ptr->get_surfaces();
03860   for (int icsurf = 0; icsurf < chcsurf_list.size(); icsurf++)
03861   {
03862     ChollaSurface *chcsurf_ptr = chcsurf_list.get_and_step();
03863 
03864     //if the adjacent surfaces are in both volumes, don't do anything
03865     if(chcsurf_ptr->is_in_volume(chvol2_ptr) )      
03866     {
03867       chcurv_ptr->remove_surface(chcsurf_ptr);
03868       chcsurf_ptr->remove_curve(chcurv_ptr);
03869       newchcurv_ptr->add_surface(chcsurf_ptr);
03870       chcsurf_ptr->add_curve_unique(newchcurv_ptr);
03871     }  
03872   } 
03873 
03874   return CUBIT_SUCCESS;
03875 }
03876 
03877 //=============================================================================
03878 //Function: detach_point 
03879 //Description: given a non-manifold point in a cholla model, create a copy
03880 //             and update connectivity. updates the point_map
03881 //Author:sjowen
03882 //Date:  09/18/09
03883 //=============================================================================
03884 CubitStatus ChollaEngine::detach_point(ChollaPoint *chpt_ptr,
03885                                        ChollaVolume *chvol2_ptr,
03886                                        std::map<ChollaPoint *, ChollaPoint *> &point_map,
03887                                        std::map<ChollaCurve *, ChollaCurve *> &curve_map )                                       
03888 { 
03889   
03890   
03891   ChollaPoint *newchpt_ptr = new ChollaPoint();
03892   chollaPointList.append( newchpt_ptr );
03893   point_map.insert(std::pair<ChollaPoint*, ChollaPoint*>(chpt_ptr, newchpt_ptr));  
03894      
03895   //find the curves that it is in
03896   DLIList<ChollaCurve *> chptcurv_list = chpt_ptr->get_curves();
03897   for (int iptcurv = 0; iptcurv < chptcurv_list.size(); iptcurv++)
03898   {
03899     ChollaCurve *chptcurv_ptr = chptcurv_list.get_and_step();
03900 
03901     // for curves that were copied (on the interface), add the new chollapoint to the new curve
03902 
03903     std::map<ChollaCurve *, ChollaCurve *>::iterator cmap_it;
03904     cmap_it = curve_map.find(chptcurv_ptr);
03905     if (cmap_it != curve_map.end())
03906     {
03907       ChollaCurve *new_chcurv_ptr = cmap_it->second;      
03908       new_chcurv_ptr->add_point(newchpt_ptr);
03909       newchpt_ptr->add_curve(new_chcurv_ptr);
03910       
03911       chpt_ptr->set_merge_partner( newchpt_ptr );
03912       newchpt_ptr->set_merge_partner( chpt_ptr );
03913     }
03914     else
03915     {
03916       // remove curve in vol 2 (not on interface) from the original point and add it to the new point
03917       
03918       if (chptcurv_ptr->is_in_volume(chvol2_ptr))
03919       {
03920         chpt_ptr->remove_curve(chptcurv_ptr);
03921         chptcurv_ptr->remove_point(chpt_ptr);
03922         newchpt_ptr->add_curve(chptcurv_ptr);
03923         chptcurv_ptr->add_point(newchpt_ptr);
03924 
03925         chpt_ptr->set_merge_partner( newchpt_ptr );
03926         newchpt_ptr->set_merge_partner( chpt_ptr );
03927       }
03928     }
03929   }
03930 
03931   return CUBIT_SUCCESS;
03932 }
03933   
03934 
03935 //=============================================================================
03936 //Function: detach_facets 
03937 //Description: detach the individual facets to create a manifold representation
03938 //Note: makes a copy of the facets on the merged surface and its child entities
03939 //      and reconnects them locally
03940 //Author:sjowen
03941 //Date:  09/10/09
03942 //=============================================================================
03943 CubitStatus ChollaEngine::detach_facets(DLIList<ChollaSurface*> &chsurfs,
03944                                         DLIList<ChollaCurve*> &chcurves,
03945                                         ChollaVolume *chvol,
03946                                         std::map<ChollaSurface *, ChollaSurface *> &surf_map,
03947                                         std::map<ChollaCurve *, ChollaCurve *> &curve_map,
03948                                         std::map<ChollaPoint *, ChollaPoint *> &point_map)
03949 {  
03950   
03951   CubitStatus rv = CUBIT_SUCCESS;
03952   
03953   std::vector<CubitPoint *> new_points;
03954   std::vector<CubitFacetEdge *> new_edges;
03955   
03956   rv = copy_facets_at_interface( chsurfs, chcurves, new_points, new_edges,
03957                                  surf_map, curve_map, point_map );
03958   if (rv != CUBIT_SUCCESS)
03959     return rv;
03960   
03961   rv = connect_facets_at_interface( chsurfs, chcurves, chvol, new_points, new_edges );
03962   if (rv != CUBIT_SUCCESS)
03963     return rv;
03964   
03965   return rv;
03966 }
03967   
03968 //=============================================================================
03969 //Function: copy_facets_at_interface 
03970 //Description: 
03971 //Author:sjowen
03972 //Date:  09/18/09
03973 //=============================================================================
03974 CubitStatus ChollaEngine::copy_facets_at_interface(DLIList<ChollaSurface*> &chsurfs,
03975                                                    DLIList<ChollaCurve*> &chcurves,
03976                                                    std::vector<CubitPoint *> &new_points,
03977                                                    std::vector<CubitFacetEdge *> &new_edges,                                                   
03978                                                    std::map<ChollaSurface *, ChollaSurface *> &surf_map,
03979                                                    std::map<ChollaCurve *, ChollaCurve *> &curve_map,
03980                                                    std::map<ChollaPoint *, ChollaPoint *> &point_map)
03981 
03982 {
03983   CubitStatus rv = CUBIT_SUCCESS;
03984   
03985   // first set the marked flags on all facets entities on this surface to -1
03986   
03987   int ifacet;
03988   DLIList<FacetEntity *> facet_list;
03989   for( int i=chsurfs.size(); i--; )
03990   {
03991     ChollaSurface *chsurf_ptr = chsurfs.get_and_step();
03992     chsurf_ptr->get_facets( facet_list );
03993   }
03994 
03995   for( int i=chcurves.size(); i--; )
03996   {
03997     DLIList<FacetEntity*> tmp_facets = chcurves.get_and_step()->get_facet_list();
03998     facet_list += tmp_facets;
03999   }
04000 
04001   FacetDataUtil::mark_facets(facet_list, FACET_ENTITY_UNINITIALIZED);
04002   
04003   // create a copy of each of the facet entities on the surface.  The marked flag in the facet will
04004   // keep track of the new entity created.  It will be a location in the new_points or new_edges
04005   // array.  Once we are finished with creating points and edges, we can create the new facets
04006   // given the references in the marked flags.
04007   
04008   // create new points
04009   
04010   rv = copy_points_at_interface(facet_list, new_points, surf_map, curve_map, point_map);
04011   if (rv != CUBIT_SUCCESS)
04012     return rv;
04013   
04014   // create new edges
04015   
04016   rv = copy_edges_at_interface(facet_list, new_points, new_edges, surf_map, curve_map, point_map);
04017   if (rv != CUBIT_SUCCESS)
04018     return rv;
04019   
04020   // create new facets
04021   
04022   DLIList<CubitFacet *> new_facets;
04023   for (ifacet = 0; ifacet<facet_list.size(); ifacet++)
04024   {
04025     FacetEntity *facet_ptr = facet_list.get_and_step();
04026     CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
04027     if( cfacet_ptr )
04028     {
04029       CubitFacetEdge *fedge, *newfedges[3];
04030       CubitFacet *newcfacet_ptr;
04031       for (int ii=0; ii<3; ii++)
04032       {
04033         fedge = cfacet_ptr->edge(ii);
04034         int idx = fedge->marked();
04035         newfedges[ii] = new_edges[idx];
04036       }
04037       newcfacet_ptr = (CubitFacet *) new CubitFacetData(newfedges[0], newfedges[1], newfedges[2]);
04038       new_facets.append( newcfacet_ptr );
04039       FacetEntity *newfacet_ptr = dynamic_cast<FacetEntity *> (newcfacet_ptr);
04040       set_new_facet_owners( 2, facet_ptr, newfacet_ptr, surf_map, curve_map, point_map );
04041     } 
04042   }
04043   
04044   // make sure facets are oriented consistently on new volume
04045   if( new_facets.size() )
04046   {
04047     CubitFacet *start_facet = new_facets.get(); 
04048     CubitBoolean do_flip = CUBIT_TRUE;
04049     int nfacets;
04050     int mydebug = 0;
04051     rv = check_facet_orientation(start_facet, do_flip, nfacets, mydebug );
04052   }
04053   
04054   return rv;
04055 }
04056 
04057 
04058 CubitStatus ChollaEngine::detach_facet_edges(DLIList<ChollaCurve*> &chcurves,
04059                                              ChollaVolume *detaching_volume,                                             
04060                                              std::map<ChollaCurve *, ChollaCurve *> &curve_map,
04061                                              std::map<ChollaPoint *, ChollaPoint *> &point_map )
04062 {  
04063   
04064   CubitStatus rv = CUBIT_SUCCESS;
04065   
04066   std::vector<CubitPoint *> new_points;
04067   std::vector<CubitFacetEdge *> new_edges;
04068   
04069   rv = copy_facet_edges_at_interface( chcurves, new_points, new_edges, curve_map, point_map );
04070   if (rv != CUBIT_SUCCESS)
04071     return rv;
04072 
04073   for (int i=chcurves.size(); i--; )
04074   {
04075     ChollaCurve *chcurv_ptr = chcurves.get_and_step();    
04076     rv = connect_points_at_interface( chcurv_ptr, detaching_volume, new_points );
04077     if (rv != CUBIT_SUCCESS)
04078       return rv;
04079     
04080     rv = connect_edges_at_interface( chcurv_ptr, detaching_volume, new_edges );
04081     if (rv != CUBIT_SUCCESS)
04082       return rv;
04083   }   
04084   
04085   return rv;
04086 }
04087 
04088 
04089 CubitStatus ChollaEngine::copy_facet_edges_at_interface(DLIList<ChollaCurve*> &chcurves,
04090                                                    std::vector<CubitPoint *> &new_points,
04091                                                    std::vector<CubitFacetEdge *> &new_edges,                                                                                                      
04092                                                    std::map<ChollaCurve *, ChollaCurve *> &curve_map,
04093                                                    std::map<ChollaPoint *, ChollaPoint *> &point_map)
04094 
04095 {
04096   CubitStatus rv = CUBIT_SUCCESS;
04097   
04098   // first set the marked flags on all facets entities to -1  
04099   DLIList<FacetEntity *> facet_list;
04100   for( int i=chcurves.size(); i--; )
04101   {
04102     ChollaCurve *chcurv_ptr = chcurves.get_and_step();
04103     DLIList<FacetEntity*> tmp_facet_list = chcurv_ptr->get_facet_list();
04104     facet_list += tmp_facet_list;
04105   }
04106 
04107   FacetDataUtil::mark_facets(facet_list, FACET_ENTITY_UNINITIALIZED);
04108   
04109   // create a copy of each of the facet entities on the surface.  The marked flag in the facet will
04110   // keep track of the new entity created.  It will be a location in the new_points or new_edges
04111   // array.  Once we are finished with creating points and edges, we can create the new facets
04112   // given the references in the marked flags.
04113   
04114   // create new points
04115 
04116   std::map<ChollaSurface *, ChollaSurface *> dummy_surf_map;
04117   
04118   rv = copy_points_at_interface(facet_list, new_points, dummy_surf_map, curve_map, point_map);
04119   if (rv != CUBIT_SUCCESS)
04120     return rv;
04121   
04122   // create new edges
04123   
04124   rv = copy_edges_at_interface(facet_list, new_points, new_edges, dummy_surf_map, curve_map, point_map);
04125   if (rv != CUBIT_SUCCESS)
04126     return rv;  
04127   
04128   return rv;
04129 }
04130 
04131 //=============================================================================
04132 //Function: copy_points_at_interface 
04133 //Description: copy the points at the interface        
04134 //Author:sjowen
04135 //Date:  09/18/09
04136 //=============================================================================
04137 CubitStatus ChollaEngine::copy_points_at_interface(DLIList<FacetEntity *> &facet_list,
04138                                                    std::vector<CubitPoint *> &new_points,                                                   
04139                                                    std::map<ChollaSurface *, ChollaSurface *> &surf_map,
04140                                                    std::map<ChollaCurve *, ChollaCurve *> &curve_map,
04141                                                    std::map<ChollaPoint *, ChollaPoint *> &point_map)
04142 {
04143   int iploc = 0;
04144   
04145   FacetEntity *fe_ptr, *newfe_ptr;
04146   CubitPoint *point_ptr, *newpoint_ptr;
04147 
04148   for (int ifacet = 0; ifacet<facet_list.size(); ifacet++)
04149   {
04150     FacetEntity *facet_ptr = facet_list.get_and_step();
04151     CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet*>(facet_ptr);
04152     if( cfacet_ptr )
04153     {     
04154       for (int ii=0; ii<3; ii++)
04155       {
04156         point_ptr = cfacet_ptr->point(ii);        
04157         if (point_ptr->marked() == FACET_ENTITY_UNINITIALIZED)
04158         {
04159           newpoint_ptr = (CubitPoint *) new CubitPointData( point_ptr->x(), point_ptr->y(), point_ptr->z() );
04160           new_points.push_back(newpoint_ptr);
04161           point_ptr->marked(iploc++);
04162           fe_ptr = dynamic_cast<FacetEntity *> (point_ptr);
04163           newfe_ptr = dynamic_cast<FacetEntity *> (newpoint_ptr);
04164           set_new_facet_owners(0, fe_ptr, newfe_ptr, surf_map, curve_map, point_map );
04165         }   
04166       } 
04167     } 
04168     else
04169     {
04170       CubitFacetEdge *cfacet_edge_ptr = dynamic_cast<CubitFacetEdge*>(facet_ptr);      
04171       for (int ii=0; ii<2; ii++)
04172       {
04173         point_ptr = cfacet_edge_ptr->point(ii);
04174         if (point_ptr->marked() == FACET_ENTITY_UNINITIALIZED)
04175         {
04176           newpoint_ptr = (CubitPoint *) new CubitPointData( point_ptr->x(), point_ptr->y(), point_ptr->z() );
04177           new_points.push_back(newpoint_ptr);
04178           point_ptr->marked(iploc++);
04179           fe_ptr = dynamic_cast<FacetEntity *> (point_ptr);
04180           newfe_ptr = dynamic_cast<FacetEntity *> (newpoint_ptr);
04181           set_new_facet_owners(0, fe_ptr, newfe_ptr, surf_map, curve_map, point_map );
04182         }   
04183       } 
04184     }
04185   }
04186   
04187   return CUBIT_SUCCESS;
04188 }
04189 
04190 //=============================================================================
04191 //Function: copy_edges_at_interface 
04192 //Description: copy the edges at the interface        
04193 //Author:sjowen
04194 //Date:  09/18/09
04195 //=============================================================================
04196 CubitStatus ChollaEngine::copy_edges_at_interface(DLIList<FacetEntity *> &facet_list,
04197                                                   std::vector<CubitPoint *> &new_points,
04198                                                   std::vector<CubitFacetEdge *> &new_edges,                                                  
04199                                                   std::map<ChollaSurface *, ChollaSurface *> &surf_map,
04200                                                   std::map<ChollaCurve *, ChollaCurve *> &curve_map,
04201                                                   std::map<ChollaPoint *, ChollaPoint *> &point_map)
04202 {
04203   int ieloc = 0;
04204   CubitFacetEdge *edge_ptr, *newedge_ptr;
04205   for (int ifacet = 0; ifacet<facet_list.size(); ifacet++)
04206   {
04207     FacetEntity *facet_ptr = facet_list.get_and_step();
04208     CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
04209     if( cfacet_ptr )
04210     {      
04211       for (int ii=0; ii<3; ii++)
04212       {
04213         edge_ptr = cfacet_ptr->edge(ii);
04214         if (edge_ptr->marked() == FACET_ENTITY_UNINITIALIZED)
04215         {
04216           CubitPoint *p0 = edge_ptr->point( 0 );
04217           CubitPoint *p1 = edge_ptr->point( 1 );
04218           int idx0 = p0->marked();
04219           int idx1 = p1->marked();
04220           CubitPoint *newp0 = new_points[idx0];
04221           CubitPoint *newp1 = new_points[idx1];
04222           newedge_ptr = (CubitFacetEdge *) new CubitFacetEdgeData( newp0, newp1 );
04223           new_edges.push_back(newedge_ptr);
04224           edge_ptr->marked(ieloc++);
04225           FacetEntity *fe_ptr = dynamic_cast<FacetEntity *> (edge_ptr);
04226           FacetEntity *newfe_ptr = dynamic_cast<FacetEntity *> (newedge_ptr);
04227           set_new_facet_owners( 1, fe_ptr, newfe_ptr, surf_map, curve_map, point_map );
04228         }  
04229       } 
04230     }
04231     else
04232     {
04233       CubitFacetEdge *edge_ptr = dynamic_cast<CubitFacetEdge*>(facet_ptr);
04234       if (edge_ptr->marked() == FACET_ENTITY_UNINITIALIZED)
04235       {
04236         CubitPoint *p0 = edge_ptr->point( 0 );
04237         CubitPoint *p1 = edge_ptr->point( 1 );
04238         int idx0 = p0->marked();
04239         int idx1 = p1->marked();
04240         CubitPoint *newp0 = new_points[idx0];
04241         CubitPoint *newp1 = new_points[idx1];
04242         newedge_ptr = (CubitFacetEdge *) new CubitFacetEdgeData( newp0, newp1 );
04243         new_edges.push_back(newedge_ptr);
04244         edge_ptr->marked(ieloc++);
04245         FacetEntity *fe_ptr = dynamic_cast<FacetEntity *> (edge_ptr);
04246         FacetEntity *newfe_ptr = dynamic_cast<FacetEntity *> (newedge_ptr);
04247         set_new_facet_owners( 1, fe_ptr, newfe_ptr, surf_map, curve_map, point_map );
04248       }
04249     }
04250   }
04251   return CUBIT_SUCCESS;
04252 }
04253 
04254 //=============================================================================
04255 //Function: connect_facets_at_interface 
04256 //Description: detach the facets from original points and edges and reattach to new copy         
04257 //Author:sjowen
04258 //Date:  09/18/09
04259 //=============================================================================
04260 CubitStatus ChollaEngine::connect_facets_at_interface(DLIList<ChollaSurface*> &chsurfs,
04261                                                       DLIList<ChollaCurve*> &chcurves,
04262                                                       ChollaVolume *chvol_ptr,
04263                                                       std::vector<CubitPoint *> &new_points,
04264                                                       std::vector<CubitFacetEdge *> &new_edges)
04265 {
04266   CubitStatus rv = CUBIT_SUCCESS;  
04267   DLIList<ChollaCurve *> chcurv_list;
04268   
04269   for( int i=chsurfs.size(); i--; )
04270   {
04271     ChollaSurface *tmp_surf = chsurfs.get_and_step();    
04272     DLIList<ChollaCurve*> tmp_curves;
04273     tmp_surf->get_curves( tmp_curves );
04274     chcurv_list += tmp_curves;
04275   }
04276 
04277   chcurv_list += chcurves;
04278   chcurv_list.uniquify_unordered();
04279 
04280   for (int icrv = 0; icrv < chcurv_list.size(); icrv++)
04281   {
04282     ChollaCurve *chcurv_ptr = chcurv_list.get_and_step();    
04283     rv = connect_points_at_interface( chcurv_ptr, chvol_ptr, new_points );
04284     if (rv != CUBIT_SUCCESS)
04285       return rv;
04286     
04287     rv = connect_edges_at_interface( chcurv_ptr, chvol_ptr, new_edges );
04288     if (rv != CUBIT_SUCCESS)
04289       return rv;
04290   } 
04291 
04292   return rv;
04293 }
04294 
04295 //=============================================================================
04296 //Function: connect_points_at_interface 
04297 //Description: find adjacent CubitFacetEdges on volume 2 that needs updating 
04298 //Notes: chcurv_ptr is a curve at the interface on the original volume
04299 //       chvol_ptr is the second volume (new (copied) entities belong to vol 2)
04300 //       This functions gets all edges attached to the original CubitPoints on the 
04301 //       original curve 'chcurv_ptr'.  If any edge is on volume 2 (the volume we are 
04302 //       splitting off) we need to update the edges on that volume to contain the
04303 //       the new CubitPoint.
04304 //Author:sjowen
04305 //Date:  09/18/09
04306 //=============================================================================
04307 CubitStatus ChollaEngine::connect_points_at_interface(ChollaCurve *chcurv_ptr,
04308                                                       ChollaVolume *chvol_ptr,
04309                                                       std::vector<CubitPoint *> &new_points)
04310 {
04311   DLIList<CubitPoint *> cp_list;
04312   chcurv_ptr->get_facet_points(cp_list, CUBIT_TRUE);
04313   for (int ip = 0; ip<cp_list.size(); ip++)
04314   {
04315     CubitPoint *cp_ptr = cp_list.get_and_step();
04316     CubitPoint *newcp_ptr = new_points[cp_ptr->marked()];
04317     
04318     // set the point into edges that are on volume 2.
04319     // Note that there is no direct reference from points to edges in our data structure 
04320     // so no need to add/remove the edge from the point
04321     
04322     DLIList<CubitFacetEdge *> pedge_list;
04323     cp_ptr->edges(pedge_list);
04324     for (int iedge=0; iedge<pedge_list.size(); iedge++)
04325     {
04326       CubitFacetEdge *edge_ptr = pedge_list.get_and_step();
04327       TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( edge_ptr );
04328       if (td_geom->is_in_volume( chvol_ptr ))
04329       {
04330         CubitPoint *p0 = edge_ptr->point(0);
04331         CubitPoint *p1 = edge_ptr->point(1);
04332         CubitFacetEdgeData *cfed_ptr = dynamic_cast<CubitFacetEdgeData *> (edge_ptr);
04333         if (p0 == cp_ptr)
04334           cfed_ptr->set_point( newcp_ptr, 0 );
04335         else if (p1 == cp_ptr)
04336           cfed_ptr->set_point( newcp_ptr, 1 );
04337       }
04338     }    
04339     
04340     // remove facets in volume 2 from the point and add the to the new point
04341     // update the point reference on the facet
04342     
04343     DLIList<CubitFacet *> pfacet_list;
04344     cp_ptr->facets(pfacet_list);
04345     for (int ifacet = 0; ifacet < pfacet_list.size(); ifacet++)
04346     {
04347       CubitFacet *facet_ptr = pfacet_list.get_and_step();
04348       TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( facet_ptr );
04349       if (td_geom->is_in_volume( chvol_ptr ))
04350       {
04351         cp_ptr->remove_facet( facet_ptr );        
04352         newcp_ptr->add_facet( facet_ptr );
04353         int ptidx = facet_ptr->point_index(cp_ptr);
04354         CubitFacetData *cfd_ptr = dynamic_cast<CubitFacetData *> (facet_ptr);
04355         cfd_ptr->set_point(newcp_ptr, ptidx);
04356       }
04357     }
04358   }
04359   return CUBIT_SUCCESS;
04360 }
04361 
04362 //=============================================================================
04363 //Function: connect_edges_at_interface 
04364 //Description: detach the facet edges from original facets and reattach to new copy         
04365 //Notes:    chcurv_ptr is a curve at the interface on the original volume
04366 //       chvol_ptr is the second volume (new (copied) entities belong to vol 2)
04367 //       This functions gets all CubitFacets attached to any CubitFacetEdges on the  
04368 //       original curve 'chcurv_ptr'.  If any facet is on volume 2 (the volume we are 
04369 //       splitting off) we need to update the edges on that facet on the new volume
04370 //       to contain the new CubitFacetEdge.
04371 //Author:sjowen
04372 //Date:  09/18/09
04373 //=============================================================================
04374 CubitStatus ChollaEngine::connect_edges_at_interface(ChollaCurve *chcurv_ptr,
04375                                                      ChollaVolume *chvol_ptr,
04376                                                      std::vector<CubitFacetEdge *> &new_edges)
04377 {
04378   DLIList<FacetEntity *> fe_list = chcurv_ptr->get_facet_list();
04379   for (int ie=0; ie<fe_list.size(); ie++)
04380   {
04381     FacetEntity *fe_ptr = fe_list.get_and_step();
04382     CubitFacetEdge *edge_ptr = dynamic_cast<CubitFacetEdge *> (fe_ptr);
04383     assert(edge_ptr != NULL);
04384     DLIList<CubitFacet *> efacet_list;
04385     edge_ptr->facets(efacet_list);
04386     for (int ifacet=0; ifacet<efacet_list.size(); ifacet++)
04387     {
04388       CubitFacet *facet_ptr = efacet_list.get_and_step();
04389       TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( facet_ptr );
04390       if (td_geom->is_in_volume( chvol_ptr ))
04391       {
04392         edge_ptr->remove_facet( facet_ptr );
04393         CubitFacetEdge *newedge_ptr = new_edges[edge_ptr->marked()];
04394         newedge_ptr->add_facet( facet_ptr );
04395         int edidx = facet_ptr->edge_index(edge_ptr);
04396         CubitFacetData *cfd_ptr = dynamic_cast<CubitFacetData *> (facet_ptr);
04397         cfd_ptr->edge(newedge_ptr, edidx);
04398       }
04399     }
04400   }
04401   return CUBIT_SUCCESS;
04402 }
04403 
04404 //=============================================================================
04405 //Function: set_new_facet_owners 
04406 //Description: update the ownenrship of the new detached facet entity based upon
04407 //             the map set up in detach_volumes
04408 //            
04409 //Author:sjowen
04410 //Date:  09/14/09
04411 //=============================================================================
04412 CubitStatus ChollaEngine::set_new_facet_owners(int type, //0, 1, or 2 based on dimension of facet entity
04413                                                FacetEntity *fe_ptr, FacetEntity *newfe_ptr,                                                
04414                                                std::map<ChollaSurface *, ChollaSurface *> &surf_map,
04415                                                std::map<ChollaCurve *, ChollaCurve *> &curve_map,
04416                                                std::map<ChollaPoint *, ChollaPoint *> &point_map )
04417 {
04418   
04419   // The tooldata on the original facet entity should tell us what cholla entity it belongs
04420   // to.  Using the map, we can then determine its new cholla entity partner.  With the
04421   // new merge partner, set the ownership of the new facet.  Note that this manages one-to-many
04422   // ownership cases where a facet lies on (or is owned by) any number of geometric entities
04423   
04424   TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( fe_ptr );
04425   TDGeomFacet::add_geom_facet(newfe_ptr, td_geom->get_block_id());
04426   
04427   // the original facet entity is owned by one or more surfaces
04428   
04429   DLIList<ChollaSurface *> surf_list;
04430   td_geom->get_cholla_surfs( surf_list );  
04431   for (int jj=0; jj<surf_list.size(); jj++)
04432   {
04433     ChollaSurface *surf_ptr = surf_list.get_and_step();
04434     std::map<ChollaSurface *, ChollaSurface *>::iterator map_it;
04435     map_it = surf_map.find( surf_ptr );
04436     assert(map_it != surf_map.end());
04437     ChollaSurface *newsurf_ptr = map_it->second;    
04438     TDGeomFacet *newtdgeom = TDGeomFacet::get_geom_facet( newfe_ptr );
04439     newtdgeom->add_cholla_surf( newsurf_ptr );
04440     
04441     // add this facet entity to the cholla surface only if this is a facet
04442     
04443     if (type == 2)
04444       newsurf_ptr->add_facet(newfe_ptr);
04445   }
04446 
04447   
04448   // the original facet entity is owned by one or more curves
04449   
04450   DLIList<ChollaCurve *> curv_list;
04451   td_geom->get_cholla_curves( curv_list );
04452   for (int jj=0; jj<curv_list.size(); jj++)
04453   {
04454     ChollaCurve *curv_ptr = curv_list.get_and_step();
04455     std::map<ChollaCurve *, ChollaCurve *>::iterator map_it, upper_iter;
04456     map_it = curve_map.find( curv_ptr );
04457     assert(map_it != curve_map.end());       
04458     ChollaCurve *newcurv_ptr = NULL;
04459     newcurv_ptr = map_it->second;
04460     
04461     TDGeomFacet *newtdgeom = TDGeomFacet::get_geom_facet( newfe_ptr );
04462     newtdgeom->add_cholla_curve( newcurv_ptr );
04463     
04464     // add this facet entity to the cholla curve only if this is a facetedge
04465     
04466     if (type == 1)
04467       newcurv_ptr->add_facet(newfe_ptr);      
04468   }
04469   
04470   // the original facet entity is owned by one or more points (vertices)
04471   
04472   DLIList<ChollaPoint *> point_list;
04473   td_geom->get_cholla_points( point_list );
04474   for (int jj=0; jj<point_list.size(); jj++)
04475   {
04476     ChollaPoint *point_ptr = point_list.get_and_step();
04477     std::map<ChollaPoint *, ChollaPoint *>::iterator map_it, upper_iter;
04478     map_it = point_map.find( point_ptr );
04479     assert(map_it != point_map.end());
04480     ChollaPoint *newchpoint_ptr = NULL;
04481     newchpoint_ptr = map_it->second;
04482   
04483     TDGeomFacet *newtdgeom = TDGeomFacet::get_geom_facet( newfe_ptr );
04484     newtdgeom->add_cholla_point( newchpoint_ptr );
04485     
04486     // add this facet entity to the cholla point only if this is a cubitpoint
04487     
04488     if (type == 0)
04489       newchpoint_ptr->add_facet(newfe_ptr);
04490   }
04491   return CUBIT_SUCCESS;
04492 
04493 }
04494 
04495 //=============================================================================
04496 //Function: verify_points_to_curves 
04497 //Description: verify the connectivity between points and curves           
04498 //Author:sjowen
04499 //Date:  09/16/09
04500 //=============================================================================
04501 CubitStatus ChollaEngine::verify_points_to_curves()
04502 {
04503   for (int ii=0; ii<chollaPointList.size(); ii++)
04504   {
04505     ChollaPoint *chpt = chollaPointList.get_and_step();
04506     if (!chpt->verify_curves())
04507     {
04508       PRINT_ERROR("ChollaPoint %d not associated with one of its curves.\n", chpt->get_id());
04509       return CUBIT_FAILURE;
04510     }
04511   }
04512   for (int ii=0; ii<chollaCurveList.size(); ii++)
04513   {
04514     ChollaCurve *chcrv = chollaCurveList.get_and_step();
04515     if (!chcrv->verify_points())
04516     {
04517       PRINT_ERROR("ChollaCurve %d not associated with one of its points.\n", chcrv->get_id());
04518       return CUBIT_FAILURE;
04519     }
04520   }
04521   return CUBIT_SUCCESS;
04522 }
04523 
04524 CubitStatus ChollaEngine::set_curve_endpoints(std::map<ChollaPoint *, ChollaPoint *> &point_map,
04525                                               std::map<ChollaCurve *, ChollaCurve *> &curve_map )
04526                                               
04527 {   
04528   DLIList<ChollaPoint*> original_chpts;
04529   DLIList<ChollaPoint*> new_chpts;
04530   DLIList<ChollaCurve*> original_chcurves;
04531   DLIList<ChollaCurve*> new_chcurves;  
04532 
04533   std::map<ChollaCurve*, ChollaCurve*>::iterator curv_iter = curve_map.begin();
04534   for(; curv_iter!=curve_map.end(); curv_iter++ )
04535   {
04536     ChollaCurve *orig_curve = curv_iter->first;
04537     ChollaCurve *new_curve = curv_iter->second;
04538 
04539     //curves
04540     original_chcurves.append( orig_curve );
04541     new_chcurves.append( new_curve );
04542     
04543     //points
04544     DLIList<ChollaPoint*> tmp_pts = orig_curve->get_points();
04545     original_chpts += tmp_pts;
04546 
04547     tmp_pts.clean_out();
04548     tmp_pts = new_curve->get_points();
04549     new_chpts += tmp_pts;
04550   }
04551 
04552   original_chpts.uniquify_unordered();
04553   original_chcurves.uniquify_unordered();
04554   new_chpts.uniquify_unordered();
04555   new_chcurves.uniquify_unordered();  
04556   
04557   std::map<ChollaPoint*,ChollaPoint*>::iterator pt_iter;
04558   for( int i=original_chpts.size(); i--; )
04559   {
04560     ChollaPoint *orig_pt = original_chpts.get_and_step();
04561 
04562     pt_iter = point_map.find( orig_pt );
04563     assert( pt_iter != point_map.end() );
04564 
04565     ChollaPoint *new_pt = pt_iter->second;    
04566     
04567     CubitPoint *new_cp = dynamic_cast<CubitPoint *>(new_pt->get_facets());
04568     CubitPoint *orig_cp = dynamic_cast<CubitPoint *>(orig_pt->get_facets());
04569 
04570     //get the curves attached to it that are in the original surface
04571     DLIList<ChollaCurve*> adj_curves = orig_pt->get_curves();
04572 
04573     for( int j=adj_curves.size(); j--; )
04574     {
04575       ChollaCurve *orig_curve = adj_curves.get_and_step();
04576 
04577       curv_iter = curve_map.find( orig_curve );
04578 
04579       //use the original curve's start/end pts as a guide to set the new curve's start/end pts
04580       if( curv_iter != curve_map.end() )
04581       {
04582         //if there is a corresponding new curve, get it
04583         ChollaCurve *new_curve_in_new_surf = curv_iter->second;
04584 
04585         CubitPoint *start, *end;
04586         orig_curve->get_ends(start, end);        
04587         assert(orig_cp != NULL);
04588         assert(start!= NULL);
04589         assert(end != NULL);
04590 
04591         if ( orig_cp == start )
04592         {
04593           new_curve_in_new_surf->set_start(new_cp);
04594         }        
04595         if ( orig_cp == end )
04596         {
04597           new_curve_in_new_surf->set_end(new_cp);
04598         }        
04599       }   
04600     }
04601   }
04602 
04603   //for each new point
04604   for( int i=new_chpts.size(); i--; )
04605   {
04606     ChollaPoint *new_point = new_chpts.get_and_step();
04607 
04608     DLIList<ChollaCurve*> curves_in_pt = new_point->get_curves();
04609 
04610     for( int k=curves_in_pt.size(); k--; )
04611     {
04612       ChollaCurve *curve_in_pt = curves_in_pt.get_and_step();
04613 
04614       //get adjacent curves that are not new (not in 'new_curves')
04615       if( !original_chcurves.is_in_list( curve_in_pt ) )
04616       {
04617         DLIList<ChollaPoint *> chpts_on_curve = curve_in_pt->get_points();        
04618         
04619         // one point on the curve assumes a periodic curve.  set both ends the same
04620 
04621         if (chpts_on_curve.size() == 1)
04622         {
04623           ChollaPoint *chpt_on_crv = chpts_on_curve.get();
04624           CubitPoint *cp = dynamic_cast<CubitPoint *> (chpt_on_crv->get_facets());
04625           curve_in_pt->set_start(cp);
04626           curve_in_pt->set_end(cp);
04627         }
04628 
04629         // standard case. one point of curve is on the interface and one is not.
04630         // In this case, one of the points has been replaced with a new point.
04631         // so one of the end point pointers are out of date.  Determine which one
04632         // and then set it.
04633 
04634         else if (chpts_on_curve.size() == 2)
04635         {
04636           ChollaPoint *chpt1_on_crv = chpts_on_curve.get_and_step();
04637           ChollaPoint *chpt2_on_crv = chpts_on_curve.get();
04638           CubitPoint *cp1 = dynamic_cast<CubitPoint *> (chpt1_on_crv->get_facets());
04639           CubitPoint *cp2 = dynamic_cast<CubitPoint *> (chpt2_on_crv->get_facets());
04640           CubitPoint *curstart, *curend;
04641           curve_in_pt->get_ends(curstart, curend);
04642           assert(curstart != NULL);
04643           assert(curend != NULL);
04644 
04645           if (curstart == cp1)
04646           {
04647             curve_in_pt->set_end(cp2);
04648           }
04649           else if (curstart == cp2)
04650           {
04651             curve_in_pt->set_end(cp1);
04652           }
04653           else if (curend == cp2)
04654           {
04655             curve_in_pt->set_start(cp1);
04656           }
04657           else if (curend == cp1)
04658           {
04659             curve_in_pt->set_start(cp2);
04660           }
04661           else
04662           {
04663             //do this by proximity
04664             double dist1 = curstart->coordinates().distance_between( cp1->coordinates() );
04665             double dist2 = curstart->coordinates().distance_between( cp2->coordinates() );
04666 
04667             if( dist1 < dist2 )
04668               curve_in_pt->set_start( cp1 );
04669             else if(dist2 < dist1 )
04670               curve_in_pt->set_start( cp2 );
04671             else
04672               assert(0);
04673           }
04674         }
04675         else
04676           assert(0);
04677       }
04678     } 
04679   }
04680   return CUBIT_SUCCESS;
04681 }
04682 
04683 // EOF
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines